Skip to content

Add run records: per-user execution history off the shared D1 writer - #955

Merged
kody-bot merged 26 commits into
mainfrom
cursor/run-records-primitive-8a57
Jul 26, 2026
Merged

kody-bot merged 26 commits into
mainfrom
cursor/run-records-primitive-8a57

Conversation

@kentcdodds

Copy link
Copy Markdown
Member

Users could not see why their own jobs, apps, or executions failed — that detail lived only in Workers logs and Sentry. Meanwhile Sentry was collecting user-code errors nobody at Kody can act on.

This adds one run records primitive that both halves needed, and consolidates the four private run logs that had grown up around it.

Why one primitive

"Something ran, here is the status and error" was implemented seven times, in whatever shape each feature needed. A package-defined job execution wrote a jobs.run_history_json entry, a package_runtime_runs row, and an Analytics Engine datapoint — three records of one event, three retention policies, two readable surfaces, no shared shape.

Two rules decide what merged:

  • State is not history. Entity rows keep current state; run records keep history. The clearest violation was entitlements computing how many services are running by scanning a history table, with a 24h window bolted on because evicted rows stranded in running forever. That is now a real state table.
  • History is not a ledger. package_invocations and stripe_webhook_events are correctness mechanisms and stay in D1 untouched.

Why not D1

Run records are per-event writes, and D1 is a single shared writer. This repeats the decision already made for usage metering, which record-usage.ts states explicitly: "a per-event D1 upsert would serialize every metered request on D1's single writer." That decision lived only in a code comment, which is why package_runtime_runs was later built in D1 doing exactly what the comment forbids. It is now an invariant in primitives.yaml.

Records live in a per-user RunLog Durable Object. Each user's history is its own SQLite with no cross-tenant contention, there is no user_id column because the DO is the user, and retention self-prunes per user instead of an hourly cron scanning a shared table.

What users get

/account/activity — failures first, with the captured console logs, filters by surface and status, and cursor pagination. Agents get the same data via run_list / run_get / run_summary.

Coverage gaps closed: ad-hoc execute, standalone kody.json jobs, and inline workflows recorded nothing before because the old store required a package_id.

account_activity_shows_failed_runs_with_logs_and_filters.mp4

Run detail with captured console logs

Two bugs found while verifying

  • Sandbox console capture never worked. The shim was a const console inside evaluate(), but user code is a separate imported module, so it resolved the global instead. Every execution returned logs: []. Pre-existing on main (reproduced there); fixed the same way fetch was already handled. Without this the Activity page would have shipped showing "No log lines were captured" for every run.
  • Activation milestones would have silently stopped. recordSuccessfulPackageRun counted successes from package_runtime_runs, which this PR stops writing, so package_activated became unreachable. Now backed by a durable counter.

Reviewing this

Start with packages/worker/src/run-records/types.ts — it is the contract everything else codes against. Then service.ts (worker API), run-log-do.ts (the store).

Nothing is dropped. package_runtime_runs, package_runtime_logs, jobs.run_history_json, and webhook_deliveries stop being written but remain in place, so this is revertible. A follow-up drops them; the legacy read arms are commented as such.

Deliberately out of scope, and documented rather than left ambiguous: run records are not covered by DR backup (observability data with 30-day self-retention), and cross-user error queries are now a sampled Analytics Engine question rather than a D1 scan. Sentry keeps the errors Kody must act on, the DO keeps the errors the user must act on.

Verification

npm run validate green: 1405 tests across 420 files, 21 Playwright E2E, MCP E2E, plus primitives:check and migrations:check.

Manually verified end to end against a real MCP session: two genuinely failing execute calls produced run records with their console output, and a successful one correctly persisted nothing.

Two independent review passes (hard-to-reverse/security, and performance) ran before this was opened; their blockers are fixed in-branch.

System recap — adds a new primitive (high risk)

Mode: recap · Base: main @ 6fed00ac · Head: 59a1e511

Classification: adds — introduces the run-records primitive and two new invariants; several existing primitives change shape around it.

Primitives touched

