Sprint 27

Table of Contents

This page documents a sprint (Sprint 27) of ORE Studio. It captures the sprint's mission, current status, and the stories that compose it. For the surrounding context — version goals, sprint order, and product identity — see Version 0.

1. Mission

Finish the UX pass: land the remaining journey groups in ores.web, and bring the record screens to the standard.

This is sprint 26's third pass, taken alone and sized to the window: its retrospective settled on one pass per sprint, not three. The codegen and journey-extraction remainders wait in the product backlog.

2. Status

Field Value
State DONE
Parent version Version 0
Previous Sprint 26
Start 2026-10-05
End (expected) 2026-10-12
Now Nothing.
Waiting on Nothing.
Next Nothing.
Release Notes Sprint 27 release notes
Last touched 2026-10-13

3. Stories

For the definitions of the themes see Themes.

3.1. Product

Story State Start End Description
Open sprint 27 DONE 2026-10-05 2026-10-05 Scaffold sprint 27, set its mission, wire the version manifest and the agile index, and bump the project version to 0.0.27.
Hold money exactly and move the external version on economic change DONE 2026-10-09 2026-10-11 Money quantities become exact decimals consistent by role, the ORE boundary stops losing the document's spelling, and an economic digest moves the trade's external version when, and only when, a component's economics change.
Add proper curve support to ores.marketdata DONE 2026-10-07 2026-10-10 A curve is a derived series and nothing else. Settle the shape the journeys demand, give a point its provenance and a manual key its author, add the operator's write and clear path, and make staleness visible when a term structure is drawn.
Make a series identity joinable in the database DONE 2026-10-08 2026-10-08 A series holds its identity only inside its oresmd URI, so the database cannot join or filter on it. Project that identity into one column per codec field, written from the same parse that writes the URI, so the joins are on real columns.
Seed a relative-time trade population with the market data it needs ABANDONED 2026-10-10   A new ACME system has no time horizon and no deal population, so nothing says which fixings it needs. Hold a sample trade corpus in DQ with dates relative to the install date, then generate the market data it requires, including historical fixings, in ores.synthetic. Carried to the product backlog inbox at the 2026-10-13 close.
Make the ACME data realistic and isolate the ORE samples DONE 2026-10-10 2026-10-13 The ACME netting, CSA, portfolio and report data is derived from the ORE samples and reads as sample data. Build a realistic ACME base bundle that follows each party's report definitions. Retarget the ORE samples bundle to the labelled reference data the sample import needs, installed on every party, with imports landing in a sandbox portfolio tree.
Publish the ACME reports ready to run DONE   2026-10-13 Publish every static input an ACME report needs through DQ datasets with declared dependencies, so a clean provision leaves each report definition ready to run: its configuration documents, its bindings, its risk configuration and its scope. Market data comes from the feeds. Trades are out of scope.
Implement the operations journeys in ores.web DONE 2026-10-05 2026-10-13 The ninth journey group: the installation's own life — the services running, the compute grid, the message bus, the logs, and the versions and database under them.
Keep the prototypes in git DONE 2026-10-05 2026-10-06 The seven prototype branches merge into main, so each design record stays reachable after its sprint closes; the prototype hub answers the credentials, operations and onboarding screens.
Complete the ores.inbox approvals and notifications DONE 2026-10-05 2026-10-06 Land the role request kind and build the request and notification screens; serving the approvals and notifications landed with PR #2652 before the close.
Land the role request journey DONE 2026-10-07 2026-10-08 The fourth access journey: the member asks for a role beyond the one registration gave them, and the tenant administrator answers. The request, the guard, the grant and both screens landed under the inbox story, and this story added which roles may be asked for and a deadline for a request nobody answers, then rewrote the journey document around the design.
Build the retire or reset tenant journey ABANDONED 2026-10-05   The Tenancy group's second journey: suspend, terminate, deprovision, purge and the party-level reset get their subjects, and the roster's Retire or reset item lights up. Carried to the product backlog inbox at the 2026-10-13 close.
Bring the record screens to the standard DONE 2026-10-05 2026-10-13 The existing record screens conform to the standard; server paging and the People and holiday calendar screens landed before the close, the rest remains.
Complete the pattern language DONE 2026-10-05 2026-10-05 The communication, coordination, resilience, load and data pattern groups, and the rule that makes a design name its patterns.
Codegen developer experience improvements DONE 2026-10-05 2026-10-13 Address workflow friction in codegen: component-mode address and type errors, no entity-scoped filter, no way to target a logical group.
Return marketdata to the clean-standard registry DONE 2026-10-05 2026-10-06 Take the marketdata registry entry once P01 and H01 close, and remove the namespace closer comments the templates forbid.
Codegen improvements from the clean-up passes DONE 2026-09-27 2026-10-06 Fix the codegen defects the component clean-up passes surface: each is recorded with the evidence that shows it and fixed at its source with a regression test, on one long-lived branch that merges once every component is clean.
Record trade activities and trade links DONE 2026-10-05 2026-10-08 One activity per business event, and typed directed links; every component version names the activity that caused it. The run and its trade groups have their own story.
Model trade structures DONE 2026-10-05 2026-10-09 The structure anchor, its kind and template, temporal membership with one structure per trade at a time, and one level of nesting.
Rework the rates instruments to the instrument table rule DONE 2026-10-08 2026-10-11 Apply the bond pattern to the rates family: a family header holding exactly its codes, product fact tables, shared children with role codes, and securities keyed by their reference datum.
Rework the credit instruments to the instrument table rule DONE 2026-10-11 2026-10-13 Apply the bond pattern to the credit family: a family header holding exactly its codes, product fact tables, shared children with role codes, and securities keyed by their reference datum.
Workspaces: finish the feature ABANDONED 2026-10-05 2026-10-05 Abandoned: workspaces are removed, not finished, by Remove workspaces from every component.
Clean ores.scheduler to the component clean standard DONE 2026-10-05 2026-10-09 Bring ores.scheduler to the Component Clean Standard (Entity items): tier 2, higher infrastructure.
Clean ores.synthetic to the component clean standard ABANDONED 2026-10-05   Bring ores.synthetic to the Component Clean Standard (Entity items): tier 3, domain component. Carried to the product backlog inbox at the 2026-10-13 close.
Add the identity workflow and the commands that drive it DONE 2026-10-05 2026-10-09 The identity workflow as a registered definition whose steps the request declares, and the commands that drive it from ores.shell.
Model the handcrafted ores.dq code and generate the artefact tables DONE 2026-10-05 2026-10-09 Model every handcrafted ores.dq table and function and automate the 49 artefact tables, keeping the component regenerating byte-identically.
Remove the presentation keys no template reads DONE 2026-10-05 2026-10-09 The presentation keys no template, render path or validator reads, the helpers that exist only to compute them, and the pages that still describe the Qt layer as live.
Run an example bundle through the compute grid from a report definition DONE 2026-10-05 2026-10-13 Give ACME a report type and definition whose run submits an existing example bundle to the compute grid and retrieves the results.
Read each tenant's cache partition inside its tenant DONE 2026-10-05 2026-10-13 The root tenant lists every tenant's parties because IAM's party cache reads as IAM's own system-tenant identity and the parties policy was widened to let it. Apply Cache-Aside with Token Exchange: each cache partition loads with a narrow, short-lived token for its own tenant, minted in-process by IAM, and the parties policy and read return to strict tenant scoping.
Complete the super administrator UX journeys DONE 2026-10-05 2026-10-05 The super administrator's own journeys: the deployment's accounts read from system administration, the platform's service accounts among them; the seeded administrators named and pictured; and the welcome that shows a username replaced by a human name.
Remove workspaces from every component DONE 2026-10-05 2026-10-08 Workspaces are replaced by sandboxes and virtual books: remove the workspace column, the workspace context and the ores.workspace component across the system.
Run a report as its tenant and party DONE 2026-10-05 2026-10-08 A scheduled report run acts as the tenant and the party of its definition: IAM holds run grants and exchanges them for short-lived run tokens, step services cache those tokens, and reporting grants and revokes them with the schedule.
Bootstrap the system at runtime DONE 2026-10-06 2026-10-09 A fresh database holds the schema and the staged DQ artefacts only. Making it usable is a runtime act: the ACME provisioning runs through ores.shell, or through ores.web's setup journeys. Tests insert the content they need through shared helpers.
Guard every read the security documentation does not allow DONE 2026-10-06 2026-10-06 363 of 367 generated read handlers answer any signed-in member; a read checks its permission unless the security documentation allow-lists it.
Migrate the remaining refdata entities to the generated event registrar DONE 2026-10-06 2026-10-06 Eighty-five refdata entities generate an event-mapping registrar that nothing composes, so their changes reach no consumer; eight still publish through the hand-wired path in application.cpp. Compose every generated registrar and retire the hand-wired path, so one composition point carries every entity's events.
Name the installation's own data DONE 2026-10-07 2026-10-07 Name the class of the deployment's own facts and give it the policy shape it wants: the codegen expresses installation-scoped data, so a model declares its owner instead of hand-writing a policy, and the grid and node samples carry that shape and are read whole by a session the permission admits. The work counts are superseded by Account for the grid's usage.
Move the installation's remaining reads onto its own class ABANDONED 2026-10-07   The roster, the logs, the bus and the versions carry the installation's policy shape and are read whole by a session the permission admits, on the same codegen feature story 58F3FC7C added. Carried to the product backlog inbox at the 2026-10-13 close.
Account for the grid's usage ABANDONED 2026-10-07   The grid's global view: which tenant is using what. The work that answers it is tenant-owned, so reading it across tenants is the widening the guard forbids. The installation records what it did instead, as it works inside each tenant. Carried to the product backlog inbox at the 2026-10-13 close.
Gather a run's inputs by declared dependency DONE 2026-10-07 2026-10-13 A run's inputs are gathered today by a fixed linear chain that exports each owner's rows as one opaque blob and never waits for more than one of anything. Give ores.trading a batcher that partitions a report's trade population into trade sets by a pluggable strategy, each set named by a batch key and carrying an as-of; declare the inputs a run needs; hold them as a dependency graph; and assemble the package only when every declared input is present. Two of the nine tasks are done: the declaration and the graph.
Group the prototypes and add the Gemini reviews DONE 2026-10-08 2026-10-08 One flat list of 46 prototypes cannot be read. Group them under the journey topic each answers to, give the top page the groups and each group a page that lists its prototypes, put the Gemini review screens beside the prototypes they review, and encode the shape so every environment classifies a prototype correctly.
Split the ER diagram by group DONE 2026-10-09 2026-10-13 The one ores_schema diagram is too large to render and carries no relationships. Decide how to group it and generate one diagram per group.
Bring the QA validation runner to ores.web DONE 2026-10-10 2026-10-11 ores.qt had a QA Validation Runner, a test scenario manager. It opened a test_scenario doc, listed its steps, let the tester mark each step PASS or FAIL with a note and a screenshot, and wrote the results back. ores.web has no equivalent.
Browse the agile tree in ores.web DONE 2026-10-11 2026-10-11 Story 2 of the QA runner arc. Add kanban for the sprint, stories, tasks, the backlog buckets and any doc by link to the Development module in ores.web. Reach parity with ores.dsh_kanban and ores.org-js, then retire both and their publishing (the copy into the site in ores-build-site.el, the exclude patterns, and the memory, tag and modeling pages that name them). Check that no site page links to the old agile view.
Raise a notification for a scenario waiting for a tester ABANDONED 2026-10-11   Story 3 of the QA runner arc. A scenario that waits for a tester raises an inbox notification and the bell shows it. Add a tester role and an assignment, and a permission for the Development module. Today any signed-in user may call the QA routes. Also settle whether the module runs in production, since a deployed BFF has no work tree. Carried to the product backlog inbox at the 2026-10-13 close.
Edit an oresmd URL in a dialog DONE 2026-10-12 2026-10-12 A dialog composes, parses and validates an oresmd URL from the schema and the codes the system keeps, so nobody writes one by hand. The server holds the grammar and answers parse, compose and describe-schema operations; the web shows the accepted editor of the prototype as a modal that a screen calls and that writes the edited URI back. The IR and FX synthetic feed screens call it first.
Link an oresmd URL to what it names DONE   2026-10-13 A click on an oresmd URL opens the object it names, as a link does everywhere else, and a small icon button beside it opens the URL in the editor. The editor has a read-only view laid out like the non-edit mode of the record screens, with labels and values and no inputs.

