Skip to content

Stack 5/5: Durability & the closing release — tolerant replay, fsync_every, doc referee, suggestions (rounds 13-15)#5

Merged
codenamev merged 28 commits into
mainfrom
claude/stack-5-closing-y0k02n
Jul 7, 2026
Merged

Stack 5/5: Durability & the closing release — tolerant replay, fsync_every, doc referee, suggestions (rounds 13-15)#5
codenamev merged 28 commits into
mainfrom
claude/stack-5-closing-y0k02n

Conversation

@codenamev

Copy link
Copy Markdown
Owner

Final slice (rounds 13-15), stacked on #4. Merging this brings the branch to the series' closing state: 610 specs green, 131 offline examples, empty asks list.

Framework

  • Tolerant journal replay (default): salvages every whole line around torn/mis-encoded/shape-broken lines and reports them on state.damage; mode: :strict raises JournalDamagedError naming the line — recovery tools must never be the second thing that fails
  • fsync_every: group commit: the durability trade named in the constructor (n-fold throughput vs up to n-1 acknowledged events at risk), plus #sync
  • Docs are runnable-or-annotated: the doctest runner is a referee — every @example/README fence runs or carries a deliberate illustrative annotation (26 run, 4 annotated, 0 dead); drifted fences fixed against current APIs
  • Learning corner revived: three more missing stdlib requires, history store de-duplicated (memory cache + files), never-functional register_with_orchestrator replaced by Learning.lifecycle_hooks
  • Agentic::Suggestions: did-you-mean threaded into ValidationError (renamed-key diagnosis via missing-plus-similar-extra, structured hints) and rewire/remove errors
  • Concurrency contract pinned: per-method guarantees as specs (spec/agentic/concurrency_contract_spec.rb) + @note Concurrency contract: docs

Examples & docs

  • Fourth and fifth persona casts (rounds 13-15): process drill, capability resolver, RBS export, behavior spec, plan server, unix workers, Ractor audit, concurrency key, attachment pipeline… plus the series retrospective

Review focus: replay modes in execution_journal.rb, suggestions.rb, the learning-corner fixes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF


Generated by Claude Code

claude added 28 commits July 7, 2026 20:00
- Tolerant journal replay (the recovery default): every whole line
  is salvaged; torn, mis-encoded, or shape-broken lines land on
  state.damage with line number and reason instead of raising.
  Recovery tools must never be the second thing that fails.
- Strict replay mode for audit tools: mode: :strict raises
  Errors::JournalDamagedError naming the damaged line, including
  task events missing a String task_id.
- fsync_every: group-commit knob on the journal constructor, with
  the durability trade named in its docs (a crash may lose up to
  n-1 acknowledged events); #sync forces the window closed.

Modernizes the asking examples: hostile_inputs flips to a green
acceptance test with both reader postures demonstrated, and
write_path_profile benches the real fsync_every: 20 knob.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
A plan's live state as composed terminal components - badge,
gauge, tree, frame - each testable alone, driven by lifecycle
hooks with structure from the graph's own depth stats. Fourth
persona cast begins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
A Flipper-shaped gate (boolean, actor, deterministic percentage)
deciding per run whether the fact-check step joins the plan,
spliced in with rewire_task - the step is a plan shape, not an
if, so the graph stays honest and the off state has zero residue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Backwards chunked reads with byte-offset cursors: the last page
of a 20,000-event journal costs 16KB and 0.3ms against a 3.2s
full replay. Cursors survive append; page numbers don't - the
kaminari lesson applied to append-only files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
A plan wrapped in a CLI honoring all four channels: data to
stdout, diagnostics-with-hints to stderr, verdicts as exit codes
(EX_USAGE 64 distinct from failure 1), JSON on request - proven
by invoking itself with injected streams the way scripts would.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Every require in lib/ classified against the gemspec and the
gemification schedule. First run caught two live hazards - logger
(bundled in 3.5) and cgi (trimmed in 3.5) - both now declared in
the gemspec with reasons. A transitive require is a loan, and
rubies refinance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
One invoice, two arithmetics: floats confess their IEEE 754 tail
while integer cents sign a contract floats cannot - integer as
tripwire type, banker's rounding as named policy at one point,
and an adds_up rule so the books balance by rule, not hope.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Plans as transition systems: one-method operational semantics,
the full state space enumerated by BFS, completion proved total
by exhaustion for the diamond, and the cycle exhibited as an
empty machine whose only terminal state is {}.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
An ActiveJob-shaped adapter in forty lines: retry_on maps to the
retry policy (accounting preserved), discard_on is backstopped by
the hopeless convention, and in-plan healing resumes work instead
of re-running it through the queue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Three runnable API shapes for the fsync_every knob - constructor
kwarg, policy object, per-call override - judged at the call
site. The kwarg deserved to ship: durability contracts belong to
the object, and one integer hasn't earned a policy wardrobe yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Every @example block and README ruby fence harvested and executed
in sandboxed subprocesses: 11 of 30 are alive. Dead examples split
into fragments-posing-as-programs and API drift; the round-14 ask
is runnable-or-annotated docs, Rust doctest style.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Adds the Round 13 table - a fourth cast of ten prolific Rubyists
(piotrmurach, jnunemaker, amatsuda, davetron5000, hsbt, noelrap,
tomstuart, excid3, kaspth, steveklabnik) - and findings to the
perspectives index, and regenerates the examples catalog (121
examples). Next asks recorded: runnable-or-annotated docs, and
revive-or-retire the learning-system corner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
- The doctest runner is now a referee: every @example and README
  fence must run or carry a deliberate annotation ((illustrative:
  reason) in titles, <!-- doctest: illustrative --> before fences);
  unannotated failure exits 1. Result: 26 run, 4 annotated, 0 dead.
