Skip to content

Web surface, shared dispatch, entry constraint enforcement - #251

Merged
patrick204nqh merged 6 commits into
mainfrom
feat/surface-architecture-web-api-dispatch
Jul 5, 2026
Merged

Web surface, shared dispatch, entry constraint enforcement#251
patrick204nqh merged 6 commits into
mainfrom
feat/surface-architecture-web-api-dispatch

Conversation

@patrick204nqh

Copy link
Copy Markdown
Owner

Summary

Three changes from the surface architecture session:

1. Web Surface

  • Sinatra + Puma web server: POST /api/:verb (verb dispatch), GET /api/status (health)
  • CLI: textus web serve starts on port 9292
  • Role via X-Textus-Role header (default: agent)

2. Shared Dispatch (Surface::Dispatch.call)

All three surfaces now route through the same invocation core:

  • CLI: Runner.dispatchDispatch.call(s, verb, **inputs)
  • MCP: Catalog.callDispatch.call(store, verb, args)
  • Web: POST /api/:verbDispatch.call(session, verb, body)

MCP Projector removed (pass-through after dispatch extraction).

3. Entry Constraint Enforcement (Protocol::EntryConstraint)

  • validate_naming! — checks key segments against naming: sequential/ dated
  • validate_schema! — checks meta against declared schema
  • validate_format! — checks content against format rules
  • Fires at propose (naming only), accept (naming + schema + format), put (all three)
  • Accept handler parses body frontmatter before schema validation

Stats

  • 18 files changed, 323 insertions, 34 deletions
  • 1070 examples, 0 failures
  • rubocop: 0 offenses

- Web surface: POST /api/:verb via Sinatra + Puma, GET /api/status
- CLI group/verb: 'textus web serve' starts the web server
- Shared Dispatch.call: all three surfaces (CLI, MCP, Web) route through it
- EntryConstraint: naming/schema/format enforcement at propose, accept, put
- MCP Projector removed (pass-through), Catalog calls Dispatch directly
- Schema validation in accept handler parses body frontmatter first
- 1070 examples, 0 failures, rubocop clean
alias ttl every created a getter that called every(:__no_arg__),
which set @Ttl = nil on every read. The Scheduler's seed_expired
read wf.ttl to check staleness, but the read itself destroyed the
value, returning nil and preventing TTL-based workflow reseeding.

Fix: add early return guard in every() when called with no argument.
- Filter commits by conventional commit type (only feat:, fix:)
- Group into 'Features' and 'Bug Fixes' sections per Keep a Changelog
- Update ERB template to render grouped sections
- Internal commits (chore, refactor, style, docs, test) excluded
@patrick204nqh
patrick204nqh merged commit 3e04bf4 into main Jul 5, 2026
4 checks passed
@patrick204nqh
patrick204nqh deleted the feat/surface-architecture-web-api-dispatch branch July 5, 2026 17:42
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