framework: a design with one example through every layer #87
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
A REST controller, the service, a repository and the database, so readability for somebody from Spring or Symfony can be judged before the framework exists.
Source
Acceptance criteria
Dependencies
None known.
Moved from the planning lists of the docs; the design record stays the specification.
[loop:torbscript] intake: in scope (author orion, label loop), source FRAMEWORK.md section 3, not a duplicate. A design issue: the worked example is written by the loop in refine; the record asks for the owner's sign-off before building (product direction), which refine files as an owner decision once the example exists. next: refine, waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z
[loop:torbscript] claim refine by session:loop-torbscript-20261029 until 2026-10-29T10:20Z
[loop:torbscript] decided by the loop: the worked example is written to this specification, in one docs-only PR; no owner decision is needed before it is written. The owner's sign-off (second acceptance criterion) is a step after the record exists and is filed then, see "Sign-off" below. Why: every choice below follows WEB.md section 13, URI.md section 11 or the guideline in FRAMEWORK.md section 1, so none of it is product direction.
What the PR delivers
docs/design/FRAMEWORK.mdsection 3 becomes "The worked example" (the stub's "Before it is built" text is replaced; the status line says the example exists and the framework is still planned). One scenario through every layer, the orders of WEB.md (Route,NewOrder,Shop), so the record and WEB.md read as one story.examples/framework/(a workspace member throughexamples/*, so tier A'scheck .gates it; no gate change). It holds the example's source files plus stand-ins for the parts ofstdthat do not exist yet (web handler/request types wherestd/webis missing, a database driver in the shape of URI.md section 11'sConnect/Connection, the module DSL). The record quotes excerpts of these files; the files are the source of truth, so the record cannot drift from code that checks. A layer that cannot be expressed today is shown in the record marked "does not check yet: " and listed as a language/library gap (the way WEB.md lists F1..F13), never silently hand-waved. No compiler orstdchange.@Autowired/ trait-typed constructor field;@Transactional/ closure;application-prod.yml/ profile receiver script;@GetMapping/route(template, to:); Doctrine mapping / mapping DSL;@WebMvcTest/ controller test slice; and so on).The layers the example must cover (acceptance criteria of the PR)
config.trb, SCRIPTS.md, examples/config-dsl) per profile (dev,prod); the database is a service URI (postgres://..., URI.md section 11), secrets bysecret, never inline.project.trbstyle, FRAMEWORK.md section 1) assembles repository -> service -> controller by constructors and traits; no annotation, reflection or scanning. Shows the compile error for a missing dependency at the line that forgot it (a real diagnostic if the checker gives one on the stand-ins, otherwise the intended message, marked as such).route("/orders/{id}", to: Route.Order)(WEB.md D5), handlers(Request) => Task<Result<Response, WebError>>, JSON in and out throughEncode/Decode, form/body validation by types (WEB.md section 3.5), error mappingFrom<OrderError> for WebError.wrap, as WEB.md section 3.3.OrderError, one domain event (OrderPlaced) published and consumed without strings or registration by scanning.examples/query-provider(filter { _.customer == name }), the table mapping is a builder DSL, not annotations.Connect, one migration written in a typed DSL, run at startup in thedevprofile.app.answer(request)as WEB.md section 3.9), a service test over an in-memory repository, a repository slice against an in-memory driver - each starting one layer without the others.Constraints for the implementer
Closes #87in the PR: useRefs #87(see "Sign-off").Connect/Connection/Cachestay out ofstduntil a second driver exists, so the database driver is a stand-in in the shape written there), ENCODING.md, SCRIPTS.md. If the example finds a contradiction in one of them, write it into the record as a finding.std/web,std/ormor DI code, a real database driver, the live UI layer, caches and message brokers beyond naming where they would plug in.torb format --checkon the touched.trbfiles, lines <= 120, keep each file's line endings. English; no private links. Commits:docs(framework): worked example through every layerand, if split,docs(examples): add the framework example package(max 100 characters, Conventional Commits).docs/design/index.mdalready lists the record; if the docs skill gate reports drift, regenerateskills/as CLAUDE.md says (CI shows it; do not build locally). Gates run in forge CI only.Sign-off (the second acceptance criterion)
Approving a framework design is product direction, an owner question per the contract. It cannot be answered before the record exists, and it is not part of the PR. So: the PR merges with
Refs #87; the issue stays open after the merge; the next tick files[loop:torbscript] owner decision:(what the example shows, plain-language options: approve as is / change a named point / stop, with a recommendation) plus a blockingquestion_askblock, and closes the issue once the answer is recorded.[loop:torbscript] refine: the requirements are written up in the comment above (deliverable: FRAMEWORK.md section 3 plus a checkable
examples/framework/package, layer-by-layer acceptance checklist, constraints, Spring/Symfony side-by-side). The earlier wait on the full ready buffer is gone. No owner decision is needed to write the record; the owner sign-off is filed after the PR merges (the issue stays open until then, PR saysRefs #87). Labelreadyset. Worker usage (RE, sonnet): about 75k tokens (estimate). next: ready[loop:torbscript] claim implement by session:loop-torbscript-20261029 until 2026-10-29T17:51Z
[loop:torbscript] release implement: the previous worker ended without a branch or PR (lease expired 2026-10-29T17:51Z), nothing was lost
[loop:torbscript] claim implement by session:loop-torbscript-20261029-0858 until 2026-10-29T23:55:00Z
[loop:torbscript] release implement: worker timed out without a PR (2026-10-29T18:25Z); #87 returns to the ready list, no slot free this tick
[loop:torbscript] claim implement by session:loop-torbscript-20261029-0858 until 2026-10-29T20:40:00Z
[loop:torbscript] release implement: PR #604 opened, head
b3ed7db0, CI not yet seen (nothing built locally), left: owner sign-off on the readability judgement; fixes for the first CI run (check, format --check, test)[loop:torbscript] claim fix by session:loop-torbscript-20261029-0858 until 2026-10-30T01:30:00Z
[loop:torbscript] release fix: PR #604's first CI run (2346, tier A) went red because examples/framework had never been compiled. The fixes are folded into the three owning commits, and the new head is
0f86e5cc(still on base5ba7fdae;tools/check-commits.shis clean).Fixed:
OrderRepository,OrdersandEndpointare nowshared traits. The adapter, the service and the controller each hold theDatabaseobject, and trait rule 17 does not let a value of an ordinary trait hide an object.web.trb:return Fail WebError.badRequest("...")now has parentheses. Without them the file did not parse.assertquotes its condition): every assert that touched a shared object, a non-Encodevalue or a{ _ => ... }closure now binds the answer to aconstfirst. An unusedexpectis nowconst _ = .... The rollback test now inserts through the repository instead ofdatabase.insertinsidedatabase.transaction, which broke the exclusivity rule.torb formatapplied to the 7 files of the package.shared traitand the prose says why, the call syntax is the formatted one, the controller excerpt is the same asweb.trb, and gap G11 (theassertquotation in tests) was added to 3.8.test compiler/testsfailed only on "The whole repository ... nothing is reported", which is the samecheck .errors and not a flake.Verified locally with the nightly
torb 0.1.0of 2026-10-29, not the PR's own build:torb check examples/frameworkreports 15 files and no problems,format --checkchanges 0 of 15 files, andtorb testin the VM passes 14 of 14.Unverified: the native tests (there is no C compiler here), the repo-wide gates and docs checks, and whether the branch's own compiler behaves differently from the nightly.
next: waiting (CI on PR #604)
[loop:torbscript] wait: PR #604 is merged (worked example in examples/framework and FRAMEWORK.md); the one open criterion is the owner sign-off on the readability judgement, which is Torben's call.
next: waiting (owner sign-off, re-check 2026-11-06)