- Fixed the drifted docs: PlanOrchestrator fence uses the current
  API, fragments became self-contained programs, the compose fence
  registers its capabilities and executes, plugin example conforms
  to the plugin contract.
- Revived the learning corner: three more missing stdlib requires
  (time x2, digest), ExecutionHistoryStore no longer double-counts
  records (memory cache + files are now deduped by id), and the
  never-functional register_with_orchestrator (it called an #on
  API that never existed) is replaced by Learning.lifecycle_hooks,
  the same construction-time seam the journal uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Plan execution over a real loopback socket: thread pool, one
shared mutexed quota across request threads, and a graceful drain
proven with a request in flight - close the listener first, finish
what you hold, join, exit. Fifth persona cast begins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Bundler-style resolution over the never-resolved dependencies:
field: backtracking search, highest-still-compatible selection,
and a conflict error with both demand chains and suggested moves
- because when resolution fails, the error message is the product.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
RBS signatures generated from capability contracts - required:
projects as record-key optionality, shape vs law divided on
principle (RBS carries what static checkers can check, the
validator carries what needs values), agreement spot-checked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
A compliance file in a dependency-free 30-line mspec: six boundary
choices (closed ceilings, resize vs old stamps, nil presence,
success-erases-failure) promoted from behavior to executable
specification - the document a porter needs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
A 40-line Levenshtein engine on three error seams: capability
lookups, contract violations (missing-plus-similar-extra is a
typo's signature), and rewire targets. The error was holding the
candidate list all along; round-15 ask filed to make suggestions
a framework property.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Mini-profiler's heresy for plans: a badge on every run, budgets
that name the offender ('fix summarize first' is an assignment; a
p95 chart is a vibe), and a self-audit proving always-on costs
144 microseconds per plan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
A master preforks three plan workers: shared-pipe work queue,
SIGTERM as finish-then-exit, reaping by pid and status, per-worker
flock'd journals. The drill taught two live lessons: require what
you use, and a pipe is a queue but not a fair one under burst.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Every interesting framework value judged by Ractor.shareable?:
stats and order cross as-is, the frozen snapshot is a shallow
promise, and the RateLimit's refusal is load-bearing - send facts,
keep machines. The auditor's first draft froze the evidence;
verdicts now come from Marshal copies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
SolidQueue's concurrency_key over the framework's limiters: at
most one sync per tenant with cross-tenant parallelism measured
(not assumed), both overflow postures named at the call site, and
a lock-guarded registry so rival limiters can't be minted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Shrine's cache/promote two-phase pattern as a journaled plan:
derivative names as idempotency keys, crash resuming at the exact
thumbnail it died on, the record committing only after every
derivative exists, and the double-submit deriving nothing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Adds the Round 14 table - a fifth cast of ten prolific Rubyists
(evanphx, indirect, soutaro, eregon, yuki24, samsaffron, rtomayko,
marcandre, rosa, janko) - and findings to the perspectives index,
and regenerates the examples catalog (131 examples). Next asks
recorded: did-you-mean suggestions in framework errors, and
fiber-vs-thread guarantees pinned as behavior specs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
- Agentic::Suggestions: a conservative Levenshtein engine (silence
  beats a confident wrong answer), threaded into the framework's
  errors. ValidationError diagnoses renamed keys from missing-plus-
  similar-extra (structured hints + message), and the rewire/remove
  errors suggest close task names - the candidate lists were already
  in scope at every raise site.
- The concurrency contract, pinned: spec/agentic/
  concurrency_contract_spec.rb promises per-method guarantees
  (journal record thread-safe, windowed limiter thread-safe,
  concurrency-mode limiter fiber-scoped, registry thread-safe),
  with @note Concurrency contract: documentation on the methods.

Modernizes the asking examples: did_you_mean.rb flips from
retrofit to native demonstration; behavior_spec.rb points at the
delivered contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
Adds the Round 15 section (did-you-mean as infrastructure, the
concurrency contract pinned) and the series retrospective: fifteen
rounds, fifty personas across five casts, thirteen releases built
from field notes, 131 offline examples, and an empty asks list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
- Durations measured on the monotonic clock (stack 1 panel,
  tenderlove): wall clocks step under NTP and every journal
  baseline downstream would eat the noise; all orchestrator timing
  deltas now use Process.clock_gettime(CLOCK_MONOTONIC).
- typo_hints detects missing keys structurally (stack 5 panel,
  jeremyevans/yuki24): violations.keys - given.keys instead of
  string-matching dry-schema's message text, which is not an API.
- Concurrency contract pins the high-water mark under threads
  (stack 4 panel, headius follow-through on the counter mutex).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FeZLdZ3M4q4cho4DZPfSkF
@codenamev codenamev changed the base branch from claude/stack-4-hardening-y0k02n to main July 7, 2026 23:38

@codenamev codenamev left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Persona review panel: Mike Dalessio, Jean Boussier, Yuki Nishijima. Verified locally: 610 examples, 0 failures at HEAD (including this stack's review-fix commits); timing-dependent examples re-smoked after the monotonic-clock change.


Mike Dalessio (flavorjones) — Tolerant replay is exactly the posture a recovery parser owes its callers: salvage every whole line, record torn/mis-encoded/shape-broken lines on state.damage with line numbers and reasons, and never let the recovery tool be the second thing that fails. The two-door design (:tolerant default for recovery, :strict raising JournalDamagedError for auditors) is the right resolution of the tension I raised — one format, two reader postures, both legitimate, and the strict error carries line_number as data, not just prose. line.scrub before parse handles the encoding-garbage case in the same sweep. The hostile-inputs probe staying in-tree as the acceptance test is how this stays fixed. Approve.

Jean Boussier (byroot)fsync_every: is the group-commit knob done the way durability knobs must be done: the trade is named in the constructor's docs (n-fold throughput, up to n-1 acknowledged events at risk — "a different durability contract, not a faster same one") instead of living in a wiki. #sync gives the explicit close-the-window call, and the write-path profile example prices the whole decision (fsync is 99.6% of the write; JSON was always innocent). Also endorsing this stack's review-fix commit: durations on CLOCK_MONOTONIC — every percentile baseline in the journal was one NTP step away from a phantom regression. Approve.

Yuki Nishijima (yuki24) — The suggestions work is my ask, delivered better than I filed it. Agentic::Suggestions is conservative where it must be (length-scaled threshold; hint returns "" rather than guess — a wrong suggestion is worse than none), and the ValidationError integration diagnoses the rename case specifically: missing-plus-similar-extra → "You sent :weight_kilo - did you mean :weight_kg?", in the message AND as structured hints for programmatic consumers (the self-correcting-output loop feeds these straight back to a model). One thing I'd flagged in draft is already fixed in this stack's review commit: missing keys are now detected structurally (violations.keys - given.keys) instead of matching dry-schema's message text, which is not an API. rewire/remove suggesting across ids and descriptions is the right candidate pool. Approve.


Panel verdict: approve (as comment; self-approval disallowed). All action items from panels 1-4 are resolved in this slice; nothing carried forward. Merging closes the stack.


Generated by Claude Code

@codenamev codenamev merged commit 0fe3f91 into main Jul 7, 2026
1 check passed
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.

2 participants