AM-H1 contract: the node-engine's composition answer names the withheld subjects

A session reads in one composition why a marked tool is not served on a node,
or that the grants part did not answer.

Builds: design 46 7 §6 (the node-engine's composition of the module names the withheld subjects; "withheld unknown: the grants part does not answer"), lead answer A-239 (withheld, withheld-unknown)

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-12 06:26:10 +01:00
parent ff63be3028
commit dbb197b0c7
5 changed files with 87 additions and 0 deletions
+10
View File
@@ -1280,6 +1280,12 @@ type CompositionAnswerWant struct {
Yes string `json:"yes,omitempty"`
}
// CompositionAnswerWithheldItem is a type of the contract.
type CompositionAnswerWithheldItem struct {
Subject string `json:"subject"`
Why string `json:"why"`
}
// CompositionAnswer is what composition answers.
type CompositionAnswer struct {
// the module's last apply that did not end running; absent when none
@@ -1305,6 +1311,10 @@ type CompositionAnswer struct {
Started bool `json:"started"`
// the module's want as the agent holds it; absent when it holds none
Want *CompositionAnswerWant `json:"want,omitempty"`
// the module's marked subjects the grants part withholds from this node's runtime, each with why, read through mesh-grants' verb withheld (design 46 approval mark 6)
Withheld []CompositionAnswerWithheldItem `json:"withheld,omitempty"`
// withheld unknown: the grants part does not answer, when its verb withheld did not answer
WithheldUnknown string `json:"withheld-unknown,omitempty"`
}
// ComposeInput is what compose takes.
+4
View File
@@ -123,6 +123,10 @@ func TestFixtures(t *testing.T) {
decode: func(b []byte) (any, error) { var v EntryAgainInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "entry-again answers what was asked and where it is read", subject: "", given: "{\"asked\":{\"at\":\"2026-11-11T08:00:00Z\",\"by\":\"operator@shanks\",\"fingerprint\":\"b3f1c9\",\"v\":1,\"why\":\"the entry could not be read\"},\"read\":\"first-views\"}", wire: "{\"asked\":{\"at\":\"2026-11-11T08:00:00Z\",\"by\":\"operator@shanks\",\"fingerprint\":\"b3f1c9\",\"v\":1,\"why\":\"the entry could not be read\"},\"read\":\"first-views\"}",
decode: func(b []byte) (any, error) { var v EntryAgainAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "composition names what the grants part withholds of the module", subject: "", given: "{\"composition\":{\"key\":\"\"},\"judged\":{\"judgement\":\"\",\"waits_for_yes\":false,\"words\":\"\"},\"module\":\"zsh\",\"node\":\"workstation\",\"started\":false,\"withheld\":[{\"subject\":\"mesh.mod.zsh.tool.execute\",\"why\":\"its tool runner does not state approval-mark/1\"}]}", wire: "{\"composition\":{\"key\":\"\"},\"judged\":{\"judgement\":\"\",\"waits_for_yes\":false,\"words\":\"\"},\"module\":\"zsh\",\"node\":\"workstation\",\"started\":false,\"withheld\":[{\"subject\":\"mesh.mod.zsh.tool.execute\",\"why\":\"its tool runner does not state approval-mark/1\"}]}",
decode: func(b []byte) (any, error) { var v CompositionAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "composition says withheld unknown when the grants part does not answer", subject: "", given: "{\"composition\":{\"key\":\"\"},\"judged\":{\"judgement\":\"\",\"waits_for_yes\":false,\"words\":\"\"},\"module\":\"zsh\",\"node\":\"workstation\",\"started\":false,\"withheld-unknown\":\"withheld unknown: the grants part does not answer\"}", wire: "{\"composition\":{\"key\":\"\"},\"judged\":{\"judgement\":\"\",\"waits_for_yes\":false,\"words\":\"\"},\"module\":\"zsh\",\"node\":\"workstation\",\"started\":false,\"withheld-unknown\":\"withheld unknown: the grants part does not answer\"}",
decode: func(b []byte) (any, error) { var v CompositionAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
}
for _, c := range cases {
v, err := c.decode([]byte(c.given))
+41
View File
@@ -218,5 +218,46 @@
},
"read": "first-views"
}
},
{
"name": "composition names what the grants part withholds of the module",
"of": "verb:composition.answer",
"given": {
"node": "workstation",
"module": "zsh",
"started": false,
"composition": {
"key": ""
},
"judged": {
"judgement": "",
"waits_for_yes": false,
"words": ""
},
"withheld": [
{
"subject": "mesh.mod.zsh.tool.execute",
"why": "its tool runner does not state approval-mark/1"
}
]
}
},
{
"name": "composition says withheld unknown when the grants part does not answer",
"of": "verb:composition.answer",
"given": {
"node": "workstation",
"module": "zsh",
"started": false,
"composition": {
"key": ""
},
"judged": {
"judgement": "",
"waits_for_yes": false,
"words": ""
},
"withheld-unknown": "withheld unknown: the grants part does not answer"
}
}
]
+23
View File
@@ -494,6 +494,29 @@
"provisioner_account"
],
"description": "of the node's own composition, its own fields beside what runs names"
},
"withheld": {
"type": "array",
"description": "the module's marked subjects the grants part withholds from this node's runtime, each with why, read through mesh-grants' verb withheld (design 46 approval mark 6)",
"items": {
"type": "object",
"properties": {
"subject": {
"type": "string"
},
"why": {
"type": "string"
}
},
"required": [
"subject",
"why"
]
}
},
"withheld-unknown": {
"type": "string",
"description": "withheld unknown: the grants part does not answer, when its verb withheld did not answer"
}
},
"required": [
+9
View File
@@ -913,6 +913,11 @@ export interface CompositionAnswerWant {
"yes"?: string;
}
export interface CompositionAnswerWithheldItem {
"subject": string;
"why": string;
}
/** is what composition answers. */
export interface CompositionAnswer {
/** the module's last apply that did not end running; absent when none */
@@ -938,6 +943,10 @@ export interface CompositionAnswer {
"started": boolean;
/** the module's want as the agent holds it; absent when it holds none */
"want"?: CompositionAnswerWant;
/** the module's marked subjects the grants part withholds from this node's runtime, each with why, read through mesh-grants' verb withheld (design 46 approval mark 6) */
"withheld"?: CompositionAnswerWithheldItem[];
/** withheld unknown: the grants part does not answer, when its verb withheld did not answer */
"withheld-unknown"?: string;
}
/** is what compose takes. */