Skip to content

feat(bus): close-experiment — terminal state for a proposal/run that will never produce a result - #181

Open
asachs01 wants to merge 1 commit into
mainfrom
fix/experiment-terminal-states
Open

asachs01 wants to merge 1 commit into
mainfrom
fix/experiment-terminal-states

Conversation

@asachs01

@asachs01 asachs01 commented Sep 9, 2026

Copy link
Copy Markdown

Summary

  • Adds cortextos bus close-experiment <id> "<reason>", a new terminal status: 'closed' reachable from proposed or running, distinct from evaluate-experiment's keep/discard (which always requires a real measurement).
  • Fixes task_1788276326374_26114110 (high priority, recurring — proposed-forever records after a declined approval, 3 confirmed live instances) and converges with task_1788228728494_04553223 (running experiment with no baseline_value, structurally unevaluatable, no repair path) per the 09-05 theta-wave note recommending both land as one CLI change.
  • New fields: closed_reason (required, free-text, stored verbatim) and closed_at (kept separate from completed_at, which stays null on a closed record since it never produced a real result). decision is deliberately untouched — closing is never a keep/discard verdict.
  • Considered and rejected the fuller MPAC-style taxonomy (REJECTED/ABANDONED/SUPERSEDED as distinct statuses) proposed in the task notes — a single status + free-text reason covers every concrete case in the corpus without a fixed enum needing its own maintenance.
  • Docs updated in the three actively-deployed template copies (agent, analyst, orchestrator). The codex/opencode/community fork copies of bus-reference/SKILL.md already carry independent drift from these three (verified via diff) and are left for a separate sync pass rather than hand-reconciling ~7 divergent files in this PR.
  • Small dashboard tweak: statusBadge() in the experiments page now has an explicit closed entry (previously would've fallen back to the generic unmapped-status badge, which is harmless but the mapped one is clearer).

Test plan

  • npm run typecheck — clean
  • npm run build (tsup) — clean
  • npx vitest run tests/sprint3-experiments.test.ts — 64/64 passing (8 new tests covering: close from proposed, close a running experiment with no baseline that evaluate-experiment refuses, active.json cleanup on close, active.json NOT disturbed when closing a different experiment, refuse double-close, refuse closing a completed experiment, not-found error, status filter)
  • npx vitest run tests/unit/cli/bus-list-experiments-format.test.ts — 5/5 passing
  • Full npx vitest run — 2589 passing / 2 failing / 51 skipped across 165 files. The 2 failures (watcher-ingests-real-events.test.ts) and 6 error-only files (better-sqlite3/next/server module-not-found) are pre-existing to this fresh worktree — dashboard/ is a separately-installed package (no root npm workspace) and its node_modules was never populated here; confirmed via ls node_modules/better-sqlite3 / ls node_modules/next (both absent) before touching any test file. None of the 8 failing files are in this PR's diff.

🤖 Generated with Claude Code


Task-ID: task_1788276326374_26114110
Agent: dev


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…will never produce a result

A proposed experiment whose linked approval was declined, or a running
experiment created before --baseline was required (baseline_value: null),
had no way to reach a terminal state without either running something
already rejected or being permanently refused by evaluate-experiment's
baseline guard. Every future fleet scan of proposed-but-never-run
experiments re-flagged the same records indefinitely (task_1788276326374_26114110,
recurrence bumped it to high priority; task_1788228728494_04553223 for the
orphaned-running case).

Adds status: 'closed', reachable from 'proposed' or 'running', refusing on
an already-completed or already-closed record. Reason is required and
stored in the new closed_reason field; closed_at is kept separate from
completed_at since a closed experiment never produced a real result.
Deliberately doesn't touch `decision` — closing is never a keep/discard
verdict.

Considered and rejected the fuller MPAC-style terminal-state taxonomy
(REJECTED/ABANDONED/SUPERSEDED) proposed in the task's theta-wave notes —
a single status + free-text reason covers every concrete case seen without
a fixed enum needing its own maintenance.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 73c080ab-2316-4d7e-94cc-5d43d62418ca


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.

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.

1 participant