diff --git a/contracts/go/seats/meshdelivery/contract.go b/contracts/go/seats/meshdelivery/contract.go index 8f065371..1ff6201e 100644 --- a/contracts/go/seats/meshdelivery/contract.go +++ b/contracts/go/seats/meshdelivery/contract.go @@ -511,14 +511,16 @@ type GroupsAnswer struct { // SourceInput is what source takes. type SourceInput struct { - // the watched branch, escaped as a key name is - Branch string `json:"branch"` + // 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) + Branch string `json:"branch,omitempty"` } // SourceAnswer is what source answers. type SourceAnswer struct { // the watched branch the source revision is of Branch string `json:"branch,omitempty"` + // 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) + Branches []string `json:"branches,omitempty"` // why it could not be read Error string `json:"error,omitempty"` // the group that moved the source revision last; absent before the first diff --git a/contracts/go/seats/meshdelivery/contract_test.go b/contracts/go/seats/meshdelivery/contract_test.go index b636e28e..e8c68c9f 100644 --- a/contracts/go/seats/meshdelivery/contract_test.go +++ b/contracts/go/seats/meshdelivery/contract_test.go @@ -71,10 +71,14 @@ func TestFixtures(t *testing.T) { decode: func(b []byte) (any, error) { var v GroupsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "groups answers a group it does not know with no groups", subject: "", given: "{}", wire: "{}", decode: func(b []byte) (any, error) { var v GroupsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, - {name: "source is asked with nothing", subject: "", given: "{\"branch\":\"main\"}", wire: "{\"branch\":\"main\"}", + {name: "source is asked for one branch", subject: "", given: "{\"branch\":\"main\"}", wire: "{\"branch\":\"main\"}", + decode: func(b []byte) (any, error) { var v SourceInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, + {name: "source is asked with no branch", subject: "", given: "{}", wire: "{}", decode: func(b []byte) (any, error) { var v SourceInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "source answers each repository's trunk and head", subject: "", given: "{\"branch\":\"main\",\"group\":\"feat/47-G\",\"repositories\":[{\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\",\"trunk\":\"main\"}],\"revision\":42}", wire: "{\"branch\":\"main\",\"group\":\"feat/47-G\",\"repositories\":[{\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\",\"trunk\":\"main\"}],\"revision\":42}", decode: func(b []byte) (any, error) { var v SourceAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, + {name: "source answers the branches it keeps", subject: "", given: "{\"branches\":[\"main\",\"beta\"]}", wire: "{\"branches\":[\"main\",\"beta\"]}", + decode: func(b []byte) (any, error) { var v SourceAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "source answers an error when it cannot be read", subject: "", given: "{\"error\":\"source.main is not readable\"}", wire: "{\"error\":\"source.main is not readable\"}", decode: func(b []byte) (any, error) { var v SourceAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "recovery names a merge and why", subject: "", given: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"why\":\"the live delivery was broken\"}", wire: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"why\":\"the live delivery was broken\"}", diff --git a/contracts/seats/mesh-delivery/fixtures/verbs.json b/contracts/seats/mesh-delivery/fixtures/verbs.json index 3024eff5..4c743636 100644 --- a/contracts/seats/mesh-delivery/fixtures/verbs.json +++ b/contracts/seats/mesh-delivery/fixtures/verbs.json @@ -66,12 +66,17 @@ "given": {} }, { - "name": "source is asked with nothing", + "name": "source is asked for one branch", "of": "verb:source.input", "given": { "branch": "main" } }, + { + "name": "source is asked with no branch", + "of": "verb:source.input", + "given": {} + }, { "name": "source answers each repository's trunk and head", "of": "verb:source.answer", @@ -88,6 +93,16 @@ "branch": "main" } }, + { + "name": "source answers the branches it keeps", + "of": "verb:source.answer", + "given": { + "branches": [ + "main", + "beta" + ] + } + }, { "name": "source answers an error when it cannot be read", "of": "verb:source.answer", diff --git a/contracts/seats/mesh-delivery/seat.json b/contracts/seats/mesh-delivery/seat.json index f39b1399..c3712e59 100644 --- a/contracts/seats/mesh-delivery/seat.json +++ b/contracts/seats/mesh-delivery/seat.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)" } } }, @@ -1074,7 +1078,7 @@ }, "Ask": { "type": "object", - "description": "the one Approve ask of a milestone (ADR 0493 ยง9), said apart from each delivery's transition", + "description": "the one Approve ask of a milestone (ADR 0493 \u00a79), said apart from each delivery's transition", "properties": { "milestone": { "type": "string", diff --git a/contracts/ts/seats/meshdelivery/index.d.ts b/contracts/ts/seats/meshdelivery/index.d.ts index 98ffe486..4d9e7332 100644 --- a/contracts/ts/seats/meshdelivery/index.d.ts +++ b/contracts/ts/seats/meshdelivery/index.d.ts @@ -282,14 +282,16 @@ export interface GroupsAnswer { /** is what source takes. */ export interface SourceInput { - /** the watched branch, escaped as a key name is */ - "branch": string; + /** 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) */ + "branch"?: string; } /** is what source answers. */ export interface SourceAnswer { /** the watched branch the source revision is of */ "branch"?: string; + /** 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) */ + "branches"?: string[]; /** why it could not be read */ "error"?: string; /** the group that moved the source revision last; absent before the first */