Architecture simplification: extract VerbRegistry per-verb files, shared Pipeline guards, Session Forwardable - #249
Merged
Merged
Conversation
…on from pipeline Two changes from architecture review (candidates 1 + 2): **Candidate 1: Collapse duplicate consumer** Workflow::Queue and Protocol::Async::Queue shared copy-pasted retry and execution logic. Extracted Workflow::Consumer — both queues delegate to it. Protocol::Async::Queue is deleted; Watcher uses Workflow::Queue#consume_one instead. One interface, two call sites. **Candidate 2: Decouple event emission from store pipeline** Pipeline::WriteDeps no longer carries workflow_registry. A new Workflow::EventEmitter is wired by Builder and passed to StoreEngine. Pipeline calls event_emitter.emit() instead of creating Workflow::Queue directly. Store path and workflow path are decoupled. Also: adds Consumer and EventEmitter terms to CONTEXT.md.
Candidate 3: Remove Materialize re-dispatch Materialize no longer re-runs matched user workflows synchronously. Event fan-out handles dispatch; Materialize only publishes entries that have publish_to but no matching workflow. Moved from hard-coded Builder.push to .textus/workflows/_builtin/ so all workflows load through the same path. Candidate 4: Deepen Runner Extracted StepExecutor (timeout + step execution) and ContextBuilder (key-to-Context assembly) behind Runner. Runner is now a thin orchestrator: build context, execute steps, publish. Both extractions are independently testable.
Entry-level publish_to/publish_tree was replaced by workflow DSL publish-to: blocks (ADR 0052). No entry in the manifest declares publish targets at the entry level anymore, so Materialize's fallback publish never activates. Removed.
- Merge Schema::Vocabulary, Keys, Semantics into Schema - Delete empty Produce and Handlers namespace modules - Inline Retention::Plan and Key::Distance into sole callers
- Add Policy#allowed?, #allowed!, #writers_for, #actor_for - Gate delegates to Policy instead of inlining V4::LANES checks - Lane drops writers_for, actor_for, proposer_role - V4::LANES stays as data source - Policy handles proposals as special case (not a V4 lane)
- Gate selects context by verb category (read→QueryContext, write→CommandContext) - QueryContext: read-only methods (read, resolve, list, exists?, mentry_for, link_store, entry_index, cursor_store) - CommandContext: extends with put, delete, move + infrastructure access - Container gains store_engine attr_reader - Old Handlers::Context deleted - ContextBuilder inlined into Runner, file deleted
- Builder::Infrastructure: I/O objects (Database, FileSystem, Store) - Builder::Domain: config objects (Manifest, Schemas, Workflows) - Builder::Runtime: wiring composition (StoreEngine, Gate, Container) - Container gains store_engine attr_reader (used by Runtime layer) - Top-level Builder orchestrates the three layers
- Validate: validate_input + validate_schema - Prepare: read_existing + inject_meta + serialize - Write: check_etag + write_bytes + build_envelope - Emit: append_audit + index_entry + emit_workflow_event - Each phase module groups sub-steps as private methods
- Extract StepBuilder (step/check/parallel DSL) - Extract PatternMatcher (match_pattern? primitive) - Extract Lifecycle (ttl/expire/max_attempts) - Definition becomes thin facade composing the three modules
- Layout/ExtraSpacing, Style/Lambda, Style/ArgumentsForwarding - Lint/IneffectiveAccessModifier, Layout/HashAlignment - Style/TrailingCommaInArguments
…ose files, Registry#workflows_for_key, be_success/be_failure matchers)
…eue/RetryPolicy, inline retry, Publisher uses container.store_engine, StepHelpers extracted from Helpers
…s; docs: align knowledge store with current architecture — 4 files updated, 3 deleted, data-flow rewritten
…o separate files, add narrow DeleteDeps/MoveDeps structs
…ks, fix stale error message (match: → on:)
…ENTS.md, boot context in session_open, nodes_checked in session_close, doctor check for skipped constraint, protocol entry 0016
…ifier/comma/guard-clause in new code
…fiedDoubleReference in rubocop; deduplicate config
bin/smoke exercises the INPUT → LOOP → OUTPUT protocol: - INPUT: session open, boot, get knowledge entries, list - LOOP: propose, write session-scoped scripts - OUTPUT: session close, drain, audit --clean flag wipes smoke-test artifacts. bin/db rewritten to Ruby. .textus/.gitignore updated for scratchpad transient dirs.
Update .rubocop.yml to tolerate pre-existing code patterns: - Raise complexity/parameter/example-length limits to current ceiling - Exclude specific files from new cops (OneClassPerFile, EmptyWhen, LineLength) - Remove redundant disable directives made unnecessary by higher limits - Fix RSpec/ReceiveMessages in handler specs
- Save session IDs to bin/.smoke-sids marker file during normal runs - --clean reads marker + finds orphan session dirs on disk - Cleans proposals, session keys, and filesystem dirs - No more accumulating session dirs across runs
- All passes show only ✓ (no noisy etag hashes or UUIDs) - Script writes show clean labels like 'write scripts/check' - Failures show error detail inline - Summary is compact — labels only, no detail repetition - Fixed session-id capture (was broken after assert simplification) - Cleanup includes orphan session dir sweep
patrick204nqh
force-pushed
the
arch-simplification
branch
from
July 5, 2026 13:20
b4bb152 to
e421229
Compare
- Fix resolve_format to respect declared format for nested entries (was always returning 'markdown', ignoring the manifest declaration) - Add append_ext_on_nested? to Format::Base (default true) - Script format overrides to false (no extension appended for nested files) - Text format overrides to false (no extension appended for nested files) - Add format: text to scratchpad.sessions manifest entry - Text nested_glob changed to **/* to match extensionless files - Script nested_glob changed to **/* to match extensionless files Files under sessions/<id>/ now have no extension: session, feedback, scripts/check, scripts/task, scripts/query, scripts/report
- Add --as-format CLI flag to textus put - Thread format: param through handler → store_engine → pipeline - When set, strips parent entry extension and uses override format's extension rules (script format = no extension, markdown = .md) - Parent entry (scratchpad.sessions) stays markdown - Smoke test passes --as-format=script when writing session scripts - Files now: scripts/check (bash, no ext), scripts/task (ruby, no ext), scripts/query (python, no ext), scripts/report (js, no ext) - Session/feedback stay as .md
- Add format classes: Bash (.sh), Ruby (.rb), Python (.py), Javascript (.js) - All inherit from Script (same parse/serialize behavior) - Each returns its own extension via nested_ext - Register in Format::STRATEGIES for --as-format=bash etc. - Remove hardcoded EXT_MAP from Script format - Smoke test passes --as-format=bash/ruby/python/js per script
- Create Ruby (.rb), Python (.py), Javascript (.js) format classes inheriting from Script (same parse/serialize behavior) - Register all 4 language formats in Format::STRATEGIES - Map .rb→ruby, .py→python, .sh→bash, .js→javascript in EXT_TO_FORMAT - Smoke test uses per-language --as-format (bash/ruby/python/javascript) - Files: check.sh, task.rb, query.py, report.js with correct content
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
5 clean-up commits extracted from the ongoing architecture work:
Testing
bundle exec rspec— all green.