3.2. Hotfixes

Story State Start End Description
Hotfix: The user systemd probe ignores the busctl transport DONE 2026-10-06 2026-10-06 compass decides whether to wrap a build in a systemd-run scope from a probe that goes through the busctl transport, so inside a sandbox it wraps the build in a scope that systemd-run cannot start.
Hotfix: Domain generator omits the Boost UUID I/O include DONE   2026-10-06 The domain-entity generator template emits generator expressions that call boost::uuids::to_string without including <boost/uuid/uuid_io.hpp>, so the generated ores.iam run_grant generator fails to compile.
Hotfix: Site build needs live GNU ELPA DONE   2026-10-06 The site build installs Emacs packages from elpa.gnu.org at build time, so a GNU ELPA outage turns site CI red; the workflows keep no package cache and the refresh retry never runs.
Hotfix: scheduler accepts six-field cron expressions DONE 2026-10-06 2026-10-06 Since the croncpp 2026-08-12 port, cron_expression::from_string accepts a six-field expression and reads it shifted, and ores.scheduler.api.tests fails.
One way to keep a prototype DONE   2026-10-06 Two prototype mechanisms exist: static HTML under doc/prototypes, and React journey prototypes in the ores.web package. Bring every prototype under doc/prototypes, document the one way to add one, and list every prototype in doc/prototypes/index.org.
Finish the refdata read path DONE   2026-10-06 The tenant roster has no order and a tenant has no history; the party read takes only offset and limit, so parties cannot be searched or sorted. IAM's party cache does not follow party events, the party pgTAP test inserts no category, and the party hierarchy has no cycle guard. Close these gaps on the two screens the record-screen standard names.
Attach pictures at runtime through one seam DONE   2026-10-06 One assets operation ensures a template image exists in a tenant; one IAM operation reconciles account pictures from it. Staff photos, party logos, counterparty logos and service account pictures all use the same seam, reachable from ores.shell and ores.web.
Implement synthetic data generation against the new market data model DONE   2026-10-09 Prove that a synthetic feed produces data the new ores.marketdata model consumes natively: oresmd identity, market_series registration, per-point provenance marked generated, and feed bindings. Fix what does not hold and record what is missing. Curves are paused until this delivers data to drive them.
Hotfix: Continuous Linux red and the site build cancelled on every push DONE   2026-10-06 Continuous Linux fails the Boost port check on a header Boost.ContainerHash owns, and the site build fires on every push so its runs cancel each other.
Hotfix: Windows MSVC build treats an unused catch parameter as an error DONE   2026-10-06 MSVC stops the Windows build at publish_service.cpp:196 with C4101 'e': unreferenced local variable, promoted to error C2220 by /W4 /WX.
Tidy up the system core and the leftovers DONE   2026-10-09 An installation brings itself up from a bundle that is the whole set of datasets it is read from, and the leftovers the first pass of that fix exposed are closed: the remaining system-tenant datasets swept in, the ER diagram image matched to its source, the web service's account settled, and the fpml dependency generator made to run.
Run every check locally in one report DONE   2026-10-07 GitHub CI makes every pull request wait for checks a workstation can run faster. Give the repo one command that reads the change, classifies it, runs exactly the checks that class needs, and prints one report that names every failure and its fix. Ship the decision tree with the runner, so a documentation change never pays for a C++ build.
Account avatars are too dark to see DONE   2026-10-06 The seeded account avatars are Fluent SVGs filled #212121, so on the dark theme a service account, tenant administrator or super administrator reads as disabled.
Separate the account's credentials from its profile DONE 2026-10-06 2026-10-07 One account entity holds both profile data and the secrets a person or service authenticates with, so a profile write replaces the whole row and clears the credential the domain cannot carry. Split the access paths.
Bring every subject onto the canonical entity protocol DONE   2026-10-09 A census of every nats_subject in the tree finds 129 of 2455 outside the specification's grammar: common verbs renamed, operations that never went to the reserved ops namespace, and three resources spelled twice, once snake_case and once kebab-case.
Report a refused request as a refusal DONE   2026-10-07 A guarded request the caller may not make is answered with an empty body and an X-Error header, but a client that only knows token_expired tries to decode the empty body and reports a decoding failure. The work is sent after a wire-format defect that does not exist, and a real permission problem is invisible.
Add the writing discipline the Zettelkasten page omits DONE   2026-10-07 The page covers identifiers, atomicity and structure notes, and says nothing about how a note argues, how a link is chosen, or what goes wrong. Compare it with the Luhmann writing skill and add what transfers to this corpus.
Write the refdata party, book, convention and tenor journeys DONE   2026-10-07 Write journeys 5 to 9 of the agreed ores.refdata catalogue: onboard a counterparty, keep a party's details current, shape the book structure, define the conventions for an instrument, and define how tenors resolve. Each journey needs a wireframe, a coverage table checked against the generated protocol headers, and a group in the journeys index.
Implement the refdata party, book, convention and tenor journeys DONE   2026-10-13 Build the five refdata journeys in ores.web on the server changes each one needs: counterparty onboarding, party details, the book structure, the instrument conventions and the tenor resolution.
Keep the nightly include-cleaner out of generated files DONE   2026-10-07 The nightly include-cleaner PR edits projects/ blindly. Classify its changes against the codegen generated marker, keep the hand-crafted fixes, and make the fixer skip generated files so their includes are fixed in the archetype templates.
Hotfix: Drop the libstdc++ internal header the include run added DONE   2026-10-07 The nightly include run added <bits/chrono.h> to two ores.refdata test files. It is a libstdc++ internal, it is not portable to libc++ or MSVC, and both files already include <chrono>.
Isolate tenant data in object storage and the compute grid DONE   2026-10-13 Give every object one owner: a tenant owns a bucket per data class, the platform owns the shared buckets, and access is an object capability scoped to exact keys. A step service presents its run token and a worker node presents a capability for one assignment, so no tenant can reach another tenant's bytes.
Clear the local-check failures on main DONE   2026-10-09 The local check gate fails on main for two reasons that are nobody's branch: six shell scripts tangle differently from what is committed, and the two DSH plugin packages still declare version 0.0.25 against a 0.0.27 product.
Hotfix: The credential model links a model that was withdrawn DONE   2026-10-07 ores.iam.account_credential.org links ores.iam.operations, a model that was withdrawn and never committed, so the link dangles and lint and site-page both fail on it.
Define the trade set model DONE 2026-10-07 2026-10-08 A trade set is the primitive: a well-defined set of trades. A trade group is the set a run of a process creates, a structure is the set that is also a product, and a link is neither. Batching, every process and every report stands on a stated model instead of an assumed one.
Trace a process run and the trade groups it creates ABANDONED     A process that acts on a set of trades must be traceable, so it can be undone or repeated. Record each run with an identity and a state machine, name the process it is a run of, and let the trade groups its inputs and outputs carry the run's key. Waits on one process with a real client. Carried to the product backlog inbox at the 2026-10-13 close.
Catch the generated artefacts up, and fix a dangling id link DONE 2026-10-08 2026-10-08 Four local checks failed on main and none was a branch's fault: two generated shell scripts, the ER diagram, and a link whose id is spelled in a different case from the document that defines it.
Repair the drifted artefacts on main DONE   2026-10-08 Main is red because two generated artefacts drifted from their sources: the ER diagram is missing a column, and the access page is not prettier-formatted. Regenerate and reformat both.
Carry every trading instrument as a typed batch DONE   2026-10-09 The export carries each trade's instrument as instrument_payload, an untyped std::string type plus a JSON std::string body, because rfl cannot tag a std::variant of the trading instrument types. That is an untyped payload and a hand-written second type system; the project's own wire rule forbids both. Replace it with one typed array per concrete instrument type, joined back to its trade by trade id, and delete the hand-written codec. Deprecate the polymorphic-payload pattern in the knowledge base and apply the same rule everywhere it is used.
Bring the last components under the drift gate DONE   2026-10-09 inbox, synthetic and scheduler generate C++ but are not named in COMPONENTS_UNDER_TEST, so check_component_drift –all never regenerates them. Their committed output has drifted from the templates across 195 files while the gate reported a clean tree, and bringing them under it exposed two more defects: the gate regeneration is not reproducible between –component and –all, and 21 tangled shell scripts have drifted.
Record the env format change for the workspace removal DONE   2026-10-08 The workspace service variables left the env format when the service was removed. Record the new format version in the env log.
Mop up after the workspace removal DONE   2026-10-08 The avatars populate script lost an insert header when the workspace avatar was removed, so the database could not recreate. The eventing worked example and several knowledge and manual pages still described the deleted table, feature flag and permission codes. Repair both.
Quote the offset column in the marketdata identity view DONE   2026-10-08 The commodity identity view selects a column named offset, which PostgreSQL reserves, so the schema cannot load and no database can be recreated.
Order the structure members after the trades they reference DONE   2026-10-08 The structure members table carries a foreign key to the trade table, but its include runs before the trade table is created, so the schema fails to load and no database can be recreated.
Hotfix: the oresmd codec does not compile DONE 2026-10-08 2026-10-09 The market data URI codec calls two static members of its own class from a free function, so ores.marketdata.core does not compile and the build stops at 70%.
Hotfix: the party role names a dropped column DONE 2026-10-08 2026-10-09 The trade_party_role model still lists counterparty_id in its C++ Table display and in its SQL Indexes, but commit 178610c4e8 removed the column, so ores.trading.api does not compile and the party roles table cannot be created.
Bring the generated column references under a gate DONE 2026-10-08 2026-10-08 A column removed from a codegen model's Columns can survive in its Table display or its Indexes, and the generator reproduces both verbatim, so generated code names a column the entity does not have and only the compiler or a database recreate finds it, after merge.
Hotfix: the consumers still set the dropped party columns DONE 2026-10-08 2026-10-09 178610c4e8 and 3053327b95 removed party_id and counterparty_id from the trade's eight children, but hand-written code in ores.ore and ores.trading still assigns them, so those targets do not compile.
Hotfix: the generated headers miss the chrono include DONE 2026-10-08 2026-10-09 The domain class template emits a std::chrono member for every entity with audit columns and supplies no include with it, so 126 generated headers named std::chrono without <chrono> and compiled only where the consumer pulled it in first.
Hotfix: the counterparty fixtures write a dropped column DONE 2026-10-08 2026-10-09 0d9dd1a899 replaced the counterparty's business_center_code column with a business centres junction, but a C++ generator test still asserts the member and nine pgTAP fixtures still insert it, so the build stops at 81% and no fixture can run against a recreated database.
Hotfix: the series shape writer cannot name its context DONE 2026-10-08 2026-10-09 bdb7215934 declared series_shape_writer::declare with a fully qualified ores::database::context in the header and an unqualified context in the definition, so ores.marketdata.service does not compile and the build stops at 87%.
Hotfix: the sweep schedule cannot see its own name DONE 2026-10-08 2026-10-09 0640cb0f2f, the reminder-before-the-deadline work, compares the registered job's name to described_.job_name inside a lambda that captures nothing, so ores.inbox.service does not compile and the build stops at 98%.
Hotfix: the tenantless catalogues ask for tenant policies DONE 2026-10-08 2026-10-09 a2dcf034fa and 2b7301ceca declared booking_nature_type, counterparty_scope_type and entry_channel_type as having no tenant, but their models still ask for a tenant isolation policy, so the generated create scripts read a tenant_id column that does not exist and the schema cannot be built at all. e37b84a81b did the same for structure_member, whose party policy reads a party_id column the pin removal had already dropped.
Hotfix: the versioned catalogues cannot be seeded DONE 2026-10-08   a2dcf034fa made the three closed trading vocabularies regular, versioned tables and so deleted their :immutable: flag, but left the models' prose and the hand-written seeds describing the immutable shape. The seeds still say on conflict (code), which matches no unique constraint, and supply none of the audit columns the versioned insert trigger now requires, so compass db recreate stops in its populate phase.
Hotfix: the chrono include never reached the trading instruments DONE 2026-10-08   177a2d6196 gated <chrono> on has_audit_columns in the domain class header template and regenerated the components under the drift gate, but six trading instrument headers kept the output they had before it. trading-cpp is in the gate's registry, so check_component_drift.py –all fails on it: bond_instrument, composite_instrument, composite_leg, equity_position_instrument, scripted_instrument and swap_leg each need the include the template now emits.
Hotfix: the operations screens cannot see the bus or the storage service DONE 2026-10-08   Two defects found by exercising the operations screens against a running fleet. The telemetry service polls the NATS monitor at a literal localhost:8221 carried in the shared service registry, while NATS ports are per environment and this one is 20406, so no bus sample is ever collected and the message bus screen is permanently empty. And ores.storage is the only compiled service whose application.cpp never constructs a heartbeat publisher, so it shows as missing on the services screen while running.
Hotfix: the settings trigger is refused by the function it calls DONE 2026-10-08   ores_variability_system_settings_default_party_fn is an invoker-rights BEFORE INSERT trigger that calls ores_variability_resolve_system_party_fn, whose EXECUTE is revoked from PUBLIC so that only the reading roles hold it. A trigger runs with the writing role's privileges, so the moment a service writes a tenant-wide setting – a nil party, which is what such a caller sends – the insert is refused by the function its own trigger calls. The bootstrap is the first caller to do it, and the last step fails with permission denied.
Hotfix: the marketdata offset field has no name DONE   2026-10-09 a6f1f9b570 renamed the series identity projection column offset to spread_offset, but datum_ore_key_codec_tests.cpp still reads fl::offset, so ores.marketdata.core.tests does not compile and the build stops at 91%.
Hotfix: the party role test asserts a dropped column DONE   2026-10-09 c73c71ea re-keyed the trade party role by the trade anchor and dropped the counterparty columns, but the empty-vector case in domain_trade_party_role_tests.cpp still asserts the rendered header contains Counterparty ID, so ores.trading.api.tests fails.
Hotfix: the export joins on a trade id nobody mints DONE   2026-10-09 export_portfolio joins each trade to its instrument by item.anchor.id while the instrument batch is keyed by trade_id, and two payload builders bypass the planner that mints them, so every id was nil and every trade joined whatever row rebuild_instrument found first: a CapFloor resolved to another trade's swap, an Ascot resolved to a swap, and the exporter tests fed duplicate nil ids.
Hotfix: the trading children write outside the session party DONE   2026-10-09 178610c4e8 stopped the trade's children copying its party, which took the party_id column away from trade_booking and trade_state. Their eventing tests lost the party-scoped session with it, so every row they wrote was invisible to their own read: the replace claim built from that read said no row existed, and the insert trigger refused the write.
Hotfix: the denial test counts on a caller without a role DONE   2026-10-09 efe1543875 granted Member the iam::roles:read code, which the account-access read is gated on. Every person account holds Member from its first version, so the test's caller – written as a person account with no roles – now holds it and is admitted: the case fails with an outcome of ok and a non-empty roles list.
Implement the audit sign-ins journey DONE   2026-10-09 A tenant administrator reviews active sessions, session activity, failed attempts and where each session came from. The auth events and the session statistics have no subject, logout leaves the session open, and an address is never resolved to a country, so the screen cannot account for the sessions it lists.
Close the sprint's finished stories DONE   2026-10-09 Twelve stories sit STARTED with every task DONE and every PR merged, so the sprint table says work is in flight that has finished, and eleven of them carry no Result at all. Close them and record what finished them, and correct the role-request journey's sentence that contradicts its own gap table.
Reconcile the sprint's bookkeeping DONE   2026-10-09 The sprint audit reports 41 findings: a story ready to close, eight tasks whose pull requests have all merged but which are still open, seven rows where the sprint table disagrees with the story file, and twenty-five closed documents whose Now is not Nothing. Reconcile all of them without losing a word.
Clear the stale block on the literate template task DONE   2026-10-09 Split every codegen template org into commented literate blocks is BLOCKED behind Fix refdata entity model drift, which is DONE. The block is stale, so the task is returned to the backlog with the dependency recorded as cleared.
Guard the curve-snapshot reads DONE 2026-10-06 2026-10-09 curve_snapshot_handler checked no permission and no curve-snapshot read code was seeded, so any authenticated caller could read every tenant's curve points. The handler now checks marketdata::curve_snapshots:read and the permission is seeded, so the story is closed with no tasks. Promoted from capture D9258D1F.
Validate a curve pillar's tenor codes ABANDONED 2026-10-06   ir_curve_bootstrap_pillar.start_tenor_code and end_tenor_code are undeclared soft references to refdata_tenors, and only curve_role_code is checked, so a typo saves and then throws at bootstrap time inside curve_republish_resolver. Promoted from capture A6472918. Carried to the product backlog inbox at the 2026-10-13 close.
State the test run's prerequisites DONE   2026-10-09 A ctest failure is often a missing prerequisite rather than a regression: the broker is down, the build and the database come from different SQL, or PostgreSQL is out of connection slots. Each has its own signature and none is a code defect.
Implement the membership journeys in ores.web DONE 2026-10-09 2026-10-09 The two Membership journeys run in ores.web: the member picks the party they act for and switches between them, and the tenant administrator reads and corrects the reporting line.
Show who did it in audit DONE   2026-10-09 The audit screen prints account UUIDs where a person needs to read who signed in, and its failed-attempts panel lists every account that has never signed in, each carrying the zero timestamp 1970-01-01 00:00:00Z as if it were an event.
Restore the trading guards the versioned model dropped ABANDONED     Making every trading entity versioned removed the immutable profiles, and two guarantees went with them without a replacement: a trade's reported portfolio no longer has to belong to the trade's party, and a raw update rewrites every version of a row instead of opening a new one. Carried to the product backlog inbox at the 2026-10-13 close.
Export the reporting line write from the browser entry DONE   2026-10-09 The web client imports ReportingLineWrite from the wire protocol's browser entry point, which never re-exported it, so the web bundle does not build on main.
Align the web palette with the reviewed scheme DONE   2026-10-09 The landing-page review argued a deeper, bluer surface ramp and an indigo accent, with role tokens the application's theme lacks: accent tints, an elevation glow, a hue for future content, a radius scale, and micro-label type. Move styles.css onto that scheme, which restyles every screen from one block.
Hotfix: the seeded books have no purpose DONE   2026-10-13 The book artefact seeds omit book_purpose_type and ledger_feed_type, so compass db recreate fails on the not-null constraint.
Hotfix: the audit events miss the sign-ins DONE 2026-10-10 2026-10-10 Multi-party sign-ins record no event, refusals record no tenant, and the time filters cannot be compared, so the audit screen shows almost nothing.
Give the super administrator's landing page its cards DONE   2026-10-10 The system administrator's home shows health figures and a tenant table. It offers no card for the places the person works in. Offer them as cards, as the tenant administrator's home does, and mark the super administrator journeys that have no screen yet.
Publish the currency groups with Acme DONE   2026-10-10 The desk currency groups (G11, Scandies, Antipodeans, Asians, Latams, commodity currencies) and their currency membership are curated in DQ and published to each tenant, so Acme sees them.
Open the web as an Acme persona DONE   2026-10-10 A compass command that opens a separate Chrome instance signed in as a seeded Acme user, chosen by name, by job title and location, or by role and location.
Keep the record screens up to date ABANDONED     Live updates from the change events, a Refresh button on lists and record pages, and a stated behaviour when the record under edit changed. Completes the Updates and refresh section of the entity screen specification. Carried to the product backlog inbox at the 2026-10-13 close.
Name the record in a change event ABANDONED     A change event names no record, so a record screen cannot tell whether a change is its own. Carry the key of the changed row on every entity event, pass it to the browser, and stale a record page only for its own record. Carried to the product backlog inbox at the 2026-10-13 close.
Approve a reporting line change by the proposed manager ABANDONED     A change to a reporting line becomes a four-eyes decision: it is proposed, and the person it would make their manager approves or declines it, like a role request. Carried to the product backlog inbox at the 2026-10-13 close.
End a session when its window closes, not when it is unattended ABANDONED     A session ends when the browser window that held it is gone, and never because a screen sat unattended, so traders can leave their screens open. Presence, not activity, decides. Carried to the product backlog inbox at the 2026-10-13 close.
Group the super administrator's home into cards and subcards DONE 2026-10-10 2026-10-10 The system administrator's home lists nine flat cards, offers Add tenant that the Tenants screen already offers, and shows raw translation keys on the accounts card. Reduce it to four top-level cards, with the operations screens behind one Operations card, as the tenant administrator's home does.
Hotfix: the er-diagram and pgtap checks fail on main DONE   2026-10-10 The local check gate fails on main in two checks. er-diagram fails on 46 RLS_002 warnings under strict mode and on stale diagrams. pgtap fails in outcome_functions_test, refdata_sandbox_test, reporting_official_reports_test and three trading suites.
Make the services screen tell the truth about the installation DONE 2026-10-10 2026-10-10 The web service is an expected service but never sends a heartbeat, so the Operations services screen cannot show it running. The screen also lists instances without summing them up. Report the web service's heartbeat, then summarise the installation: services up, lost and missing, errors, and version skew.
Show the release with its v DONE   2026-10-10 The installation figures state the newest release as 0.0.27, because the services report it without a leading v. The rest of the application writes releases as v0.0.27. Show the figure the same way.
Review the system administrator's home screen DONE   2026-10-10 The screen review of the system administrator's home. Three tabs: Dashboard, Active modules and Upcoming modules. The Dashboard has one panel each for tenants, services, grid and message queue, with one status language. The tenants sentence is gone. Every change from this review goes into this story and its one PR.
Build the four-eyes framework DONE   2026-10-13 Grow the approval request so any gated write raises a request that several functions approve, holds the change until then, and applies it as one transaction, with one set of screens for every kind of request.
Review the tenant administrator's home screen DONE   2026-10-10 Give the tenant administrator's home the same shape as the system administrator's: a header with one status, three tabs, and a dashboard of panels that state their status the same way. The panels are People, Sign-ins, Access requests and Parties. Every change from this review goes into this story and its one PR.
Hotfix: a codegen test remaps the trade target for every later test DONE   2026-10-10 test_soft_fk_target edits the cached table-to-org map in place. ores_trading_trades_tbl then points at the inbox delivery outcome model for the rest of the run, so test_a_routed_table_checks_exactly_the_codes_routed_to_it fails in a full codegen run and passes alone. The local check gate is red on main.
Bring the existing screens to the entity screen specification ABANDONED     Check the currency screens and every other existing screen against the entity screen specification and the record screen standard, and fix each difference in one PR. Carried to the product backlog inbox at the 2026-10-13 close.
Show a curve evolving in ores.web DONE 2026-10-10 2026-10-11 The curve reads are built on the server and no screen reaches them. Give the BFF its routes for the snapshot, slice, evolution and identity reads, and build the watch a curve or surface evolve screen.
Pick a curve from the series a party can see DONE 2026-10-11 2026-10-12 The curve evolution screen makes the person type the identity of the object. List the typed identity of each series the party can see, route the list through the BFF, and pick from it on the screen.
Project the identities of the series a publish seeds DONE 2026-10-12 2026-10-12 A publish from the data quality area inserts market series in SQL, which cannot run the codec, so the series have no identity rows and the resolver and the series list cannot see them. Project them when the publish completes.
Adjust a curve point by hand from the web DONE 2026-10-12 2026-10-12 The repository can key and clear a manual point and no wire operation reaches it. Add the two operations, route them through the BFF, and put the controls on the evolution screen so an operator can correct a node and see the correction marked as theirs.
Order the term axes of a shape by duration DONE   2026-10-13 A composite series stores each axis value in the order its first source states it, so a surface imported from an unordered file shows its tenors out of order on every screen. Order a term axis by duration when the shape is declared.
Plot a surface as a heatmap and slices DONE   2026-10-13 A person who reads a two-axis surface on the evolution screen sees only a table of numbers. Draw the grid as a heatmap and as one line for each value of the first axis, from the snapshot the screen already reads.
Polish the audit sign-ins screen DONE   2026-10-10 Link the username to the profile, use the standard badge for the lock state, and let the failed attempts tab hide accounts that never signed in.
Paint every web badge from the catalogue ABANDONED     Replace the hand-picked Tag tones on state and type values in ores.web with one shared Badge component that paints from the badge catalogue. Carried to the product backlog inbox at the 2026-10-13 close.
Session activity: record the size of every NATS message per server ABANDONED     Count the bytes of every NATS message each server receives and sends, and write the totals to the database at a fixed interval, so the session activity has samples to draw. Carried to the product backlog inbox at the 2026-10-13 close.
Keep counting failed attempts on a locked account ABANDONED     A locked account still counts its failed sign-in attempts and records the address of each, so a run of attempts against a locked account shows as an attack. Carried to the product backlog inbox at the 2026-10-13 close.
Link every reference to its record ABANDONED     Replace the per-screen address functions with one system-wide mechanism, so every foreign key a web screen shows is a link to the page of the record it names. Carried to the product backlog inbox at the 2026-10-13 close.
Hide what system accounts did in a history DONE   2026-10-13 A history can hide the entries made by service accounts, so a reader sees what people did. The server says which actor is a service, so the answer does not depend on what the caller may read.
Show the whole history of a party DONE   2026-10-13 A party's history cannot show the countries, currencies and counterparties it is linked to, because link tables have no history read, and shows its contacts wrongly, because a contact's history is read by its type alone, which every party shares. Give links a history, key every history by the row, and let the party timeline draw both.
Edit a party on a standard entity page ABANDONED     Replace the party wizards with a standard entity page for a party: a list, a page with cards and tabs, and dialogs, built from the shared record parts. A save writes directly for now. The four-eyes approval of party changes belongs to the story Build the four-eyes framework. Carried to the product backlog inbox at the 2026-10-13 close.
Split accounts into open and confidential data DONE   2026-10-13 Split the account into an open table and a confidential table, and share the open table across tenants with the standard shared-reference pattern, so a history can name a service account for every reader.
Sort every list by when it was updated ABANDONED     Every list can be ordered by the time of the latest save, so the newest changes come first. Carried to the product backlog inbox at the 2026-10-13 close.
Run compute nodes on the local network hosts DONE 2026-10-11 2026-10-11 Deploy the current environment's compute node to the machines on the local network, goedel, newton and 192.168.1.11, so each joins an existing environment's grid and runs work. Not every host is always up.
Write the trade journeys DONE 2026-10-11 2026-10-11 Seven use cases for trades: book, amend, review, import, export, record a lifecycle event and group into a structure. Each states the person's goal and the operations it needs; the prototypes that follow serve them with entity pages, not step-by-step screens.
Serve the grid's samples as time series DONE   2026-10-13 The grid stores a sample every 30 seconds, for the grid and for each node, and no read returns more than the newest. Serve both as bucketed time series over a range, and draw the Watch the grid charts from them: load, fleet, throughput, outcomes, the node heatmap and the node state ribbon. Then add the engine's run time and peak memory to the node sample.
Draw the menu by reads alone DONE   2026-10-11 The menu structure page says an area and a card are drawn by the read their screens need, and nothing else. One difference remains: the installation screens (Tenants, Services, Grid, Message queue and Telemetry) are drawn by the session mode. Close that gap, settle the two open points about Rescue access and Market data, and prove that every screen sits in one area with the trail Home, the area, the screen.
Prototype the trade journeys DONE   2026-10-11 Clickable prototypes that serve the seven trade journeys: the trade list and trade page, booking, the ORE import and export workflows, and the structure page. They follow the entity screen specification and link to the existing trade-entry prototype for pricing and structure composition.
Specify the trade screens in the UX standards DONE   2026-10-11 Add the Trades area to the menu page, add the trade, structure and package to the entity screen specification, and bring the trade prototypes to the standard entity protocol: filters from the model, a combo box for the trade type, and booking as one page with the instrument in tabs.
Keep queued grid jobs runnable for as long as they wait DONE   2026-10-12 A grid job can wait in the queue for hours, because the grid is shared and a burst can exceed its capacity. Today a job that waits more than an hour fails on its first step, because the storage token that travels with its assignment lives for one hour. Decide how a queued job stays runnable, how the queue is bounded, and what a person sees while work waits.
Name every synthetic feed by its oresmd reference DONE 2026-10-12 2026-10-12 A synthetic feed names the datum it produces by its own key: an ORE key for the FX spot feed, and a currency, index family and tenor qualifier for the IR curve feed. The rest of market data names a datum by its oresmd URI, so every feed should carry that reference instead.
Filter and search trades through the model DONE   2026-10-12 Declare the filterable, searchable and sortable columns of the trade in its model, so that the standard list filter can find a trade by its counterparty and its trade type and search by type. The trade screens need this and no new operation.
Complete the trade list's filters DONE   2026-10-13 The trade list filters and searches by every need of the review journey: identifier, state, book, date and the enum columns, with reads by trade for the child tables, all through the standard entity protocol.
Model the hand-written IAM tables DONE   2026-10-13 Five IAM tables have no model: account_role, role_permission, auth_event, run_token_issue and session_sample. The codegen drift check compares a model with its output, so it cannot see them and reports the component clean. Each gets a model and is generated, and its callers move to the generated code.
Manage market data bindings DONE   2026-10-13 A user journey, a prototype and the screen to manage the bindings that connect a producer of market data to a party's series, for synthetic data and for real data, where real data is shown and not supported.
Change party from the account menu DONE   2026-10-13 A person who works in several parties has to sign out to act for another. The account menu offers the other parties and switches the open session.
Close the IAM isolation gaps and review account visibility DONE     Two IAM audit tables and three seed profile tables carry a tenant and have no isolation policy, so a session in one tenant can read another tenant's authentication events. The account visibility model built in PR 3124 widens what a tenant reads of the system tenant and what a service reads of a tenant, and was promised a review once its tests passed. This story closes the gaps and records the review as findings.
Make the local checks faster DONE   2026-10-13 The local gate spends most of its time re-rendering components and republishing the whole site on every run, whenever only a fraction of the tree moved.
Run the compute grid on the shared hosts DONE 2026-10-13 2026-10-13 Point this environment's compute nodes at the machines on the local network and fix what co-hosting them exposes.
The bootstrap runs as two workflows, one per administrator DONE 2026-10-09 2026-10-09 Tenant provisioning is one run that a super administrator starts and that also does the new tenant's own setup, so the person who owns the deployment is the one who finishes somebody else's tenant, and a single screen tries to be both wizards. The run is split at the authentication boundary: the super administrator's run creates the tenant and its administrator and hands over, and the tenant administrator's own run initialises the tenant.
Give every prototype its design note DONE 2026-10-09 2026-10-13 Fifty prototypes sit in the tree and eleven carry a design note. Market data's twenty-one have none, so the group is one table where the convention wants a page per prototype.
Write the synthetic market data journeys DONE 2026-10-09 2026-10-09 Six synthetic prototypes sit in the market data group with no journey behind them. Write the journeys that say who authors an FX or IR feed, how a collection is run and watched, and how the model catalogue is kept.
Implement the synthetic market data journeys in ores.web DONE 2026-10-09 2026-10-13 The four synthetic journeys are written and none is built. ores.web could not speak the component at all: synthetic had no TypeScript protocol twin. The twins are committed and the four hand-written operation surfaces are modelled, so the BFF routes are next.
Record system events in a central event log ABANDONED 2026-10-11   Telemetry logs bury the key system events among every log line, and entity change events say a record changed, not that something happened. Extend telemetry with a central event log: a catalogue of event types, a publish API, a store queried by subject, an Operations Events screen, and events in each record's History. Feed runs are the first client. Carried to the product backlog inbox at the 2026-10-13 close.
Organise feeds by provider and scope DONE 2026-10-11 2026-10-13 Feeds have two scopes: system feeds simulating real providers (Bloomberg, Refinitiv, exchanges), run once and consumed by tenants through bindings, and a tenant's or party's test feeds. Organise system feeds by provider and kind in one feed browser that scales to many thousands of feeds, order books among them.
Bring every DQ artefact table onto the canonical model DONE 2026-10-11 2026-10-13 Every DQ artefact table should come from the model of the entity it stages, through one flag. Six come from ores.dq models that duplicate a domain model, nine from ores.dq models whose owner is unsettled, fifteen from the older lookup template and seven from hand-written SQL. Write the guide that says how to do DQ, then move each group onto the canonical model. Junction tables are out of scope.
Sprint health review — System 2 analysis DONE 2026-10-13 2026-10-13 The System 2 health review of sprint 27 at its close: the six dimensions measured and challenged, the bookkeeping reconciled, and one overall RED verdict with the evidence behind it.