Primitive Group Impact
run-records storage adds — per-user RunLog DO, runs capability domain
jobs assistant extends — stops writing run_history_json; keeps last_run_* as state
webhooks assistant extends — deliveries become run records instead of webhook_deliveries
workflows assistant extends — records once (was twice); UserCodeError narrowed
entitlements auth extends — concurrency from package_service_states, not history
package-apps assistant extends — logs persisted and redacted; finish off the response path
package-services assistant extends — projects lifecycle state to D1
capabilities-execute runtime extends — sandbox console capture fixed; run recording wired
capability-registry assistant extends — runs domain added, package_debug_* removed
app-ui surfaces extends — /account/activity
account-export assistant extends — run_records export section, DO purge on deletion
usage-metering storage extends — activation counter replaces history scan
d1-app-db storage extends — migrations 0095, 0096
scheduled-cron surfaces extends — legacy lanes drain only; new records self-prune

System map

Execution surfaces stop writing private D1 run logs and report through one per-user Durable Object, which the UI and capability graph read.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
	runRecords["run-records<br/>Run records"]:::added
	capabilitiesExecute["capabilities-execute<br/>Capabilities execute runtime"]:::extended
	jobs["jobs<br/>Scheduled jobs"]:::extended
	webhooks["webhooks<br/>Inbound webhooks"]:::extended
	workflows["workflows<br/>Workflows"]:::extended
	packageApps["package-apps<br/>Package apps"]:::extended
	appUi["app-ui<br/>Browser app"]:::extended
	capabilityRegistry["capability-registry<br/>Capability registry"]:::extended
	entitlements["entitlements<br/>Plans & entitlements"]:::extended
	accountExport["account-export<br/>Account data export"]:::extended
	d1AppDb["d1-app-db<br/>D1 app database"]:::extended
	usageMetering["usage-metering<br/>Usage metering"]:::extended
	capabilitiesExecute -->|"surface execute, failures only"| runRecords
	jobs -->|"surface job incl. standalone kody.json"| runRecords
	webhooks -->|"surface webhook, one-call record"| runRecords
	workflows -->|"surface workflow, one record per run"| runRecords
	packageApps -->|"redacted logs via waitUntil"| runRecords
	appUi -->|"/account/activity list + logs"| runRecords
	capabilityRegistry -->|"run_list / run_get / run_summary"| runRecords
	runRecords -->|"activation counter on success"| usageMetering
	accountExport -->|"run_records section + DO purge"| runRecords
	entitlements -->|"0095 package_service_states"| d1AppDb
	usageMetering -->|"0096 user_package_run_successes"| d1AppDb
	classDef touched fill:#1a7f37,color:#fff
	classDef extended fill:#9a6700,color:#fff
	classDef added fill:#cf222e,color:#fff
	classDef untouched fill:#57606a,color:#fff
Loading

Before / after

Concern Before After
Store D1 package_runtime_runs (shared writer) per-user RunLog DO SQLite
Hot path awaited INSERT before execution non-blocking begin, upserting finish
Coverage package surfaces only all ten surfaces
Retention hourly cron over a shared table in-DO, self-terminating alarm
Storage quota counted against the user excluded
UI none /account/activity

Invariants

Adds two, both previously unwritten decisions:

  • state-vs-history — entity rows hold current state; run records hold history. Never derive state from history.
  • no-per-event-shared-writes — per-event writes go to Analytics Engine or per-user DO SQLite, never the shared D1 writer.

per-user-isolation is strengthened rather than touched: the store is keyed by user id with no user_id column to filter on.

Open in Web Open in Cursor 

