DynoInvoice · Traceability

Every commit answers to a requirement.

DynoInvoice is built by AI coding agents. Each commit names the task it implements. Each task traces back to a requirement, its acceptance criteria, an independent review and, where the specification fell short, a recorded ruling. This page shows how to read that record, then walks through eight real examples from the public repository.

How to read a commit

A commit subject looks like this:

[svc-submission] INV-T-6317 decide the hold, release and release-alone of a credit note …

The part in brackets is the service. Next comes the task, then what changed. When the change applies a ruling, the ruling’s ID follows in brackets. The IDs you will meet:

INV-T
Task. One unit of build work with written done-when criteria. Every commit names exactly one.
INV-Q
Design question, raised when a task’s specification has a gap or ambiguity. Its recorded answer is the ruling. Questions about functionality and product direction go to the product owner. Others are ruled by the coordinating agent on a named practice when the answer is clear-cut, and go to the owner when it isn’t. A question ruled before is answered from that record.
INV-REQ
Product requirement.
INV-AC
Acceptance criterion attached to a requirement.
CS
Changeset: a reviewed and published edit to the requirement or task record.
RUL- SUB- PAY- TNC- ING- MDM- SRT-
Error codes declared in the service contracts, catalogued in platform-contracts. RUL-001, for example, means an internal tax code has no mapping in the active rules pack.
API- STK- TPL-
Rules in DynoInvoice’s engineering standards for API design, the technology stack and code templates. The standards themselves are not in the public repository.
VP-
Variation point: a configurable product setting, catalogued in platform-contracts.

The path behind one commit

  1. Requirement and acceptance criteria are written first.
  2. A task is cut from them, with done-when criteria and dependencies.
  3. A readiness gate: no open questions, criteria complete, dependencies merged.
  4. A coding agent implements the task on a merge request, and CI runs.
  5. An independent reviewer agent checks the change against the task’s current done-when criteria, and either posts blocking threads or passes it.
  6. The change merges to main. The public mirror picks it up within the hour.

Any gap found at steps 3 to 5 becomes a design question. It is ruled, the task is revised through a changeset that a separate examiner checks before it is published, and the work resumes. As of 26 October 2026 the project had recorded 1,649 design questions; the owner answered 12% of those answered, and the coordinating agent ruled 81%. The examples below are mostly about those moments.

Eight examples, from requirement to merged code

Each example is taken from the project record and checked against the public repository. Quotes from the product owner are translated from chat.

01 · Rules · INV-T-10210

An unmapped tax code is a blocking refusal, not a default

INV-REQ-364
“A mapping miss MUST raise a blocking exception into a work queue. It MUST NOT silently default to SR or TX.”

The rules contract did not yet declare the error the requirement demanded. Rather than let the evaluation work run ahead of its contract, the coordinating agent ruled (INV-Q-10197) to add error code RUL-001 to both evaluation operations first, as a non-breaking contract change, with each gate probe shown failing before it passed.

Review: Passed.

Commits: 08aea3fe

02 · Rules · INV-T-4965

Rule evaluation leaves a trace of every decision

INV-REQ-777
“Rule evaluation MUST emit a decision trace per document: which rule fired, from which pack version, producing which verdict…”

The first attempt stopped at gaps in the specification, and each was ruled before work resumed. One ruling came from the product owner (INV-Q-5331): of four proposed restrictions on the domain layer, keep three and drop the fourth, because it would stop domain code from referring to ordinary data types and exceptions, “exactly what I have been correcting again and again.” The domain layer now refuses framework imports such as Spring and jOOQ, and may use java.sql types.

Review: Three rounds. The last one wired the architecture gates into the unit-test job, so a gate failure fails the build.

Commits: 921c9eba, f457b071, 0b94d90b, 9dab0027

03 · Evidence · INV-T-5547

The evidence store can be lifted out on its own

INV-REQ-636
“The evidence store MUST be physically separable from the operational stores, with its own retention policy and access control…”