4. Achievements

4.1. 2026-10-08: a series identity became joinable in the database

Make a series identity joinable in the database closed on the day it opened. Each codec field of a series' oresmd URI is projected into its own column, written from the same parse that writes the URI, so the database can join and filter a series identity instead of scanning the string.

4.2. 2026-10-10: ores.marketdata gained curves

Add proper curve support to ores.marketdata closed. A curve is a derived series and nothing else; a point carries its provenance, a manual key its author, the operator can write and clear a point, and staleness is visible when a term structure is drawn.

4.3. 2026-10-11: money became exact and the rates family moved to the instrument table rule

Hold money exactly and move the external version on economic change and Rework the rates instruments to the instrument table rule both closed. Money quantities are exact decimals consistent by role, the ORE boundary keeps the document's own spelling, and an economic digest moves a trade's external version only when its economics change. The rates family now sits on a family header, product fact tables, shared children with role codes, and securities keyed by their reference datum.

4.4. 2026-10-11: the grid reached the local network hosts

Run compute nodes on the local network hosts closed: three machines join an existing environment's grid under Quadlet units, 22 wrappers in all, and the grid screen groups every node by machine.

4.5. 2026-10-11: the QA validation runner and the agile tree arrived in ores.web

Bring the QA validation runner to ores.web and Browse the agile tree in ores.web closed. A tester marks each scenario step PASS or FAIL with a note and a screenshot, and the sprint, its stories and tasks, and the backlog buckets are browsable in one Development module that retires the two predecessor views.