cursoragent and others added 24 commits July 26, 2026 03:00
Replace package_runtime_runs inference with an authoritative
package_service_states D1 projection written on service lifecycle
transitions and heartbeaten while running, so concurrency quota is not
derived from stranded history rows and survives the runs-table move.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Introduce the run-records primitive: a user-scoped SQLite Durable Object
for execution history, a never-blocking begin/finish service API with
eager vs on-failure persistence, retention inside the DO, and workers
runtime coverage for the shared contract.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Stop reporting sandbox/workflow user-code throws as platform bugs by
throwing UserCodeError at known boundaries and dropping it in beforeSend,
while keeping string-match filters as backstops. Also record inline and
package workflow runs with workflowId via begin/finishRunRecord.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Surface per-user run records in a failures-first Activity page with
status/surface filters, summary counts, detail logs, and cursor pagination.
Repoint Jobs recent runs to listRunRecords and link each run into Activity.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Include run records in account export/deletion, union RunLog storage ids
with legacy D1 sources so StorageRunner buckets are not leaked, leave DR
explicitly out of scope for observability data, and keep legacy D1
retention lanes draining old package_runtime_* rows.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Add a runs capability domain (run_list, run_get, run_summary) over the
per-user RunLog DO, delete package_debug_* capabilities, and repoint
job_get recent_runs plus webhook_delivery_list onto listRunRecords.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Webhook run records store camelCase httpStatus/payloadBytes without an
outcome field; map 4xx errors to rejected and other failures to failed.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Delete package-runtime-debug D1 writers and wire execute, jobs, apps,
services, retrievers, invocations, and webhooks through beginRunRecord/
finishRunRecord. Close coverage gaps for ad-hoc execute (on-failure) and
standalone kody.json jobs, pass package-app console logs through the
runtime bridge, stop writing jobs.run_history_json, and replace
webhook_deliveries inserts with webhook run records.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
The ledger test hardcoded prefix 0095, which collides with the new
package_service_states migration and would break on every future
migration. Derive both the expected prefixes and the monotonic-addition
fixture name from the live ledger instead.

Admin usage stub now answers the package_service_states count query
that replaced the package_runtime_runs history scan.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Add the architecture doc and primitives map entry for per-user RunLog
history, garden stale storage/entitlement/webhook docs, and publish
end-user Activity guidance.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Webhook delivery history now comes from run records, so the D1-backed
listWebhookDeliveries* readers were unreachable. Register the RunLog DO
in the user-owned surface registry so the out-of-band DO inventory stays
complete, and point the package-app crash page at Account -> Activity.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Track packageSecrets.get values on the runtime bridge, redact logs and
errors at packageRuntimeRunFinish before persistence, and schedule finish
via waitUntil so app_fetch/app_realtime responses are not blocked.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Keep finish cheap with a stored run counter and every-Nth/alarm prune,
reconcile stale running rows, add recordRunRecord plus finish waitUntil,
and support name list filters with covering indexes.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
The allowlist still named the deleted package-runtime-debug warnings, so the
run-record and activation warnings that replaced them escaped the console spy
and turned an incidental missing-table warning into a failed package run.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Pin that an unhandled surface yields a null handle and that a failing
activation milestone write still leaves the observed run successful.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Record inbound webhook deliveries with one recordRunRecord RPC (real
startedAt + waitUntil off the response path) and always store an explicit
outcome. Push webhook name filtering into listRunRecords so delivery list
no longer under-reports when a package has multiple webhooks.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
…rror

Keep the outer workflow begin/finish (workflowId + pre-invocation failures)
and have resolveInvocationRuntimeSurface return null for package-workflow so
the inner invoke does not open a second row. Only mark sandbox/4xx package
workflow failures as UserCodeError; known infrastructure codes and other 5xx
stay ordinary Errors for Sentry.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
…ervices

Activation now increments a durable per-package success counter instead of
counting retention-pruned history, so package_activated can still be awarded.
Account deletion/export enumerate package services from package_service_states
(unioned with legacy runs), and PackageServiceInstance projects state on restore
so the inventory converges after upgrade.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Self-terminate the RunLog alarm when nothing is due, skip alarm storage on
hot finishes via in-isolate caches, and skip DDL on schema-version matches
so parallel workers tests are not dominated by per-finish getAlarm/setAlarm.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Subscription dispatch was awaiting per-run finish writes on the
single-threaded RunLog DO, which serialized concurrent package
handlers and timed out under the full workers suite. Thread optional
waitUntil through runBundledModuleWithRegistry and the invocation
callers that have an ExecutionContext so observability stays off the
critical path.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Each RunLog Durable Object RPC costs roughly 400ms in the vitest workers
pool while the production finish path measures ~0.4ms, so this suite was
timing out under full-validate contention. The previous explicit 15s cap
was also below the 20s CI default. Budget it like the other DO-heavy
suites, pipeline independent seeds, and drop clears that were redundant
because every test mints a fresh user id.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
User modules resolve console from globalThis, so a lexical const
console shim in evaluate() never ran. Override globalThis.console
like fetch, restore it in finally for worker reuse, and cover the
capture path end to end through RunLog.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
The sandbox flattens console output to strings and encodes the level as a
leading marker, so every persisted line landed as level 'log'. The
Activity page renders that level in a gutter and colours by it, so warn
and error lines were indistinguishable from ordinary output. Parse the
marker back into the structured level the schema already supports.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Package subscription dispatch boots the real Worker Loader sandbox, which
costs seconds per run, while the shared default is 5s locally. These
suites flaked under a loaded validate even though the production write
path measures well under a millisecond. Budget them like the other
sandbox-executing suites.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented Jul 26, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 127 files, which is 27 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 627a9589-9411-4cc2-bc78-77b271219b90

