From ab355879f00b5d6c38e81491e18fd2ad4b1f9b94 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 13 Nov 2026 17:45:44 +0100 Subject: [PATCH] Bootstrap the seat mesh-delivery so a runner admits its source before the seat list is read (A-362) The catalog half is read through mesh-delivery's source as well as mesh-catalog's verbs, and a runner with an unread seat list admitted only the latter. The bootstrapped copy is mesh-delivery main 21eaa55b's contract file, byte for byte; the tests' seat list and the captured beside copy take the same file. Builds: design 47 G lead answers A-362, A-353 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h --- go/seatlist/bootstrap/mesh-delivery.json | 1190 +++++++++++++++++ go/seatlist/bootstrap_contracts_test.go | 1 + go/seatlist/seatlist_test.go | 8 + .../seatlisttest/seats/mesh-delivery.json | 118 +- .../seats/mesh-delivery/seat.json.captured | 1190 +++++++++++++++++ 5 files changed, 2499 insertions(+), 8 deletions(-) create mode 100644 go/seatlist/bootstrap/mesh-delivery.json create mode 100644 go/testdata/beside/mesh-delivery/modules/mesh-delivery-contracts/seats/mesh-delivery/seat.json.captured diff --git a/go/seatlist/bootstrap/mesh-delivery.json b/go/seatlist/bootstrap/mesh-delivery.json new file mode 100644 index 00000000..93f31549 --- /dev/null +++ b/go/seatlist/bootstrap/mesh-delivery.json @@ -0,0 +1,1190 @@ +{ + "format": 1, + "seat": "mesh-delivery", + "scope": "mesh", + "grain": "whole", + "domain": "Delivery", + "decision": "novox/hq ADR 0239", + "description": "The delivery gate: reads and steers deliveries, merges and the checks that decide them; the merge is made on the operator's Approve once both checks passed.", + "verbs": [ + { + "name": "deliveries", + "description": "Every delivery not final, and those that ended in the last day, one line each: its id (owner/repository@commit), its state, its group, what it waits for and since when. Narrowed by state, repository or group.", + "input": { + "properties": { + "all": { + "description": "\"true\": the final ones of the last thirty days too", + "enum": [ + "true", + "false" + ], + "type": "string" + }, + "group": { + "description": "a group's id (its branch name)", + "type": "string" + }, + "repository": { + "description": "owner/repository", + "type": "string" + }, + "state": { + "description": "one state, e.g. delivering or held", + "type": "string" + } + }, + "type": "object" + }, + "answer": { + "type": "object", + "description": "what deliveries answers, as its description says" + }, + "class": "read" + }, + { + "name": "show", + "description": "One delivery or group whole: its delivery plan (what it builds, what each machine receives, what is not an ordinary send), every transition with when and why, the machine steps of its walk, its group and its order.", + "input": { + "properties": { + "id": { + "description": "a delivery's id, or a group's", + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "answer": { + "type": "object", + "description": "what show answers, as its description says" + }, + "class": "read" + }, + { + "name": "groups", + "description": "Every delivery group: its members in merge order, its check and its state, derived from its members, and the acts the gate said it owes the forge for it, each with its id and its recorded outcome (design 47 *What the gate owes the forge*). With a group, that group alone, and none for a group it does not know: the forge bridge reads a group's members and catches up on what it owes from here, never from the gate's state.", + "input": { + "type": "object", + "properties": { + "all": { + "description": "\"true\": the groups that ended too", + "enum": [ + "true", + "false" + ], + "type": "string" + }, + "group": { + "type": "string", + "description": "one group's id: that group alone, ended or not" + } + } + }, + "answer": { + "type": "object", + "properties": { + "groups": { + "type": "array", + "items": { + "$ref": "#/defs/Group" + } + }, + "error": { + "type": "string", + "description": "why it could not answer at all; a group it does not know is answered with no groups, never an error" + } + } + }, + "class": "read" + }, + { + "name": "source", + "description": "One watched branch's source revision (design 47 *Watched branches and the catalog graph per branch*: source. in place of source.main): The source revision the gate holds: every repository it names, its trunk branch and that trunk's head as the gate merged or seeded it, and the group that moved it last. Read, never written: the node-engines read it to call a reverted build's catch-up tool once per repository, never the gate's state (design 47). Given no branch it answers branches alone, the branch of each source key the gate keeps; given a branch, that branch's source revision (design 47 G section 690).", + "input": { + "type": "object", + "properties": { + "branch": { + "type": "string", + "description": "the watched branch, escaped as a key name is; absent: the answer is the list of the branches the gate keeps a source revision of (design 47 G section 690)" + } + } + }, + "answer": { + "type": "object", + "properties": { + "group": { + "type": "string", + "description": "the group that moved the source revision last; absent before the first" + }, + "revision": { + "type": "integer", + "description": "the source revision's number on the bus; 0 before the first" + }, + "repositories": { + "type": "array", + "items": { + "$ref": "#/defs/SourceHead" + }, + "description": "every repository the source revision names, by name" + }, + "error": { + "type": "string", + "description": "why it could not be read" + }, + "branch": { + "type": "string", + "description": "the watched branch the source revision is of" + }, + "branches": { + "type": "array", + "items": { + "type": "string" + }, + "description": "given no branch: the branch name of each source. key the gate keeps, which every reader of the catalog half follows before the first registrations (design 47 G section 614, section 690)" + } + } + }, + "class": "read" + }, + { + "name": "stalled", + "description": "Every delivery held past its state's bound, with the transition the table lets healer H2 take for it, or none.", + "input": { + "properties": {}, + "type": "object" + }, + "answer": { + "type": "object", + "description": "what stalled answers, as its description says" + }, + "class": "read" + }, + { + "name": "recovery", + "class": "act", + "callers": [ + "operator", + "sessions" + ], + "description": "Mark a merge its author names a recovery: the commit and why; the delivery record is marked recovery with the caller the runtime proves, and recovery-merged is said (design 47 G section 305).", + "input": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "the repository, /" + }, + "commit": { + "type": "string", + "description": "the merge commit" + }, + "why": { + "type": "string", + "description": "why the merge is a recovery" + } + }, + "required": [ + "repository", + "commit", + "why" + ] + }, + "answer": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "the repository" + }, + "commit": { + "type": "string", + "description": "the merge commit" + }, + "recovery": { + "type": "boolean" + }, + "by": { + "type": "string", + "description": "the caller the runtime proved" + } + }, + "required": [ + "commit", + "recovery" + ] + } + } + ], + "family": { + "name": "mesh-delivery.events", + "max-age-days": 7 + }, + "events": [ + { + "name": "owed", + "subject": "owed..", + "keep": { + "max-age-days": 7, + "max-mib": 64 + }, + "body": { + "$ref": "#/defs/Owed" + } + }, + { + "name": "pinned", + "body": { + "$ref": "#/defs/Pins" + } + }, + { + "name": "freed", + "body": { + "$ref": "#/defs/Pins" + } + }, + { + "name": "heads-replaced", + "body": { + "type": "object", + "description": "a candidate's heads replaced or its pull request closed: its graphs mean nothing any more", + "properties": { + "group": { + "type": "string", + "description": "the group" + }, + "heads": { + "type": "string", + "description": "the candidate's heads, 12 hex digits, as its revisions are keyed" + }, + "repository": { + "type": "string", + "description": "the member whose head moved or which closed" + }, + "number": { + "type": "integer", + "description": "its pull request's number" + }, + "head": { + "type": "string", + "description": "its new head; absent when it closed", + "pattern": "^[0-9a-f]{40}$" + }, + "closed": { + "type": "boolean", + "description": "the pull request closed" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "group", + "heads", + "repository", + "number" + ] + } + }, + { + "name": "record-opened", + "body": { + "type": "object", + "description": "a delivery record opened: its merge was taken in, and the watchman times it against 24 hours", + "properties": { + "record": { + "type": "string", + "description": "the record's id" + }, + "milestone": { + "type": "string", + "description": "its milestone" + }, + "forge-made": { + "type": "boolean", + "description": "a merge made at the forge, with no Approve" + }, + "repository": { + "type": "string", + "description": "for a forge-made record, the repository, /" + }, + "pull": { + "type": "integer", + "description": "for a forge-made record, the pull request's number" + }, + "commit": { + "type": "string", + "description": "for a forge-made record, the merge commit" + }, + "branch": { + "type": "string", + "description": "for a forge-made record, the branch the merge moved" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "record", + "milestone" + ] + } + }, + { + "name": "record-ended", + "body": { + "type": "object", + "description": "a delivery record ended: every present node runs its entries", + "properties": { + "record": { + "type": "string", + "description": "the record's id" + }, + "milestone": { + "type": "string", + "description": "its milestone" + }, + "forge-made": { + "type": "boolean", + "description": "a merge made at the forge, with no Approve" + }, + "away": { + "type": "array", + "items": { + "type": "object", + "properties": { + "node": { + "type": "string", + "description": "a node away" + }, + "since": { + "type": "string", + "format": "date-time", + "description": "since when" + } + }, + "required": [ + "node" + ] + }, + "description": "the nodes away, each with since when; it ends without them" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "record", + "milestone" + ] + } + }, + { + "name": "filling", + "body": { + "$ref": "#/defs/Fill" + } + }, + { + "name": "full", + "body": { + "$ref": "#/defs/Fill" + } + }, + { + "name": "room", + "body": { + "$ref": "#/defs/Fill" + } + }, + { + "name": "source-moved", + "subject": "source-moved.", + "body": { + "type": "object", + "description": "a new source revision of a watched branch (design 47 *The verbs*)", + "properties": { + "v": { + "type": "integer" + }, + "branch": { + "type": "string" + }, + "revision": { + "type": "integer" + }, + "group": { + "type": "string", + "description": "the group that moved it, when one did" + }, + "at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "branch", + "revision" + ] + } + }, + { + "name": "recovery-merged", + "body": { + "type": "object", + "description": "a merge named a recovery, which the teller passes on to every channel (design 47 G section 305)", + "properties": { + "v": { + "type": "integer" + }, + "repository": { + "type": "string", + "description": "the repository" + }, + "module": { + "type": "string", + "description": "the module the merge changed, from the delivery record" + }, + "branch": { + "type": "string", + "description": "the watched branch the merge moved" + }, + "commit": { + "type": "string", + "description": "the merge commit" + }, + "why": { + "type": "string", + "description": "why" + }, + "by": { + "type": "string", + "description": "the caller the runtime proved" + }, + "at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "v", + "repository", + "commit", + "why" + ] + } + }, + { + "name": "approval-carried", + "subject": "approval-carried..", + "keep": { + "max-age-days": 90 + }, + "body": { + "type": "object", + "description": "an Approve given before G, carried as that pull request's approval step: said at G's switch for each merges key the old bridge had not performed (design 47 G 542)", + "properties": { + "repository": { + "type": "string", + "description": "the repository" + }, + "pull": { + "type": "integer", + "description": "the pull request's number", + "minimum": 1 + }, + "commit": { + "type": "string", + "description": "the head the Approve named" + }, + "approver": { + "type": "string", + "description": "who approved: the operator" + }, + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "repository", + "pull", + "commit", + "approver", + "at" + ] + } + }, + { + "name": "pins-stated", + "body": { + "type": "object", + "description": "the gate states every pin it holds once its pinned events are said, so an indexer whose state pins was made later hears them all; kept as pinned is, on the seat's family (design 47 G 579, 652)", + "properties": { + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "at" + ] + } + } + ], + "states": [ + { + "name": "source", + "template": "state", + "key-forms": [ + { + "key": "", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "group": { + "type": "string", + "description": "the group that moved it" + }, + "heads": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "repository to the merged head, a full commit" + } + }, + "required": [ + "group", + "heads" + ], + "description": "every repository's merged head; its revision is the mesh's source revision" + }, + "description": "one key per watched branch, written by the holder alone by compare-and-set; deleted when the last registration watching the branch unwatches it" + } + ], + "description": "the mesh's source revision", + "history": 64 + }, + { + "name": "merges", + "template": "state", + "key-forms": [ + { + "key": "", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "group": { + "type": "string" + }, + "ask": { + "type": "string", + "description": "the ask key" + }, + "approved": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "@ to the approved head" + }, + "pulls": { + "type": "array", + "items": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "number": { + "type": "integer" + }, + "head": { + "type": "string" + }, + "state": { + "type": "string", + "description": "merging, merged or refused" + }, + "commit": { + "type": "string" + }, + "words": { + "type": "string" + } + }, + "required": [ + "repository", + "number", + "head", + "state" + ] + } + } + }, + "required": [ + "group", + "ask", + "pulls" + ], + "description": "one group's merge and how far each pull request is" + }, + "description": "a group's merge" + } + ], + "description": "the merges", + "history": 10 + }, + { + "name": "asks", + "template": "state", + "key-forms": [ + { + "key": "merge..", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "group": { + "type": "string" + }, + "heads": { + "type": "array", + "items": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "/" + }, + "number": { + "type": "integer" + }, + "head": { + "type": "string", + "description": "the full commit" + } + }, + "required": [ + "repository", + "number", + "head" + ] + } + }, + "ask": { + "description": "the operator-channel ask as raised" + }, + "asking": { + "type": "integer", + "description": "the number of times it was asked" + } + }, + "required": [ + "group", + "heads", + "ask" + ] + }, + "description": "the ask of the operator for one group at one set of heads" + } + ], + "description": "the asks of the operator for a merge", + "history": 5 + }, + { + "name": "owed", + "template": "state", + "key-forms": [ + { + "key": "...", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "act": { + "type": "string", + "description": "status=, view, note or comment." + }, + "context": { + "type": "string" + }, + "target": { + "type": "string" + }, + "state": { + "type": "string" + }, + "text": { + "type": "string" + }, + "ref": { + "type": "string" + } + }, + "required": [ + "act" + ], + "description": "one act owed to the forge, written by its owner and done by the forge bridge" + }, + "description": "one act owed to the forge" + } + ], + "description": "the acts the gate owes the forge", + "history": 5 + }, + { + "name": "turns", + "template": "state", + "key-forms": [ + { + "key": "", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "repository": { + "type": "string" + }, + "waiting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "group": { + "type": "string" + }, + "heads": { + "type": "string" + }, + "ask": { + "type": "string" + }, + "approved": { + "type": "string", + "format": "date-time", + "description": "when (RFC 3339 time)" + }, + "since": { + "type": "string", + "format": "date-time", + "description": "when (RFC 3339 time)" + }, + "waits-for": { + "type": "string" + }, + "waits-since": { + "type": "string", + "format": "date-time", + "description": "when (RFC 3339 time)" + }, + "step": { + "type": "string" + } + }, + "required": [ + "group", + "heads", + "approved", + "since" + ] + } + } + }, + "required": [ + "repository", + "waiting" + ], + "description": "the merges of a repository in the order they wait for their turn" + }, + "description": "the merges waiting on a repository" + } + ], + "description": "which merge waits for which", + "history": 5 + } + ], + "defs": { + "Owed": { + "type": "object", + "description": "one act the gate owes the forge, said once under its id and safe to repeat at the forge (design 47 *What the gate owes the forge*); the forge bridge performs it through the seat git's verb of the same act", + "properties": { + "id": { + "type": "string", + "description": "the act's id, the same each time it is said again; a comment and a note line carry it, so the forge holds it once" + }, + "act": { + "type": "string", + "enum": [ + "merge", + "status", + "view", + "comment", + "note" + ], + "description": "the act: merge (the seat git's merge-pull), status, view, comment or note" + }, + "repository": { + "type": "string", + "description": "the repository, /", + "minLength": 1 + }, + "number": { + "type": "integer", + "description": "the pull request's number" + }, + "head": { + "type": "string", + "description": "the pull request's head the act is for", + "pattern": "^[0-9a-f]{40}$" + }, + "group": { + "type": "string", + "description": "the delivery group the pull request is a member of, for a merge" + }, + "ask": { + "type": "string", + "description": "the operator's ask that approved the heads, for a merge" + }, + "commit": { + "type": "string", + "description": "the commit a status or a note line is on; the head when absent", + "pattern": "^[0-9a-f]{40}$" + }, + "context": { + "type": "string", + "description": "a status: its context, such as mesh/merge-gate" + }, + "state": { + "type": "string", + "description": "a status: its state, pending, success, failure or error" + }, + "description": { + "type": "string", + "description": "a status: what it says" + }, + "target": { + "type": "string", + "description": "a status: the page it links to" + }, + "text": { + "type": "string", + "description": "a comment or the view: the text, markdown" + }, + "line": { + "type": "string", + "description": "a note line: the one line" + }, + "said": { + "type": "string", + "format": "date-time", + "description": "when the gate first said it" + } + }, + "required": [ + "id", + "act", + "repository", + "number", + "head" + ] + }, + "Act": { + "type": "object", + "description": "an act the gate said for a group, with its recorded outcome once the forge bridge said one", + "properties": { + "owed": { + "$ref": "#/defs/Owed" + }, + "outcome": { + "type": "string", + "enum": [ + "performed", + "refused", + "could not be performed", + "undecodable", + "dropped" + ], + "description": "the outcome the forge bridge said as owed.ended and the gate recorded; absent while unanswered" + }, + "words": { + "type": "string", + "description": "the forge's own words for a refusal, the error for an act that could not be performed, why one is undecodable or dropped" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when the outcome was recorded" + } + }, + "required": [ + "owed" + ] + }, + "Member": { + "type": "object", + "description": "one member of a group: a pull request", + "properties": { + "id": { + "type": "string", + "description": "the member's delivery id" + }, + "repository": { + "type": "string", + "description": "the repository, /" + }, + "number": { + "type": "integer", + "description": "the pull request's number" + }, + "head": { + "type": "string", + "description": "its head", + "pattern": "^[0-9a-f]{40}$" + }, + "base": { + "type": "string", + "description": "the branch it merges into" + }, + "state": { + "type": "string", + "description": "the member's delivery state" + }, + "open": { + "type": "boolean", + "description": "the pull request is open: not merged, closed or final" + } + }, + "required": [ + "id", + "repository", + "number", + "head", + "state" + ] + }, + "Group": { + "type": "object", + "description": "one delivery group: its members, its derived state and the acts the gate said for it", + "properties": { + "id": { + "type": "string", + "description": "the group's id, its branch" + }, + "state": { + "type": "string", + "description": "its state, derived from its members" + }, + "why": { + "type": "string", + "description": "why it is in that state" + }, + "check": { + "type": "string", + "description": "the group's check: its verdict, or asked as " + }, + "members": { + "type": "array", + "items": { + "$ref": "#/defs/Member" + }, + "description": "its members in merge order" + }, + "acts": { + "type": "array", + "items": { + "$ref": "#/defs/Act" + }, + "description": "the acts the gate said for it, each with its id and its recorded outcome; an id said and not answered is the forge bridge's to perform" + } + }, + "required": [ + "id", + "state", + "members", + "acts" + ] + }, + "Fill": { + "type": "object", + "description": "the delivery records' ledger's fill against its cap", + "properties": { + "store": { + "type": "string", + "description": "the kept data, by its name in the holder's manifest" + }, + "bytes": { + "type": "integer" + }, + "cap": { + "type": "integer", + "description": "bytes" + }, + "refused": { + "type": "string", + "description": "what full refuses, such as the next record" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "store", + "bytes", + "cap" + ] + }, + "Pins": { + "type": "object", + "description": "the graph revisions a delivery record starts or stops pointing at", + "properties": { + "record": { + "type": "string", + "description": "the record's id" + }, + "milestone": { + "type": "string", + "description": "the record's milestone" + }, + "catalog": { + "type": "array", + "items": { + "type": "object", + "description": "one catalog graph revision, named by its watched branch and its number on the seat mesh-catalog (revisions are numbered per branch)", + "properties": { + "branch": { + "type": "string", + "description": "the watched branch the revision belongs to" + }, + "revision": { + "type": "integer", + "description": "its number on that branch" + } + }, + "required": [ + "branch", + "revision" + ] + }, + "description": "catalog graph revisions, by watched branch and number on the seat mesh-catalog" + }, + "assignment": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "assignment graph revisions, by their number on the seat mesh-wants" + }, + "why": { + "type": "string", + "description": "on freed: the record ended past its retention, or was removed by hand" + } + }, + "required": [ + "record", + "milestone" + ] + }, + "Ask": { + "type": "object", + "description": "the one Approve ask of a milestone (ADR 0493 \u00a79), said apart from each delivery's transition", + "properties": { + "milestone": { + "type": "string", + "description": "the milestone" + }, + "ask": { + "type": "string", + "description": "the ask's id" + }, + "group": { + "type": "string", + "description": "its delivery group" + }, + "heads": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "repository to the head asked" + }, + "answer": { + "type": "string", + "description": "on answered: approve or decline" + }, + "by": { + "type": "string", + "description": "on answered: who answered" + }, + "why": { + "type": "string", + "description": "on withdrawn: why, such as a new head of a member" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "milestone", + "ask", + "group" + ] + }, + "SourceHead": { + "type": "object", + "description": "one repository of the source revision: its trunk branch and that trunk's head", + "properties": { + "repository": { + "type": "string", + "description": "the repository, /" + }, + "trunk": { + "type": "string", + "description": "its trunk branch, such as main" + }, + "head": { + "type": "string", + "description": "the trunk's head the source revision names", + "pattern": "^[0-9a-f]{40}$" + } + }, + "required": [ + "repository", + "trunk", + "head" + ] + } + } +} diff --git a/go/seatlist/bootstrap_contracts_test.go b/go/seatlist/bootstrap_contracts_test.go index b14290a1..99aa19bd 100644 --- a/go/seatlist/bootstrap_contracts_test.go +++ b/go/seatlist/bootstrap_contracts_test.go @@ -26,6 +26,7 @@ func TestEveryBootstrappedDefinitionEqualsItsContractsFile(t *testing.T) { {"operator-channel", "mesh-contracts", "operator-and-conversation/seats/operator-channel/seat.json"}, {"mesh-catalog", "mesh-delivery", "modules/mesh-delivery-contracts/seats/mesh-catalog/seat.json"}, {"mesh-delivery-checker", "mesh-delivery", "modules/mesh-delivery-contracts/seats/mesh-delivery-checker/seat.json"}, + {"mesh-delivery", "mesh-delivery", "modules/mesh-delivery-contracts/seats/mesh-delivery/seat.json"}, } var have []string for _, d := range Bootstrapped() { diff --git a/go/seatlist/seatlist_test.go b/go/seatlist/seatlist_test.go index 526c53fa..7d915d70 100644 --- a/go/seatlist/seatlist_test.go +++ b/go/seatlist/seatlist_test.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "reflect" + "slices" "strings" "testing" "time" @@ -182,6 +183,13 @@ func TestTheBootstrapIsHeldAndNothingNewIsActedOnUntilTheSeatAnswers(t *testing. if got := len(r.Definitions()); got != len(boot) { t.Fatalf("the reader holds %d definitions, the bootstrap has %d", got, len(boot)) } + // Design 47 G lead answers A-353, A-362: before the list is read the runner admits the seat verbs its catalog half is + // read by, mesh-delivery's source beside mesh-catalog's registrations, revision and entry. + for _, sv := range [][2]string{{"mesh-catalog", "registrations"}, {"mesh-catalog", "revision"}, {"mesh-catalog", "entry"}, {"mesh-delivery", "source"}} { + if !slices.ContainsFunc(r.Definitions()[sv[0]].Verbs, func(v seatdef.Verb) bool { return v.Name == sv[1] }) { + t.Errorf("with the seat list unread the reader holds no %s.%s", sv[0], sv[1]) + } + } st := r.Status() if st.Heard || len(st.Waiting) != len(boot) || st.LastError == "" || st.Health() == "" { t.Fatalf("status %+v: want the seat not heard, every bootstrapped seat waiting, the error and the health said", st) diff --git a/go/seatlist/seatlisttest/seats/mesh-delivery.json b/go/seatlist/seatlisttest/seats/mesh-delivery.json index 4f4bf39f..93f31549 100644 --- a/go/seatlist/seatlisttest/seats/mesh-delivery.json +++ b/go/seatlist/seatlisttest/seats/mesh-delivery.json @@ -101,18 +101,15 @@ }, { "name": "source", - "description": "One watched branch's source revision (design 47 *Watched branches and the catalog graph per branch*: source. in place of source.main): The source revision the gate holds: every repository it names, its trunk branch and that trunk's head as the gate merged or seeded it, and the group that moved it last. Read, never written: the node-engines read it to call a reverted build's catch-up tool once per repository, never the gate's state (design 47).", + "description": "One watched branch's source revision (design 47 *Watched branches and the catalog graph per branch*: source. in place of source.main): The source revision the gate holds: every repository it names, its trunk branch and that trunk's head as the gate merged or seeded it, and the group that moved it last. Read, never written: the node-engines read it to call a reverted build's catch-up tool once per repository, never the gate's state (design 47). Given no branch it answers branches alone, the branch of each source key the gate keeps; given a branch, that branch's source revision (design 47 G section 690).", "input": { "type": "object", "properties": { "branch": { "type": "string", - "description": "the watched branch, escaped as a key name is" + "description": "the watched branch, escaped as a key name is; absent: the answer is the list of the branches the gate keeps a source revision of (design 47 G section 690)" } - }, - "required": [ - "branch" - ] + } }, "answer": { "type": "object", @@ -139,6 +136,13 @@ "branch": { "type": "string", "description": "the watched branch the source revision is of" + }, + "branches": { + "type": "array", + "items": { + "type": "string" + }, + "description": "given no branch: the branch name of each source. key the gate keeps, which every reader of the catalog half follows before the first registrations (design 47 G section 614, section 690)" } } }, @@ -304,6 +308,22 @@ "type": "boolean", "description": "a merge made at the forge, with no Approve" }, + "repository": { + "type": "string", + "description": "for a forge-made record, the repository, /" + }, + "pull": { + "type": "integer", + "description": "for a forge-made record, the pull request's number" + }, + "commit": { + "type": "string", + "description": "for a forge-made record, the merge commit" + }, + "branch": { + "type": "string", + "description": "for a forge-made record, the branch the merge moved" + }, "at": { "type": "string", "format": "date-time", @@ -429,6 +449,14 @@ "type": "string", "description": "the repository" }, + "module": { + "type": "string", + "description": "the module the merge changed, from the delivery record" + }, + "branch": { + "type": "string", + "description": "the watched branch the merge moved" + }, "commit": { "type": "string", "description": "the merge commit" @@ -453,6 +481,65 @@ "why" ] } + }, + { + "name": "approval-carried", + "subject": "approval-carried..", + "keep": { + "max-age-days": 90 + }, + "body": { + "type": "object", + "description": "an Approve given before G, carried as that pull request's approval step: said at G's switch for each merges key the old bridge had not performed (design 47 G 542)", + "properties": { + "repository": { + "type": "string", + "description": "the repository" + }, + "pull": { + "type": "integer", + "description": "the pull request's number", + "minimum": 1 + }, + "commit": { + "type": "string", + "description": "the head the Approve named" + }, + "approver": { + "type": "string", + "description": "who approved: the operator" + }, + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "repository", + "pull", + "commit", + "approver", + "at" + ] + } + }, + { + "name": "pins-stated", + "body": { + "type": "object", + "description": "the gate states every pin it holds once its pinned events are said, so an indexer whose state pins was made later hears them all; kept as pinned is, on the seat's family (design 47 G 579, 652)", + "properties": { + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "at" + ] + } } ], "states": [ @@ -992,9 +1079,24 @@ "catalog": { "type": "array", "items": { - "type": "integer" + "type": "object", + "description": "one catalog graph revision, named by its watched branch and its number on the seat mesh-catalog (revisions are numbered per branch)", + "properties": { + "branch": { + "type": "string", + "description": "the watched branch the revision belongs to" + }, + "revision": { + "type": "integer", + "description": "its number on that branch" + } + }, + "required": [ + "branch", + "revision" + ] }, - "description": "catalog graph revisions, by their number on the seat mesh-catalog" + "description": "catalog graph revisions, by watched branch and number on the seat mesh-catalog" }, "assignment": { "type": "array", diff --git a/go/testdata/beside/mesh-delivery/modules/mesh-delivery-contracts/seats/mesh-delivery/seat.json.captured b/go/testdata/beside/mesh-delivery/modules/mesh-delivery-contracts/seats/mesh-delivery/seat.json.captured new file mode 100644 index 00000000..93f31549 --- /dev/null +++ b/go/testdata/beside/mesh-delivery/modules/mesh-delivery-contracts/seats/mesh-delivery/seat.json.captured @@ -0,0 +1,1190 @@ +{ + "format": 1, + "seat": "mesh-delivery", + "scope": "mesh", + "grain": "whole", + "domain": "Delivery", + "decision": "novox/hq ADR 0239", + "description": "The delivery gate: reads and steers deliveries, merges and the checks that decide them; the merge is made on the operator's Approve once both checks passed.", + "verbs": [ + { + "name": "deliveries", + "description": "Every delivery not final, and those that ended in the last day, one line each: its id (owner/repository@commit), its state, its group, what it waits for and since when. Narrowed by state, repository or group.", + "input": { + "properties": { + "all": { + "description": "\"true\": the final ones of the last thirty days too", + "enum": [ + "true", + "false" + ], + "type": "string" + }, + "group": { + "description": "a group's id (its branch name)", + "type": "string" + }, + "repository": { + "description": "owner/repository", + "type": "string" + }, + "state": { + "description": "one state, e.g. delivering or held", + "type": "string" + } + }, + "type": "object" + }, + "answer": { + "type": "object", + "description": "what deliveries answers, as its description says" + }, + "class": "read" + }, + { + "name": "show", + "description": "One delivery or group whole: its delivery plan (what it builds, what each machine receives, what is not an ordinary send), every transition with when and why, the machine steps of its walk, its group and its order.", + "input": { + "properties": { + "id": { + "description": "a delivery's id, or a group's", + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "answer": { + "type": "object", + "description": "what show answers, as its description says" + }, + "class": "read" + }, + { + "name": "groups", + "description": "Every delivery group: its members in merge order, its check and its state, derived from its members, and the acts the gate said it owes the forge for it, each with its id and its recorded outcome (design 47 *What the gate owes the forge*). With a group, that group alone, and none for a group it does not know: the forge bridge reads a group's members and catches up on what it owes from here, never from the gate's state.", + "input": { + "type": "object", + "properties": { + "all": { + "description": "\"true\": the groups that ended too", + "enum": [ + "true", + "false" + ], + "type": "string" + }, + "group": { + "type": "string", + "description": "one group's id: that group alone, ended or not" + } + } + }, + "answer": { + "type": "object", + "properties": { + "groups": { + "type": "array", + "items": { + "$ref": "#/defs/Group" + } + }, + "error": { + "type": "string", + "description": "why it could not answer at all; a group it does not know is answered with no groups, never an error" + } + } + }, + "class": "read" + }, + { + "name": "source", + "description": "One watched branch's source revision (design 47 *Watched branches and the catalog graph per branch*: source. in place of source.main): The source revision the gate holds: every repository it names, its trunk branch and that trunk's head as the gate merged or seeded it, and the group that moved it last. Read, never written: the node-engines read it to call a reverted build's catch-up tool once per repository, never the gate's state (design 47). Given no branch it answers branches alone, the branch of each source key the gate keeps; given a branch, that branch's source revision (design 47 G section 690).", + "input": { + "type": "object", + "properties": { + "branch": { + "type": "string", + "description": "the watched branch, escaped as a key name is; absent: the answer is the list of the branches the gate keeps a source revision of (design 47 G section 690)" + } + } + }, + "answer": { + "type": "object", + "properties": { + "group": { + "type": "string", + "description": "the group that moved the source revision last; absent before the first" + }, + "revision": { + "type": "integer", + "description": "the source revision's number on the bus; 0 before the first" + }, + "repositories": { + "type": "array", + "items": { + "$ref": "#/defs/SourceHead" + }, + "description": "every repository the source revision names, by name" + }, + "error": { + "type": "string", + "description": "why it could not be read" + }, + "branch": { + "type": "string", + "description": "the watched branch the source revision is of" + }, + "branches": { + "type": "array", + "items": { + "type": "string" + }, + "description": "given no branch: the branch name of each source. key the gate keeps, which every reader of the catalog half follows before the first registrations (design 47 G section 614, section 690)" + } + } + }, + "class": "read" + }, + { + "name": "stalled", + "description": "Every delivery held past its state's bound, with the transition the table lets healer H2 take for it, or none.", + "input": { + "properties": {}, + "type": "object" + }, + "answer": { + "type": "object", + "description": "what stalled answers, as its description says" + }, + "class": "read" + }, + { + "name": "recovery", + "class": "act", + "callers": [ + "operator", + "sessions" + ], + "description": "Mark a merge its author names a recovery: the commit and why; the delivery record is marked recovery with the caller the runtime proves, and recovery-merged is said (design 47 G section 305).", + "input": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "the repository, /" + }, + "commit": { + "type": "string", + "description": "the merge commit" + }, + "why": { + "type": "string", + "description": "why the merge is a recovery" + } + }, + "required": [ + "repository", + "commit", + "why" + ] + }, + "answer": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "the repository" + }, + "commit": { + "type": "string", + "description": "the merge commit" + }, + "recovery": { + "type": "boolean" + }, + "by": { + "type": "string", + "description": "the caller the runtime proved" + } + }, + "required": [ + "commit", + "recovery" + ] + } + } + ], + "family": { + "name": "mesh-delivery.events", + "max-age-days": 7 + }, + "events": [ + { + "name": "owed", + "subject": "owed..", + "keep": { + "max-age-days": 7, + "max-mib": 64 + }, + "body": { + "$ref": "#/defs/Owed" + } + }, + { + "name": "pinned", + "body": { + "$ref": "#/defs/Pins" + } + }, + { + "name": "freed", + "body": { + "$ref": "#/defs/Pins" + } + }, + { + "name": "heads-replaced", + "body": { + "type": "object", + "description": "a candidate's heads replaced or its pull request closed: its graphs mean nothing any more", + "properties": { + "group": { + "type": "string", + "description": "the group" + }, + "heads": { + "type": "string", + "description": "the candidate's heads, 12 hex digits, as its revisions are keyed" + }, + "repository": { + "type": "string", + "description": "the member whose head moved or which closed" + }, + "number": { + "type": "integer", + "description": "its pull request's number" + }, + "head": { + "type": "string", + "description": "its new head; absent when it closed", + "pattern": "^[0-9a-f]{40}$" + }, + "closed": { + "type": "boolean", + "description": "the pull request closed" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "group", + "heads", + "repository", + "number" + ] + } + }, + { + "name": "record-opened", + "body": { + "type": "object", + "description": "a delivery record opened: its merge was taken in, and the watchman times it against 24 hours", + "properties": { + "record": { + "type": "string", + "description": "the record's id" + }, + "milestone": { + "type": "string", + "description": "its milestone" + }, + "forge-made": { + "type": "boolean", + "description": "a merge made at the forge, with no Approve" + }, + "repository": { + "type": "string", + "description": "for a forge-made record, the repository, /" + }, + "pull": { + "type": "integer", + "description": "for a forge-made record, the pull request's number" + }, + "commit": { + "type": "string", + "description": "for a forge-made record, the merge commit" + }, + "branch": { + "type": "string", + "description": "for a forge-made record, the branch the merge moved" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "record", + "milestone" + ] + } + }, + { + "name": "record-ended", + "body": { + "type": "object", + "description": "a delivery record ended: every present node runs its entries", + "properties": { + "record": { + "type": "string", + "description": "the record's id" + }, + "milestone": { + "type": "string", + "description": "its milestone" + }, + "forge-made": { + "type": "boolean", + "description": "a merge made at the forge, with no Approve" + }, + "away": { + "type": "array", + "items": { + "type": "object", + "properties": { + "node": { + "type": "string", + "description": "a node away" + }, + "since": { + "type": "string", + "format": "date-time", + "description": "since when" + } + }, + "required": [ + "node" + ] + }, + "description": "the nodes away, each with since when; it ends without them" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "record", + "milestone" + ] + } + }, + { + "name": "filling", + "body": { + "$ref": "#/defs/Fill" + } + }, + { + "name": "full", + "body": { + "$ref": "#/defs/Fill" + } + }, + { + "name": "room", + "body": { + "$ref": "#/defs/Fill" + } + }, + { + "name": "source-moved", + "subject": "source-moved.", + "body": { + "type": "object", + "description": "a new source revision of a watched branch (design 47 *The verbs*)", + "properties": { + "v": { + "type": "integer" + }, + "branch": { + "type": "string" + }, + "revision": { + "type": "integer" + }, + "group": { + "type": "string", + "description": "the group that moved it, when one did" + }, + "at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "branch", + "revision" + ] + } + }, + { + "name": "recovery-merged", + "body": { + "type": "object", + "description": "a merge named a recovery, which the teller passes on to every channel (design 47 G section 305)", + "properties": { + "v": { + "type": "integer" + }, + "repository": { + "type": "string", + "description": "the repository" + }, + "module": { + "type": "string", + "description": "the module the merge changed, from the delivery record" + }, + "branch": { + "type": "string", + "description": "the watched branch the merge moved" + }, + "commit": { + "type": "string", + "description": "the merge commit" + }, + "why": { + "type": "string", + "description": "why" + }, + "by": { + "type": "string", + "description": "the caller the runtime proved" + }, + "at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "v", + "repository", + "commit", + "why" + ] + } + }, + { + "name": "approval-carried", + "subject": "approval-carried..", + "keep": { + "max-age-days": 90 + }, + "body": { + "type": "object", + "description": "an Approve given before G, carried as that pull request's approval step: said at G's switch for each merges key the old bridge had not performed (design 47 G 542)", + "properties": { + "repository": { + "type": "string", + "description": "the repository" + }, + "pull": { + "type": "integer", + "description": "the pull request's number", + "minimum": 1 + }, + "commit": { + "type": "string", + "description": "the head the Approve named" + }, + "approver": { + "type": "string", + "description": "who approved: the operator" + }, + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "repository", + "pull", + "commit", + "approver", + "at" + ] + } + }, + { + "name": "pins-stated", + "body": { + "type": "object", + "description": "the gate states every pin it holds once its pinned events are said, so an indexer whose state pins was made later hears them all; kept as pinned is, on the seat's family (design 47 G 579, 652)", + "properties": { + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "at" + ] + } + } + ], + "states": [ + { + "name": "source", + "template": "state", + "key-forms": [ + { + "key": "", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "group": { + "type": "string", + "description": "the group that moved it" + }, + "heads": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "repository to the merged head, a full commit" + } + }, + "required": [ + "group", + "heads" + ], + "description": "every repository's merged head; its revision is the mesh's source revision" + }, + "description": "one key per watched branch, written by the holder alone by compare-and-set; deleted when the last registration watching the branch unwatches it" + } + ], + "description": "the mesh's source revision", + "history": 64 + }, + { + "name": "merges", + "template": "state", + "key-forms": [ + { + "key": "", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "group": { + "type": "string" + }, + "ask": { + "type": "string", + "description": "the ask key" + }, + "approved": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "@ to the approved head" + }, + "pulls": { + "type": "array", + "items": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "number": { + "type": "integer" + }, + "head": { + "type": "string" + }, + "state": { + "type": "string", + "description": "merging, merged or refused" + }, + "commit": { + "type": "string" + }, + "words": { + "type": "string" + } + }, + "required": [ + "repository", + "number", + "head", + "state" + ] + } + } + }, + "required": [ + "group", + "ask", + "pulls" + ], + "description": "one group's merge and how far each pull request is" + }, + "description": "a group's merge" + } + ], + "description": "the merges", + "history": 10 + }, + { + "name": "asks", + "template": "state", + "key-forms": [ + { + "key": "merge..", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "group": { + "type": "string" + }, + "heads": { + "type": "array", + "items": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "/" + }, + "number": { + "type": "integer" + }, + "head": { + "type": "string", + "description": "the full commit" + } + }, + "required": [ + "repository", + "number", + "head" + ] + } + }, + "ask": { + "description": "the operator-channel ask as raised" + }, + "asking": { + "type": "integer", + "description": "the number of times it was asked" + } + }, + "required": [ + "group", + "heads", + "ask" + ] + }, + "description": "the ask of the operator for one group at one set of heads" + } + ], + "description": "the asks of the operator for a merge", + "history": 5 + }, + { + "name": "owed", + "template": "state", + "key-forms": [ + { + "key": "...", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "act": { + "type": "string", + "description": "status=, view, note or comment." + }, + "context": { + "type": "string" + }, + "target": { + "type": "string" + }, + "state": { + "type": "string" + }, + "text": { + "type": "string" + }, + "ref": { + "type": "string" + } + }, + "required": [ + "act" + ], + "description": "one act owed to the forge, written by its owner and done by the forge bridge" + }, + "description": "one act owed to the forge" + } + ], + "description": "the acts the gate owes the forge", + "history": 5 + }, + { + "name": "turns", + "template": "state", + "key-forms": [ + { + "key": "", + "value": { + "type": "object", + "properties": { + "v": { + "type": "integer", + "description": "the layout version" + }, + "repository": { + "type": "string" + }, + "waiting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "group": { + "type": "string" + }, + "heads": { + "type": "string" + }, + "ask": { + "type": "string" + }, + "approved": { + "type": "string", + "format": "date-time", + "description": "when (RFC 3339 time)" + }, + "since": { + "type": "string", + "format": "date-time", + "description": "when (RFC 3339 time)" + }, + "waits-for": { + "type": "string" + }, + "waits-since": { + "type": "string", + "format": "date-time", + "description": "when (RFC 3339 time)" + }, + "step": { + "type": "string" + } + }, + "required": [ + "group", + "heads", + "approved", + "since" + ] + } + } + }, + "required": [ + "repository", + "waiting" + ], + "description": "the merges of a repository in the order they wait for their turn" + }, + "description": "the merges waiting on a repository" + } + ], + "description": "which merge waits for which", + "history": 5 + } + ], + "defs": { + "Owed": { + "type": "object", + "description": "one act the gate owes the forge, said once under its id and safe to repeat at the forge (design 47 *What the gate owes the forge*); the forge bridge performs it through the seat git's verb of the same act", + "properties": { + "id": { + "type": "string", + "description": "the act's id, the same each time it is said again; a comment and a note line carry it, so the forge holds it once" + }, + "act": { + "type": "string", + "enum": [ + "merge", + "status", + "view", + "comment", + "note" + ], + "description": "the act: merge (the seat git's merge-pull), status, view, comment or note" + }, + "repository": { + "type": "string", + "description": "the repository, /", + "minLength": 1 + }, + "number": { + "type": "integer", + "description": "the pull request's number" + }, + "head": { + "type": "string", + "description": "the pull request's head the act is for", + "pattern": "^[0-9a-f]{40}$" + }, + "group": { + "type": "string", + "description": "the delivery group the pull request is a member of, for a merge" + }, + "ask": { + "type": "string", + "description": "the operator's ask that approved the heads, for a merge" + }, + "commit": { + "type": "string", + "description": "the commit a status or a note line is on; the head when absent", + "pattern": "^[0-9a-f]{40}$" + }, + "context": { + "type": "string", + "description": "a status: its context, such as mesh/merge-gate" + }, + "state": { + "type": "string", + "description": "a status: its state, pending, success, failure or error" + }, + "description": { + "type": "string", + "description": "a status: what it says" + }, + "target": { + "type": "string", + "description": "a status: the page it links to" + }, + "text": { + "type": "string", + "description": "a comment or the view: the text, markdown" + }, + "line": { + "type": "string", + "description": "a note line: the one line" + }, + "said": { + "type": "string", + "format": "date-time", + "description": "when the gate first said it" + } + }, + "required": [ + "id", + "act", + "repository", + "number", + "head" + ] + }, + "Act": { + "type": "object", + "description": "an act the gate said for a group, with its recorded outcome once the forge bridge said one", + "properties": { + "owed": { + "$ref": "#/defs/Owed" + }, + "outcome": { + "type": "string", + "enum": [ + "performed", + "refused", + "could not be performed", + "undecodable", + "dropped" + ], + "description": "the outcome the forge bridge said as owed.ended and the gate recorded; absent while unanswered" + }, + "words": { + "type": "string", + "description": "the forge's own words for a refusal, the error for an act that could not be performed, why one is undecodable or dropped" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when the outcome was recorded" + } + }, + "required": [ + "owed" + ] + }, + "Member": { + "type": "object", + "description": "one member of a group: a pull request", + "properties": { + "id": { + "type": "string", + "description": "the member's delivery id" + }, + "repository": { + "type": "string", + "description": "the repository, /" + }, + "number": { + "type": "integer", + "description": "the pull request's number" + }, + "head": { + "type": "string", + "description": "its head", + "pattern": "^[0-9a-f]{40}$" + }, + "base": { + "type": "string", + "description": "the branch it merges into" + }, + "state": { + "type": "string", + "description": "the member's delivery state" + }, + "open": { + "type": "boolean", + "description": "the pull request is open: not merged, closed or final" + } + }, + "required": [ + "id", + "repository", + "number", + "head", + "state" + ] + }, + "Group": { + "type": "object", + "description": "one delivery group: its members, its derived state and the acts the gate said for it", + "properties": { + "id": { + "type": "string", + "description": "the group's id, its branch" + }, + "state": { + "type": "string", + "description": "its state, derived from its members" + }, + "why": { + "type": "string", + "description": "why it is in that state" + }, + "check": { + "type": "string", + "description": "the group's check: its verdict, or asked as " + }, + "members": { + "type": "array", + "items": { + "$ref": "#/defs/Member" + }, + "description": "its members in merge order" + }, + "acts": { + "type": "array", + "items": { + "$ref": "#/defs/Act" + }, + "description": "the acts the gate said for it, each with its id and its recorded outcome; an id said and not answered is the forge bridge's to perform" + } + }, + "required": [ + "id", + "state", + "members", + "acts" + ] + }, + "Fill": { + "type": "object", + "description": "the delivery records' ledger's fill against its cap", + "properties": { + "store": { + "type": "string", + "description": "the kept data, by its name in the holder's manifest" + }, + "bytes": { + "type": "integer" + }, + "cap": { + "type": "integer", + "description": "bytes" + }, + "refused": { + "type": "string", + "description": "what full refuses, such as the next record" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "store", + "bytes", + "cap" + ] + }, + "Pins": { + "type": "object", + "description": "the graph revisions a delivery record starts or stops pointing at", + "properties": { + "record": { + "type": "string", + "description": "the record's id" + }, + "milestone": { + "type": "string", + "description": "the record's milestone" + }, + "catalog": { + "type": "array", + "items": { + "type": "object", + "description": "one catalog graph revision, named by its watched branch and its number on the seat mesh-catalog (revisions are numbered per branch)", + "properties": { + "branch": { + "type": "string", + "description": "the watched branch the revision belongs to" + }, + "revision": { + "type": "integer", + "description": "its number on that branch" + } + }, + "required": [ + "branch", + "revision" + ] + }, + "description": "catalog graph revisions, by watched branch and number on the seat mesh-catalog" + }, + "assignment": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "assignment graph revisions, by their number on the seat mesh-wants" + }, + "why": { + "type": "string", + "description": "on freed: the record ended past its retention, or was removed by hand" + } + }, + "required": [ + "record", + "milestone" + ] + }, + "Ask": { + "type": "object", + "description": "the one Approve ask of a milestone (ADR 0493 \u00a79), said apart from each delivery's transition", + "properties": { + "milestone": { + "type": "string", + "description": "the milestone" + }, + "ask": { + "type": "string", + "description": "the ask's id" + }, + "group": { + "type": "string", + "description": "its delivery group" + }, + "heads": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "repository to the head asked" + }, + "answer": { + "type": "string", + "description": "on answered: approve or decline" + }, + "by": { + "type": "string", + "description": "on answered: who answered" + }, + "why": { + "type": "string", + "description": "on withdrawn: why, such as a new head of a member" + }, + "at": { + "type": "string", + "format": "date-time", + "description": "when" + } + }, + "required": [ + "milestone", + "ask", + "group" + ] + }, + "SourceHead": { + "type": "object", + "description": "one repository of the source revision: its trunk branch and that trunk's head", + "properties": { + "repository": { + "type": "string", + "description": "the repository, /" + }, + "trunk": { + "type": "string", + "description": "its trunk branch, such as main" + }, + "head": { + "type": "string", + "description": "the trunk's head the source revision names", + "pattern": "^[0-9a-f]{40}$" + } + }, + "required": [ + "repository", + "trunk", + "head" + ] + } + } +}