The acceptance criterion said every foreign key, view, function and trigger in the evidence schema may refer only to evidence objects. Two installer functions need a shared hashing function, so the strict wording could never pass. The coding agent stopped rather than loosen the check. The coordinating agent ruled (INV-Q-8331) that the check still covers every function, with exactly two named exceptions.

Review: A dependency-verification job was red. The reviewer’s instruction: “do not disable verification.” It was fixed, then passed.

Commits: b54cc702, 3c3a7802

04 · Evidence and reconciliation · INV-T-8267

Every operation declares who may call it

INV-REQ-1202
“Service-to-service calls MUST authenticate with workload identity … No hop looks up user grants remotely.”

Each operation must state its caller type (end user, signed link or service job), and a lint rule refuses anything else. The technical answer would have widened an existing check, so it went to the product owner, who chose option A (INV-Q-8201): the declaration is mandatory, and any caller type other than end user needs a contract review. The work touched too many modules for one task and was split into slices.

Review: Three “nothing else changes” checks had been done by reading the diff. The reviewer asked for them to be run; they were, and they failed exactly when they should. Then passed.

Commits: f6a3b879

05 · Submission · INV-T-6317

A credit note waits for the invoice it corrects

INV-REQ-709
“submission-svc MUST detect, at enqueue time, that a credit note’s preceding document is in a non-terminal state. When it is, the credit note is held until the original reaches ACKNOWLEDGED, then released.”

Before any code, the record had two gaps: nothing carried the preceding document’s identifier, and nothing said which lifecycle states count as finished. The coordinating agent ruled (INV-Q-6311) to add an optional preceding-document field and a classification of every state, and split the work into three tasks. The hold decision is a pure function that must handle every state explicitly.

Review: The reviewer checked that a missing register entry fails closed and that the release boundary is exact. Passed.

Commits: 0d311032

06 · Tenancy · INV-T-9735

A filing-frequency change announces itself once

INV-REQ-688
“A change mid-period creates a short or long transitional period. The System MUST NOT assume uniform period length, and MUST raise PER-004 for review rather than silently re-bucketing documents.”

The reviewer found a gap in the specification, not in the code: a revision of the task had dropped the line saying the change emits an event, and nothing said when it should fire. The reviewer set out three options and blocked the merge until one was chosen. The coordinating agent ruled (INV-Q-9993): the event is published once, when the period proposal is confirmed.

Review: Blocked pending the ruling, then passed.

Commits: 6ff6974f, f5073ab1

07 · Tenancy · INV-T-4926

A GST group cannot pick a voluntary start date

INV-REQ-717
“…phase assignment for groups MUST therefore be an overridable configuration rather than a derived value.”

The product owner accepted the recommended rules (INV-Q-8911): voluntary dates are set per entity, and a group takes the mandatory or the IRAS-communicated date.

Review: The test that refuses a group’s voluntary date did not exist, so the refusal could have been deleted with every test still green. Writing the missing probes turned up a real hole, a table exemption that accepted one name too many, which now has its own test. Then passed.

Commits: 6fce19ec, 1d82fea1, b330bd25, 81089e3f

08 · Access Point · INV-T-4981

Submitting to the Access Point is a machine step, not a human decision

INV-REQ-539
“The System MUST treat the AP as a replaceable adapter behind a stable internal interface. AP switching is a commercial reality and must not require rework.”

An earlier design refused a submission when the caller’s authorisation data was stale. That collided with another requirement (INV-REQ-1201): a submission is never denied for want of an authorisation decision. The product owner ruled (INV-Q-8339): “transport-svc submitting the invoice payload to the Access Point is a system process in the architecture, not a human operation; why does it still need a separate authorisation check?” Then (INV-Q-8411): “Write it into the standard.” It became API standard rule API-25.

Review: Lint was red while the pre-push check reported all clear, and the unit tests had never actually run. Both were fixed before the review passed.

Commits: eddff2ad, 9d7ea8b7, bc61d806

The full record lives in DynoKore Keel. A public view of it is being built; until then, this page is the way in. For the full record behind a single requirement, see one requirement, and everything recorded about it.

Want your agents to work from a record like this?

Keel keeps requirements, rulings and reviews in one place your coding agents answer to.

Keel early access Watch the commits