📥 Commits

Reviewing files that changed from the base of the PR and between 7612859 and 26a1a44.

📒 Files selected for processing (132)
  • docs/contributing/architecture/data-storage.md
  • docs/contributing/architecture/entitlements.md
  • docs/contributing/architecture/index.md
  • docs/contributing/architecture/primitives.yaml
  • docs/contributing/architecture/run-records.md
  • docs/contributing/architecture/webhooks.md
  • docs/contributing/disaster-recovery.md
  • docs/use/activity.md
  • docs/use/index.md
  • docs/use/privacy.md
  • docs/use/troubleshooting.md
  • docs/use/webhooks.md
  • e2e/account-activity.spec.ts
  • packages/worker/client/routes/account-activity.tsx
  • packages/worker/client/routes/account-jobs.tsx
  • packages/worker/client/routes/account-management-components.tsx
  • packages/worker/client/routes/index.tsx
  • packages/worker/migrations/0095-package-service-states.sql
  • packages/worker/migrations/0096-user-package-run-successes.sql
  • packages/worker/src/app/account-activity-data.node.test.ts
  • packages/worker/src/app/account-activity-data.ts
  • packages/worker/src/app/account-data-targets.ts
  • packages/worker/src/app/account-deletion.node.test.ts
  • packages/worker/src/app/account-deletion.ts
  • packages/worker/src/app/account-export.node.test.ts
  • packages/worker/src/app/account-export.ts
  • packages/worker/src/app/account-jobs-data.ts
  • packages/worker/src/app/account-retention-dispositions.node.test.ts
  • packages/worker/src/app/account-retention-dispositions.ts
  • packages/worker/src/app/account-user-owned-surfaces.ts
  • packages/worker/src/app/admin-user-usage-data.node.test.ts
  • packages/worker/src/app/document-head.ts
  • packages/worker/src/app/handlers/account-activity.ts
  • packages/worker/src/app/handlers/account-jobs.node.test.ts
  • packages/worker/src/app/handlers/package-app.ts
  • packages/worker/src/app/loader-data.ts
  • packages/worker/src/app/retention.ts
  • packages/worker/src/app/router.ts
  • packages/worker/src/app/routes.ts
  • packages/worker/src/email/delivery-queue.node.test.ts
  • packages/worker/src/email/delivery-queue.ts
  • packages/worker/src/email/inbound-effects.ts
  • packages/worker/src/email/inbound.ts
  • packages/worker/src/email/inbound.workers.test.ts
  • packages/worker/src/email/package-subscriptions.ts
  • packages/worker/src/email/system-email-subscriptions.workers.test.ts
  • packages/worker/src/entitlements/entitlements.node.test.ts
  • packages/worker/src/entitlements/package-service-states.workers.test.ts
  • packages/worker/src/entitlements/service.ts
  • packages/worker/src/entitlements/test-schema.ts
  • packages/worker/src/index.ts
  • packages/worker/src/jobs/job-reindex.node.test.ts
  • packages/worker/src/jobs/manager-do.node.test.ts
  • packages/worker/src/jobs/manager-do.ts
  • packages/worker/src/jobs/process-due-jobs.node.test.ts
  • packages/worker/src/jobs/process-due-jobs.ts
  • packages/worker/src/jobs/repo.ts
  • packages/worker/src/jobs/service.node.test.ts
  • packages/worker/src/jobs/service.ts
  • packages/worker/src/jobs/types.ts
  • packages/worker/src/mcp/capabilities/builtin-domains.ts
  • packages/worker/src/mcp/capabilities/domain-metadata.ts
  • packages/worker/src/mcp/capabilities/jobs/job-get.ts
  • packages/worker/src/mcp/capabilities/jobs/job-list.ts
  • packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts
  • packages/worker/src/mcp/capabilities/jobs/shared.ts
  • packages/worker/src/mcp/capabilities/packages/domain.ts
  • packages/worker/src/mcp/capabilities/packages/package-debug-get-run.ts
  • packages/worker/src/mcp/capabilities/packages/package-debug-list-runs.ts
  • packages/worker/src/mcp/capabilities/packages/package-debug-shared.ts
  • packages/worker/src/mcp/capabilities/runs/domain.ts
  • packages/worker/src/mcp/capabilities/runs/run-get.ts
  • packages/worker/src/mcp/capabilities/runs/run-list.ts
  • packages/worker/src/mcp/capabilities/runs/run-summary.ts
  • packages/worker/src/mcp/capabilities/runs/runs.workers.test.ts
  • packages/worker/src/mcp/capabilities/runs/shared.ts
  • packages/worker/src/mcp/capabilities/services/service-start.node.test.ts
  • packages/worker/src/mcp/capabilities/webhooks/webhook-capabilities.node.test.ts
  • packages/worker/src/mcp/capabilities/webhooks/webhook-delivery-list.ts
  • packages/worker/src/mcp/execute-console-capture.workers.test.ts
  • packages/worker/src/mcp/executor.ts
  • packages/worker/src/mcp/observability.node.test.ts
  • packages/worker/src/mcp/observability.ts
  • packages/worker/src/mcp/run-kody-registry.node.test.ts
  • packages/worker/src/mcp/run-kody-registry.ts
  • packages/worker/src/mcp/secrets/execution-secret-redactor.ts
  • packages/worker/src/mcp/tools/execute.node.test.ts
  • packages/worker/src/mcp/tools/execute.ts
  • packages/worker/src/package-invocations/admin-package-subscriptions.ts
  • packages/worker/src/package-invocations/common.node.test.ts
  • packages/worker/src/package-invocations/common.ts
  • packages/worker/src/package-invocations/http-invoke.ts
  • packages/worker/src/package-invocations/http.ts
  • packages/worker/src/package-invocations/http.workers.test.ts
  • packages/worker/src/package-invocations/idempotency.ts
  • packages/worker/src/package-invocations/idempotent-module-invocation.ts
  • packages/worker/src/package-invocations/runtime-tool-factories.ts
  • packages/worker/src/package-invocations/service.node.test.ts
  • packages/worker/src/package-invocations/service.ts
  • packages/worker/src/package-invocations/subscription-dispatch.ts
  • packages/worker/src/package-retrievers/service.node.test.ts
  • packages/worker/src/package-retrievers/service.ts
  • packages/worker/src/package-runtime/package-app.node.test.ts
  • packages/worker/src/package-runtime/package-app.ts
  • packages/worker/src/package-runtime/package-runtime-debug.node.test.ts
  • packages/worker/src/package-runtime/package-runtime-debug.ts
  • packages/worker/src/package-runtime/package-service.node.test.ts
  • packages/worker/src/package-runtime/package-service.ts
  • packages/worker/src/package-runtime/package-workflows.node.test.ts
  • packages/worker/src/package-runtime/package-workflows.ts
  • packages/worker/src/platform-feedback/platform-feedback-subscriptions.workers.test.ts
  • packages/worker/src/run-records/run-log-do.ts
  • packages/worker/src/run-records/run-records.workers.test.ts
  • packages/worker/src/run-records/service.ts
  • packages/worker/src/run-records/types.ts
  • packages/worker/src/sentry-options.node.test.ts
  • packages/worker/src/sentry-options.ts
  • packages/worker/src/test-support/incidental-runtime-warnings.ts
  • packages/worker/src/usage/activation.node.test.ts
  • packages/worker/src/usage/activation.ts
  • packages/worker/src/user-code-error.node.test.ts
  • packages/worker/src/user-code-error.ts
  • packages/worker/src/user-scoped-durable-object-name.ts
  • packages/worker/src/webhooks/http.ts
  • packages/worker/src/webhooks/http.workers.test.ts
  • packages/worker/src/webhooks/repo.ts
  • packages/worker/src/webhooks/service.node.test.ts
  • packages/worker/src/webhooks/service.ts
  • packages/worker/worker-configuration.d.ts
  • packages/worker/wrangler.jsonc
  • tools/check-migrations.node.test.ts
  • tools/migration-ledger.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/run-records-primitive-8a57

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kody-bot
kody-bot marked this pull request as ready for review July 26, 2026 07:51
@github-actions