4.6. 2026-10-12: an oresmd URL is composed, parsed and edited in the browser

Edit an oresmd URL in a dialog closed. The server holds the grammar and answers parse, compose and describe-schema; the web shows the accepted editor as a modal that a screen calls and that writes the edited URI back. The IR and FX synthetic feed screens call it first.

4.7. 2026-10-13: the credit family, the IAM tables and the last record-screen work

Rework the credit instruments to the instrument table rule, Model the hand-written IAM tables, Show the whole history of a party, Plot a surface as a heatmap and slices and Order the term axes of a shape by duration closed on the last day. The credit family follows the bond pattern, five hand-written IAM tables gained models and generation, a party timeline draws its links and contacts, and a two-axis surface is drawn as a heatmap and as slices.

5. Captures

Real captures filed during this sprint that have not been pulled into a story as tasks — listed here purely for visibility into what the sprint surfaced. Each is an inbox capture (compass capture); triage them at the health review (promote to a story, move to next, or discard).

Capture Tags Description
     

6. Health Review

# Date Day Overall Task
1 2026-10-13 day 9 RED Health review 1 — sprint 27 close analysis

(Run compass-agile-review-sprint to add more rows.)

7. Charts

Charts generated via compass sprint charts. See Sprint health charts for what each chart measures, its purpose, and how to read it.

