Skip to content

engine(experiment): the series, the locks, and the surfaces - #1070

Merged
leeovery merged 13 commits into
mainfrom
feat/experiment-engine
Sep 1, 2026
Merged

engine(experiment): the series, the locks, and the surfaces#1070
leeovery merged 13 commits into
mainfrom
feat/experiment-engine

Conversation

@leeovery

@leeovery leeovery commented Aug 31, 2026

Copy link
Copy Markdown
Owner

PR1 of the experiment-phase stack, built fresh against design/experiment-phase.md (#1057). Replaces the engine layers of the closed #1058/#1059.

What this is

The engine layer of the experiment phase: an umbrella tool research and discussion use — a conversation hits a question talking cannot settle and hands it to the laboratory, which always begins in fresh context. This PR is state, verbs, and render surfaces only; the skills (PR2), the spawn offer in the conversational phases (PR3), and absorption/docs/prose cases (PR4) follow.

The model, engine-side

  • Series records: phases.experiment.items.{topic}.experiments.{id} — lifecycle conceived → designed → approved → running → concluded | abandoned, with the id shape (E{n}, sub-experiments E{n}.{m}) single-homed in the kernel. The phase item is derived bookkeeping over the rows: the spawn opens it, the last record's terminal transition closes it, and topic start/complete/reopen refuse it outright.
  • The verb family: experiment create (the spawn — id allocation, the problem file's directory, and the lock; or --parent for a split under a running record), advance (the mechanical steps), approve (the freeze — deliberately its own verb, never a step a loop drifts past), conclude --verdict, abandon --reason.
  • The lock: awaiting_experiments on the spawning item, research and discussion identically — a locked conversation cannot complete until the wait releases. Terminal transitions release it: a conclusion flags the holder for its next entry and runs the one-hop flag downstream; an abandonment releases with no downstream hop; the epic cancel releases behind a confirm gate (--cascade).
  • Splits: E{n}.{m} under a running parent, records nested in the parent's directory; no lock moves — the parent's verdict synthesises them and releases once.
  • Surfaces: the series register (render surface off the manifest, never a hand-maintained file; terminal rows carry verdict/reason on the line), the approval gate (commands first, prompt last), per-experiment epic menu entries (Enter E1 {slug} — *{Topic} · experiment*) that lead the menu and outrank every other recommendation, and the awaiting E{n} cues on the map and dashboards.
  • The staleness hop walks past the series slot unconditionally — a reconcile flag must land where an entry flow can clear it, and the series item has none; its only flag edges are the wait release (the holder) and a parent conclusion (downstream).
  • Boundaries: experiments never touch the knowledge base, triage, or discovery routing — no indexing, no queues, no map legs. Presence: the phase joins the source phases (a live experiment defers the epic-wide analyses); commits scope to the record directory.

Tests

test-engine-experiment.cjs (36 tests: spawn symmetry, the walk, the freeze, terminal refusals, splits, release/flag edges with abandon-vs-conclude pinned both ways, derived item status, cancel cascade, the hop walk incl. never-reaching-spec, field guards, presence beats); two pipeline-simulation scenarios (epic: both spawn phases, menu entries, freeze, split, verdict, series continuation, abandonment, cancel release, reopen hop; feature: the bridge routes to the laboratory and back); extensions across the derivations, render-surface, epic-projection, presence, transactions, and render suites.

Gates: npm test 2657/2657 · npm run test:cli green · npm run test:migrations green · npm run typecheck clean.

🤖 Generated with Claude Code

leeovery and others added 13 commits September 1, 2026 17:08
The experiment phase joins the schema between research and discussion —
never a routed phase: the spawn (experiment create --from) is its one
door, allocating E{n}, opening the derived item, and locking the
spawning conversation (awaiting_experiments); a locked research or
discussion refuses completion until conclude/abandon releases it. The
record walks conceived → designed → approved (its own verb — the freeze
is never a step a loop drifts past) → running → concluded|abandoned;
splits take E{n}.{m} under a running parent, the lock staying on the
parent and releasing once. Conclude flags downstream, abandon never
does, and the downstream hop now walks only the optional slots — past
an absent or unflaggable record, stopping at discussion, never reaching
spec. The field surface guards the container leaf-by-leaf, the linear
router answers 'experiment (awaiting evidence)' over a live wait, and
the phase joins presence's source set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nu entries

The register is the series' one readout off the manifest — sub-rows
nested under their parent, live rows tagged, terminal rows spelling
their verdict or reason on the ↳ line, a gap between siblings. The
approval gate is the briefing's freeze confirm (commands first, the
Amend prompt last). Each live top-level record renders its own epic
menu entry (E1 {slug} — {Topic} · experiment), leading the menu and
outranking every other recommendation while the pick stays the user's;
entries retire at conclusion, abandonment, or cancellation, and a held
laboratory session strikes its row. The map row cues a waiting
conversation (· awaiting E1), cancel-cascade-gate renders the softer
wait-release confirm for an experiment address, and the single-topic
pipeline view treats the awaiting-evidence route as a started phase
(never a revisit candidate — a new spawn reopens the series).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two scenarios: the epic walks a discussion spawn and a research spawn
(symmetric locks) through the register and briefing freeze to the
verdict — a split refusing the parent's conclusion until its subs
settle, the release flagging the conversation, series continuation
reopening the completed item, abandonment and the cancel cascade
releasing the other waits, and a research reopen hopping to the settled
record. The feature walks the linear route: the bridge answers
experiment while the wait is live and hands back to the conversation at
the verdict.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nditionally

A reconcile flag must land where an entry flow can clear it, and the
series item has none — entry is per-record, a completed series carries
no live records, and no map cue reads its flags. Landing the hop on a
completed experiment item stranded an invisible, unclearable flag,
dead-ended the linear ladder on 'experiment (input moved — reconcile)',
and kept the discussion from learning its research moved. The walk now
skips the slot whatever its item holds: a research reopen flags the
discussion whichever series sits between them, and the series item
never takes a reconcile flag. Its two flag edges stand as designed —
the wait release flags the holder, and a parent conclusion flags
downstream from the slot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ption grammar

experiment-pick joins the render catalogue — the entry skill's no-id
path, a menu beneath the register instead of a prose-authored ask. The
epic menu's per-experiment entries gain their verb and italic metadata
tail, and the approval gate's approve label sheds the amendment-window
essay (the prose owns it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… findings

The cancel/reactivate/successor shape becomes coherent: a series cancel
abandons every open record with the cancellation as its reason (the
register stays honest, no zombie survives), reactivate refuses the
phase — the rows stand, and a new spawn onto the cancelled item revives
the series at the next id. Cancelling a spawning conversation now
cascades the same way: bare refuses naming the stranded waits, --cascade
cancels the series with it, abandoning its open records and releasing
every wait. The item's status also refuses the one hand-write left.

Alongside: the id helpers single-home in the schema (parent check and
series comparator, six local re-spellings replaced); a completed or
cancelled series leaves the resume and reactivate candidates; the
analysis-defer set narrows back to research and discussion — a
laboratory session never touches the corpora the analyses read; the
phase-completed and revisit-gate lines say "Experiment session
complete" — the ceremony the design says doesn't exist stays
nonexistent; cancel's KB skip reads the artifact table; the bridge
gateway's dead dot-filter and the sub-allocator's per-map RegExp go.
Pinned across the engine suites: the triangle's every edge, the commit
door over a full record tree, the projections' resume/reactivate
filters and the awaiting-evidence row, the bulk index discovering no
experiment file, and the sim's walk writing the design before advance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The gate's second option is b/abandon — "park" and "put down" read as a
resumable pause the record never offers, and park already means
set-aside-retrievable on the roadmap. The abandon guard, the row-reason
doc, and the command reference speak the same verb.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
No phase outside INDEXED_PHASES carries an exclusion pin — a guard
against an impossibility singles nothing out.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A comment states what code does, never what it doesn't; a refusal the
schema already makes generic carries no per-phase re-pin; the cancel's
store removal is documented by the rule, not a lone exception. The
create doc follows the shipped revival of a cancelled series.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ins its gate

One row per topic whose series holds a live top-level record, in the
standard continue form with the live count as the tail — the route is
the uniform three-argument entry contract, and which experiment to work
resolves inside the phase. The record id leaves the MenuKey shape and
every route. experiment-next-gate joins the surface catalogue: fetched
after a terminal record transition while live records remain, naming
the live ids and offering the next experiment or the menu; it refuses a
finished series.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… cascade scopes to its own records

DERIVED_PHASES (kernel/manifest-schema.cjs) absorbs the experiment branch
conditions in every generic surface — the lifecycle refusals, the hop
skip, the status-write guard, the resume/reactivate/revisit filters, the
continue-entries skip, and the session-complete wording forks all key on
the property. The cancel consent gate states the terminal truth for a
derived phase. Cancelling a spawning conversation now abandons exactly
its own awaited records and closes only its own waits — the experiment
item is never cancelled; its derived status settles over what remains.
experiment create gains --problem: the spawn installs the problem
statement from a cache scratch in the same transaction, so no conceived
record ever exists without one. The record picker gains b/back.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rt flags, one settle, and the surface that repairs but never creates

The cancel-cascade gate speaks each consumer's truth: the spec collapse
computes only for the phases specs source, a spawn-phase holder's live
waits render their own clause, and the derived-phase branch keys on the
schema property. The spawner cascade leaves the release flag on the
cancelled holder inertly — reactivation restores it live, and the
reopened conversation's entry surfaces its abandoned records.
Supersession refuses over a live evidence wait. The item settle moves
to derivations as the one exported home; the kernel keeps constants and
grammar. The field surface checks existence on the write path — records
are allocated by the spawn, and a lock only ever names one. The picker
sheds its unreachable guard; the laboratory claims its slot at entry
(render phase-note beats); the menu row rides topicRoute; the spawn
guards its topic name. Pins across the suites, the KB exclusion class
re-pinned on planning, and the sim states the inert-flag doctrine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leeovery
leeovery force-pushed the feat/experiment-engine branch from 824829d to d91657f Compare September 1, 2026 17:27
@leeovery
leeovery merged commit 59c0978 into main Sep 1, 2026
@leeovery
leeovery deleted the feat/experiment-engine branch September 1, 2026 17:56
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