github-actions Bot commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-955.kody-a99.workers.dev

Worker: kody-pr-955
D1: kody-pr-955-db
KV: kody-pr-955-oauth-kv

Mocks:

Clear the idle-confirmed fast path on every start/finish write and schedule
the soonest age/stale due-time so warm low-traffic RunLogs still self-prune
without scanning pending work on every finish.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
status: statusFilterToRunStatus(statusFilter),
surface: surfaceFilterToRunSurface(surfaceFilter),
since,
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Activity list capped seven days

Medium Severity

loadAccountActivityData applies the same seven-day since window to listRunRecords as to the summary tiles, so /account/activity only lists runs from the last week even though the page states records are kept about thirty days and supports cursor pagination. Runs between seven and thirty days old can still load by direct id via getRunRecord, but they never appear in the sidebar list or “load more” pages.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ab1e78f. Configure here.

Align count eviction with age prune by deleting only success then error
rows. Stale running still converges because reconcile demotes them to
error before the cap pass.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

There are 3 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 26a1a44. Configure here.

status: run.status,
durationMs: run.durationMs ?? 0,
error: run.errorMessage,
}))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running jobs show fake finish time

Medium Severity

After recent runs come from RunLog, in-flight job rows can have a null finishedAt. Mapping null to startedAt makes the Jobs table “Finished” column show the start time while status is still running, which reads as a completed run at a glance.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 26a1a44. Configure here.