7.1. PRs & Commits per Day

Dual-axis bar chart. PRs (left axis) and commits (right axis) per day. A high commits-to-PR ratio may indicate scope creep.

prs_commits.png

7.2. Daily Line Churn

Lines added (green) and deleted (red) per day. Building work produces mostly additions; refactoring produces a mix. Days with no churn may indicate blockers.

line_churn.png

7.3. PR Cycle Time

Hours from PR open to merge, one bar per PR. Long bars indicate review bottlenecks. Generated only when PR data is available.

pr_cycle.png

7.4. Cumulative Stories Done

Line chart tracking stories marked DONE during the sprint. Steady upward slope is healthy; plateauing signals a stall.

stories_done.png

8. Retrospective

The sprint 27 release notes carry the full narrative.

8.1. What went well

  • The UX pass landed its largest journey groups: the operations, refdata, synthetic-marketdata and super-administrator journeys run in ores.web, and the record screens gained their party timeline, audit polish and account split.
  • The market data model matured end to end: curves as derived series with provenance and manual keys, a joinable series identity, and an oresmd URL editor that composes, parses and validates an address in the browser.
  • The instrument reworks held their line: the rates family shipped, and the credit family followed the same bond pattern, so the trading model carries typed families instead of polymorphic payloads.
  • The codegen programme kept paying down structural debt: the drift gate now covers the last components, hand-written IAM and DQ tables gained models, and every subject sits on the canonical entity protocol.
  • The close discipline worked: all 42 open stories were split at the close, 21 closed at the scope they delivered with a named successor, and no open story or task was left behind.
  • A hotfix line answered every red build, clearing the local-check failures on main and keeping the continuous builds green.

8.2. What didn't work

  • The sprint ran nine days against a seven-day window and closed RED on load, PR velocity and focus: 3487 commits against a 1000 ceiling, and 569 merged PRs against a 100-band.
  • The mission covered only part of the sprint. The money-exactness, curve, instrument, codegen, isolation and roughly forty hotfix stories serve no clause of the UX mission.
  • Thirty-one stories were still in flight at the review, across at least seven themes, while eleven other worktrees were active at the same time.
  • Bookkeeping drifted under the load: 18 sprint-table rows disagreed with their story files, and three stories were duplicated in the table.

8.3. Improve next sprint

  • Reduce the in-flight story count, and stop carrying the standing infrastructure programme in the same sprint as the UX pass.
  • Split or defer at planning time rather than at the close; the close-time pass cost a whole session.
  • Keep the sprint table in step with the story files as state changes, so the close starts from agreement rather than reconciliation.

9. Release Notes

See release_notes.org for the full narrative.

Emacs 29.3 (Org mode 9.6.15)