DynoInvoice · Traceability · Anatomy
Tickets close and chats scroll away. In Keel, a requirement stays connected to its acceptance criteria, the tasks cut from it, every question raised along the way and who answered it, every reviewed change, and the code and tests that implement it. This page opens one DynoInvoice requirement, INV-REQ-738, and lays all of that out.
In plain words: when an invoice names a buyer or seller, DynoInvoice marks whether that party is in the same GST group, or in the same customer account. Whether supplies inside a GST group must be reported is still a question for a tax adviser, so the rule for them ships marked provisional, and a data release can change it without a code change.
Every box below is a record you can open, and every arrow is a link Keel stores. Questions block the tasks that raised them; answering a question publishes a reviewed change that revises the requirement or the task; tasks become merge requests; merge requests become commits; tests carry the key of the criterion they prove.
INV-REQ-738 -has_criterion-> INV-AC-760, INV-AC-761, INV-AC-1823, INV-AC-2783 INV-REQ-738 -refines-> INV-REQ-720, INV-REQ-44 INV-REQ-738 -decided_by-> INV-ADR-2778 INV-T-4912, INV-T-6503, INV-T-8434, INV-T-4943 -implements-> INV-REQ-738 INV-T-4943 -implements-> INV-AC-760, INV-AC-1823 INV-T-4912, INV-T-6503 -implements-> INV-AC-761 INV-T-4968 -implements-> INV-AC-761, INV-AC-2783 (waiting on a dependency) INV-Q-8421, 8423, 8425, 8427, 8480, 8482, 8484, 8486, 8513 -blocks-> INV-T-4943 INV-CS-8432 -resolves-> INV-Q-8421, 8423, 8425, 8427 INV-CS-8487 -resolves-> INV-Q-8480, 8482, 8484, 8486 INV-Q-8427 -ruled_by_precedent-> INV-Q-3324 INV-Q-8486 -ruled_by_precedent-> owner ruling, 22 October INV-CS-8432 -changed-> INV-REQ-738 (revision 14), INV-T-4943 INV-T-4912 -merged_as-> platform-contracts !57 -> d49bed5e, b77af3a8 INV-T-6503 -merged_as-> platform-contracts !136 -> 199b454d INV-T-4943 -merged_as-> svc-masterdata !2 -> 1de1ed9f, cfe12822, 23cf7c8c, f1e61905, 07e79ef3 INV-AC-760 -tested_by-> CounterpartySamenessTest (1 test) INV-AC-1823 -tested_by-> CounterpartySamenessTest (3 tests)
INV-REQ-738 · revision 14
“Counterparty resolution MUST flagsameGroupandsameTenant. The scope pack MUST contain a parameterised rule for intra-group supplies, set provisional until INV-Q-2835 is answered.”
Its behaviour, as now written: master data sets both flags; the rules pack holds the intra-group rule, marked provisional and labelled as inferred; an in-group document is scoped on its own category, like a third-party one, and carries the flag so it can be reprocessed later; both flags are derived from organisation-structure events, with no synchronous call to another service.
It has been published five times. Each revision is a reviewed change with a reason:
| Revision | Date | Change | What changed | Why |
|---|---|---|---|---|
| 6 | 24 Sep | INV-CS-682 | First published form | Part of the domain batch built from the source documents; the owner approved the batch |
| 8 | 25 Sep | INV-CS-2731 | Phase moved from wave 4 to wave 2 | The owner ruled that waves are build-dependency layers for agents (INV-ADR-2732) |
| 12 | 26 Sep | INV-CS-2777 | “Provisional” narrowed to the group flag only; criterion INV-AC-2783 added | Low-confidence rulings from the import were re-decided (INV-ADR-2778) |
| 13 | 22 Oct | INV-CS-8370 | Readiness slots filled; text unchanged | Ruling INV-Q-8368 |
| 14 | 22 Oct | INV-CS-8432 | Behaviour 4 and a data-model sentence added | Ruling INV-Q-8427, after a coding agent stopped to ask |
| Criterion | What it requires | Proved by |
|---|---|---|
| INV-AC-760 | Two entities of one customer account trade with each other: both sides are recorded and paired, with no collision | Test 1 checks the flags; pairing itself belongs to another requirement |
| INV-AC-761 | An in-group standard-rated supply is in scope and an out-of-scope one is not, the same as for a third party; the rule shows it is inferred | Contract half merged (scope-pack-contents.schema.json); its test waits on a rules-service task |
| INV-AC-1823 | X and Y in one GST group, Z in the same account but outside the group: Y gets both flags, Z only the account flag | Tests 1, 2 and 3 |
| INV-AC-2783 | An in-group standard-rated supply is submitted with a warning (GST Act s30(2)), not blocked | Waits on the same rules-service task |
The three tests live in CounterpartySamenessTest.kt, and each name carries the criterion key, which is how the build checks coverage:
INV-AC-1823 INV-AC-760 resolution sets sameTenant and sameGroup from the structure events INV-AC-1823 a retired node, a lower structure version and a group without a GSTN are read as the rules say INV-AC-1823 a node of another tenant with the same UEN gives neither flag
The service’s ac-keys.tsv lists INV-AC-760 and INV-AC-1823 against task INV-T-4943; a gate fails the build if a listed criterion has no test with its key. The two criteria still waiting for tests stay open in Keel until their task is done.
Agents cut four tasks from this requirement. Two of them exist only because a coding agent stopped and asked: the questions it raised turned into new work instead of guesses.
INV-T-4912
Done when: new optional fields for the group and account flags and related data, with valid and invalid samples; the breaking-change check must report additive changes only.
Implements this requirement and nine others. Merged 15 Oct after review found a missing required list, missing invalid samples and a wrong reversibility flag.
INV-T-6503
Done when: five required sections, including the intra-group rule with its provisional flag, proved by valid and invalid samples.
Merged 18 Oct; the reviewer re-ran every sample and three fail-closed probes.
Commits: 199b454d
INV-T-8434
Done when: the master-data service consumes organisation-structure events; the model’s consistency check passes and fails on planted faults.
Created when a coding agent stopped on INV-T-4943. Lives in the design repository, which is not mirrored.
Commits: —
INV-T-4943
Done when: resolve a counterparty with block, hold or warn findings; keep identifier provenance and history; derive both flags from the service’s own structure table; publish the resolved event; refuse an entity outside the caller’s scope.
Merged 22 Oct. That day the coding agent stopped three times, each time on questions that were ruled before it resumed.
Each task owns rows in the service’s operations.tsv; an operation owned by a finished task must not answer “not implemented”.
Questions about functionality and direction go to the product owner. The coordinating agent rules the rest when the answer is clear-cut, citing a named practice or an earlier ruling. Here is how this requirement’s questions went.
INV-Q-4874 · Owner, recommendation not taken
Early contracts lacked fields later work needed: how should they be completed if contracts are “frozen” early? The agent recommended follow-up tasks. The owner chose otherwise: “Contract-first means the contract is settled first, then implemented; it does not require completion in the first wave. Contracts are supplemented when they are needed.” Task INV-T-4912 exists because of this answer.
INV-Q-2835 · Open, waiting on a tax adviser
Must supplies inside a GST group be reported? Nobody inside the project can settle this, so the rule ships provisional and the question stays visibly open.
INV-Q-1736 · Coordinating agent
How to scope in-group supplies: pass them through as for a third party, marked provisional. Re-decided two days later to narrow “provisional” to the group flag and add a warning rather than a block, citing GST Act s30(2).
INV-Q-8427 · Coordinating agent, by precedent
Where do the flags come from? From a read model the service owns, fed by structure events, following an earlier ruling on version ordering (INV-Q-3324) and the published rule that this service makes no outward calls. A synchronous call to the tenancy service was rejected.
INV-Q-8486 · Coordinating agent, by precedent
No operation existed for the ingestion service to write counterparties: add one on the existing edge, following the owner’s ruling of 22 October that “who may call whom, and when, must follow the system architecture design, not a mechanical judgement.”
INV-Q-5203 · Coordinating agent, by precedent
Six contract-shape choices, each copied from a sibling contract: “every choice has a published precedent.”
INV-Q-8368 · Coordinating agent
Eleven requirements lacked criteria, so the task could not be marked done. Ruling: write the criteria. A waiver was rejected, because “a waiver of a check is the owner’s.”
INV-Q-8513 · Coordinating agent
Where should the “outside your scope” refusal come from? One generic filter driven by the contract. Inferring it from property names was rejected: “a guess in a security filter fails open or over-refuses.”
The other eight (INV-Q-5189, 6492, 8421, 8423, 8425, 8480, 8482, 8484) were ruled by the coordinating agent with a named reason, most of them on the day a coding agent stopped to ask.
A revision of task INV-T-4943 (INV-CS-7893) came back with four findings: a line still cited a removed criterion; “the set the policy port holds” named no set, so it couldn’t be verified; a criterion said no merge request existed when one did; and an example used a request body the service now refuses. All four were fixed and approved four minutes later.
On the contract, a request body had no required list and invalid samples were missing (fixed in b77af3a8). On the service, an operation took six parameters where the standard allows five; the finding said to group them into a value type and “do not add a suppression or a baseline entry”. A dependency-verification gap was also fixed (f1e61905, 07e79ef3).
Across the four merge requests: eight review threads, five of them must-fix; two needed a fix round. On the two that passed first time, the reviewer re-ran the samples and planted a fault to confirm the checks catch it.
Nothing here was reconstructed for this page. The requirement, its five revisions, the sixteen questions and their answers, the reviewed changes and the links between them are records in Keel; the code, tests and commits are in the public repository. A coding agent picking up any of these tasks, or a person asking in six months why the group flag is provisional, gets the same answer from the same record.
That is what we mean by governing requirements rather than managing code: the requirement is the source of truth, and the code is a mapping of it that can be checked.
More: when green isn’t enough · why does this line exist? · reviewing like an attacker · when the spec runs out · eight shorter traces from requirement to merged code · when a decision changes · the DynoInvoice repository