status: run.status,
durationMs: run.durationMs ?? 0,
error: run.errorMessage,
}))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running jobs show zero duration

Low Severity

Recent runs from RunLog leave durationMs null while status is running. Coercing null to 0 makes the Jobs duration column show 0 ms for active executions instead of an in-progress or unknown duration.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 26a1a44. Configure here.

@kody-bot
kody-bot merged commit 0461410 into main Jul 26, 2026
10 checks passed
@kody-bot
kody-bot deleted the cursor/run-records-primitive-8a57 branch July 26, 2026 08:40
cursor Bot pushed a commit that referenced this pull request Jul 26, 2026
Repoint DR inventory, account deletion, and account export off
package_runtime_runs onto user_storage_buckets plus manifest/state
service enumeration so post-#955 buckets and idle services stay
discoverable.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
kody-bot pushed a commit that referenced this pull request Jul 26, 2026
…m run history (#965)

* feat(storage): track user storage bucket ownership in D1

Add user_storage_buckets as authoritative state (with a one-time
package_runtime_runs backfill), register buckets on StorageRunner
mutators with isolate-local dedupe, and cover the table in account
export/deletion targets.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(account): stop enumerating storage and services from run history

Repoint DR inventory, account deletion, and account export off
package_runtime_runs onto user_storage_buckets plus manifest/state
service enumeration so post-#955 buckets and idle services stay
discoverable.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(account-export): keep discovery paging on D1 keyset SQL

durable_object_summaries pages again over user_storage_buckets and
entity/state tables without per-page manifest fetches. Manifest-inclusive
enumeration stays on deletion and one-shot full export inventory.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(account-export): align discovery counts and cheap section probes

Make storage_runners counts match D1 discovery paging, probe ownership
and package-service lookups without full inventory rebuilds, batch the
service-stage base check, and surface manifest degradation in deletion
warnings so incomplete purges cannot look clean.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(account-export): treat malformed service storage ids as not found

Guard decodeURIComponent on caller-supplied service: storage ids so a
bare % returns the normal not-found path instead of throwing URIError.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(storage): do not register ownership on clearStorage

Account deletion clears StorageRunner DOs then deletes user_storage_buckets.
Registering on clearStorage could fire-and-forget an upsert that recreates
rows for an already-deleted user. Registration stays on genuine write paths.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(account): restore RunLog storage ids and legacy service deletion

Union listRunRecordStorageIds into export count, ownership probes, and
discovery paging so RunLog-only buckets stay exportable and count≡paging.
Restore package_runtime_runs on the deletion path only (issue #956), and
dedupe package-manifest loads within a single inventory request.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants