Bound ai_runs saves and redact every stored column
CI / ci (push) Successful in 1m37s
CI / ci (pull_request) Successful in 1m38s

- runOnce no longer saves with an unbounded context.WithoutCancel. Work
  that ended in time must write its row before the skill deadline; if the
  writer is not free by then the run fails with llm.ErrTimeout and its
  row records the timeout. A failed run's row is written within
  runSaveTimeout (5s); if that write fails too, the run returns both
  errors and no row is stored. A stored row's status now always matches
  what the caller received. The row ID is fixed per run, so a second
  save attempt can never add a second row.
- skill, provider and model are redacted with the same redactor as the
  bodies; TestRunRowsHoldNoSecrets seeds the API key and a webhook URL
  into the model value.
- guard_test: "row saved late" now expects a provider_error timeout row;
  new "writer blocked" case proves Run returns ErrTimeout within the
  bound and stores no row.
- Purge doc and ARCHITECTURE: the daily purge is owned by Feature 20's
  scheduler, which must call harness.Purge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 10:52:42 -04:00
co-authored by Claude Opus 5.5
parent a8b0c7894f
commit db0835342f
5 changed files with 109 additions and 30 deletions
+6
View File
@@ -276,6 +276,9 @@ func TestRunRowsHoldNoSecrets(t *testing.T) {
return &f, nil
}
cfg.Persona = "Our kitchen. " + leaky
// A model value can hold a credential too: every stored
// column is redacted, not only the bodies.
cfg.Settings.Model = "model-" + seededKey + " " + seededWebhook
_, _ = Run(context.Background(), cfg, echoSkill{}, "week-1", echoInput{Word: "tacos " + seededWebhook})
assertCalls(t, &f, len(script))
@@ -289,6 +292,9 @@ func TestRunRowsHoldNoSecrets(t *testing.T) {
t.Errorf("stored row holds %q:\n%s", s, text)
}
}
if want := "model-" + redactionMarker + " " + redactionMarker; rows[0].Model != want {
t.Errorf("stored model = %q, want %q", rows[0].Model, want)
}
for _, kept := range []string{"Our kitchen.", "Repeat: tacos", redactionMarker} {
if !strings.Contains(text, kept) {
t.Errorf("stored row lacks %q:\n%s", kept, text)