C4: the build modules ask the steps state with its objects store in requires; outputs goes
Builds: design 47 G A-254, A-313, A-314, §58, §547 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -151,14 +151,14 @@ func TestManifestRequiresForgeAccountKeepsKeysAndTakesFilesFromTemplates(t *test
|
||||
// detected-steps: the state of the verb steps (design 47 G §326, §414), asked by the template state.
|
||||
// kept-builds: the builds kept for the artifact store's holder (keptbuilds.go), by the template objects (W12.5).
|
||||
kept := map[string]any{"name": "kept-builds", "storage": "object-store", "template": "objects", "options": map[string]any{"max-mib": float64(1024)}}
|
||||
// outputs: a run's answer over what step-ended carries inline, by the template objects (design 47 G A-254).
|
||||
outputs := map[string]any{"name": "outputs", "storage": "object-store", "template": "objects", "options": map[string]any{"max-mib": float64(256)}}
|
||||
// outputs: a run's answer over what step-ended carries inline, in the steps state's objects store (design 47 G A-254, A-313).
|
||||
outputs := map[string]any{"name": "steps", "storage": "key-value", "template": "state", "options": map[string]any{"ttl-seconds": float64(172800), "objects-max-mib": float64(256)}}
|
||||
detected := map[string]any{"name": "detected-steps", "storage": "key-value", "template": "state", "options": map[string]any{"history": float64(1)}}
|
||||
// The findings are asked in requires as a part that is no foundation part asks them (design 47 G §529, A-30).
|
||||
findings := map[string]any{"name": "findings", "storage": "key-value", "template": "state"}
|
||||
findingEvents := map[string]any{"name": "finding-events", "storage": "stream", "template": "events", "options": map[string]any{
|
||||
"events": []any{"finding-written.*", "finding-cleared.*", "findings-stated.*"}, "max-age-days": float64(7), "max-mib": float64(16)}}
|
||||
if want := []any{detected, kept, outputs, "artifact-store", "forge-account", "go-toolchain", "go-package-registry", "node-tools", findings, findingEvents}; !reflect.DeepEqual(m.Requires, want) {
|
||||
if want := []any{outputs, detected, kept, "artifact-store", "forge-account", "go-toolchain", "go-package-registry", "node-tools", findings, findingEvents}; !reflect.DeepEqual(m.Requires, want) {
|
||||
t.Errorf("requires = %v, want %v", m.Requires, want)
|
||||
}
|
||||
keeps := false
|
||||
|
||||
@@ -113,12 +113,12 @@ func TestManifestKeepsItsStatesClaimsItsBuildSeatAndDeclaresItsHealthTool(t *tes
|
||||
for _, s := range m.State {
|
||||
states = append(states, s.Name)
|
||||
// A step's key is per step and dropped after its age, so the bucket cannot fill; a pause has no age.
|
||||
if (s.Name == "steps") != (s.TTLSeconds > 0) {
|
||||
t.Errorf("state %s has ttl-seconds %d: only steps has an age", s.Name, s.TTLSeconds)
|
||||
if s.TTLSeconds > 0 {
|
||||
t.Errorf("state %s has ttl-seconds %d: steps, the one with an age, is asked in requires (A-314)", s.Name, s.TTLSeconds)
|
||||
}
|
||||
}
|
||||
slices.Sort(states)
|
||||
if want := []string{"keys", "pauses", "steps", "toolchains"}; !slices.Equal(states, want) {
|
||||
if want := []string{"keys", "pauses", "toolchains"}; !slices.Equal(states, want) {
|
||||
t.Errorf("state = %v, want %v", states, want)
|
||||
}
|
||||
if len(m.Claims) != 1 || m.Claims[0].Name != Seat {
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
"state": [
|
||||
"toolchains",
|
||||
"keys",
|
||||
{
|
||||
"name": "steps",
|
||||
"ttl-seconds": 172800
|
||||
},
|
||||
"pauses"
|
||||
],
|
||||
"claims": [
|
||||
@@ -89,6 +85,15 @@
|
||||
"build_go_health"
|
||||
],
|
||||
"requires": [
|
||||
{
|
||||
"name": "steps",
|
||||
"storage": "key-value",
|
||||
"template": "state",
|
||||
"options": {
|
||||
"ttl-seconds": 172800,
|
||||
"objects-max-mib": 256
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "detected-steps",
|
||||
"storage": "key-value",
|
||||
@@ -105,14 +110,6 @@
|
||||
"max-mib": 1024
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "outputs",
|
||||
"storage": "object-store",
|
||||
"template": "objects",
|
||||
"options": {
|
||||
"max-mib": 256
|
||||
}
|
||||
},
|
||||
"artifact-store",
|
||||
"forge-account",
|
||||
"go-toolchain",
|
||||
|
||||
@@ -145,8 +145,8 @@ func TestForgeFilesRenderFromTheBoundValuesInTheModulesOwnHome(t *testing.T) {
|
||||
// template in the files/ archive (novox/hq ADR 0349 §2).
|
||||
func TestManifestRequiresForgeAccountKeepsKeysAndTakesFilesFromTemplates(t *testing.T) {
|
||||
m := readForgeManifest(t)
|
||||
// outputs: a run's answer over what step-ended carries inline, by the template objects (design 47 G A-254).
|
||||
outputs := map[string]any{"name": "outputs", "storage": "object-store", "template": "objects", "options": map[string]any{"max-mib": float64(256)}}
|
||||
// outputs: a run's answer over what step-ended carries inline, in the steps state's objects store (design 47 G A-254, A-313).
|
||||
outputs := map[string]any{"name": "steps", "storage": "key-value", "template": "state", "options": map[string]any{"ttl-seconds": float64(172800), "objects-max-mib": float64(256)}}
|
||||
if want := []any{outputs, "forge-account", "rootless-image-build", "node-tools"}; !reflect.DeepEqual(m.Requires, want) {
|
||||
t.Errorf("requires = %v, want %v", m.Requires, want)
|
||||
}
|
||||
|
||||
@@ -118,12 +118,12 @@ func TestManifestKeepsItsStatesClaimsItsBuildSeatAndDeclaresItsHealthTool(t *tes
|
||||
states = append(states, s.Name)
|
||||
// A step's key is per step and dropped after its age, so the bucket cannot fill, and so is a copy's wait, which a
|
||||
// stopped process leaves; a pause has no age.
|
||||
if (s.Name == "steps" || s.Name == MirrorWaitsState) != (s.TTLSeconds > 0) {
|
||||
t.Errorf("state %s has ttl-seconds %d: only steps and %s have an age", s.Name, s.TTLSeconds, MirrorWaitsState)
|
||||
if (s.Name == MirrorWaitsState) != (s.TTLSeconds > 0) {
|
||||
t.Errorf("state %s has ttl-seconds %d: only %s has an age here, steps being asked in requires (A-314)", s.Name, s.TTLSeconds, MirrorWaitsState)
|
||||
}
|
||||
}
|
||||
slices.Sort(states)
|
||||
if want := []string{"keys", MirrorWaitsState, "pauses", "steps"}; !slices.Equal(states, want) {
|
||||
if want := []string{"keys", MirrorWaitsState, "pauses"}; !slices.Equal(states, want) {
|
||||
t.Errorf("state = %v, want %v", states, want)
|
||||
}
|
||||
if len(m.Claims) != 1 || m.Claims[0].Name != Seat || !slices.Equal(m.Claims[0].Serves, []string{"current", "drop", "pause", "resume", "steps", "kept-artifact", "output"}) {
|
||||
@@ -213,9 +213,9 @@ func TestTheModuleRequiresNodeToolsItPullsThrough(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Design 47 G A-254: the module keeps a run's answer over what step-ended carries inline in an object store of its own, asked for
|
||||
// in `requires` by the template objects, and serves it through the verb output.
|
||||
func TestManifestRequiresTheOutputsStore(t *testing.T) {
|
||||
// Design 47 G A-254, A-313, A-314: the module keeps a run's answer over what step-ended carries inline in the steps state's own
|
||||
// objects store, sized in `requires` by the state option objects-max-mib, and serves it through the verb output.
|
||||
func TestManifestRequiresTheStepsStateWithItsObjectsStore(t *testing.T) {
|
||||
raw, err := os.ReadFile(moduleDir + "/module.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -226,7 +226,7 @@ func TestManifestRequiresTheOutputsStore(t *testing.T) {
|
||||
if err := json.Unmarshal(raw, &doc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := map[string]any{"name": "outputs", "storage": "object-store", "template": "objects", "options": map[string]any{"max-mib": float64(256)}}
|
||||
want := map[string]any{"name": "steps", "storage": "key-value", "template": "state", "options": map[string]any{"ttl-seconds": float64(172800), "objects-max-mib": float64(256)}}
|
||||
for _, r := range doc.Requires {
|
||||
if reflect.DeepEqual(r, want) {
|
||||
return
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
],
|
||||
"state": [
|
||||
"keys",
|
||||
{"name": "steps", "ttl-seconds": 172800}, "pauses",
|
||||
"pauses",
|
||||
{"name": "mirror-waits", "ttl-seconds": 172800}
|
||||
],
|
||||
"claims": [
|
||||
@@ -57,7 +57,7 @@
|
||||
"build_image_health"
|
||||
],
|
||||
"requires": [
|
||||
{"name": "outputs", "storage": "object-store", "template": "objects", "options": {"max-mib": 256}},
|
||||
{"name": "steps", "storage": "key-value", "template": "state", "options": {"ttl-seconds": 172800, "objects-max-mib": 256}},
|
||||
"forge-account",
|
||||
"rootless-image-build",
|
||||
"node-tools"
|
||||
|
||||
@@ -110,12 +110,12 @@ func TestManifestKeepsItsStatesClaimsItsBuildSeatAndDeclaresItsHealthTool(t *tes
|
||||
for _, s := range m.State {
|
||||
states = append(states, s.Name)
|
||||
// A step's key is per step and dropped after its age, so the bucket cannot fill; a pause has no age.
|
||||
if (s.Name == "steps") != (s.TTLSeconds > 0) {
|
||||
t.Errorf("state %s has ttl-seconds %d: only steps has an age", s.Name, s.TTLSeconds)
|
||||
if s.TTLSeconds > 0 {
|
||||
t.Errorf("state %s has ttl-seconds %d: steps, the one with an age, is asked in requires (A-314)", s.Name, s.TTLSeconds)
|
||||
}
|
||||
}
|
||||
slices.Sort(states)
|
||||
if want := []string{"keys", "pauses", "steps", "toolchains"}; !slices.Equal(states, want) {
|
||||
if want := []string{"keys", "pauses", "toolchains"}; !slices.Equal(states, want) {
|
||||
t.Errorf("state = %v, want %v", states, want)
|
||||
}
|
||||
if len(m.Claims) != 1 || m.Claims[0].Name != Seat || !slices.Equal(m.Claims[0].Serves, []string{"current", "drop", "pause", "resume", "steps", "kept-artifact", "output"}) {
|
||||
@@ -279,9 +279,9 @@ func TestTheModuleRequiresNodeToolsItPullsThrough(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Design 47 G A-254: the module keeps a run's answer over what step-ended carries inline in an object store of its own, asked for
|
||||
// in `requires` by the template objects, and serves it through the verb output.
|
||||
func TestManifestRequiresTheOutputsStore(t *testing.T) {
|
||||
// Design 47 G A-254, A-313, A-314: the module keeps a run's answer over what step-ended carries inline in the steps state's own
|
||||
// objects store, sized in `requires` by the state option objects-max-mib, and serves it through the verb output.
|
||||
func TestManifestRequiresTheStepsStateWithItsObjectsStore(t *testing.T) {
|
||||
raw, err := os.ReadFile(moduleDir + "/module.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -292,7 +292,7 @@ func TestManifestRequiresTheOutputsStore(t *testing.T) {
|
||||
if err := json.Unmarshal(raw, &doc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := map[string]any{"name": "outputs", "storage": "object-store", "template": "objects", "options": map[string]any{"max-mib": float64(256)}}
|
||||
want := map[string]any{"name": "steps", "storage": "key-value", "template": "state", "options": map[string]any{"ttl-seconds": float64(172800), "objects-max-mib": float64(256)}}
|
||||
for _, r := range doc.Requires {
|
||||
if reflect.DeepEqual(r, want) {
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"state": [
|
||||
"toolchains",
|
||||
"keys",
|
||||
{"name": "steps", "ttl-seconds": 172800}, "pauses"
|
||||
"pauses"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
@@ -57,8 +57,8 @@
|
||||
"build_node_health"
|
||||
],
|
||||
"requires": [
|
||||
{"name": "steps", "storage": "key-value", "template": "state", "options": {"ttl-seconds": 172800, "objects-max-mib": 256}},
|
||||
{"name": "detected-steps", "storage": "key-value", "template": "state", "options": {"history": 1}},
|
||||
{"name": "outputs", "storage": "object-store", "template": "objects", "options": {"max-mib": 256}},
|
||||
"artifact-store",
|
||||
"forge-account",
|
||||
"npm-package-registry",
|
||||
|
||||
@@ -341,6 +341,8 @@ func TestEachTemplateIsPlannedUnderTheModulesNames(t *testing.T) {
|
||||
{name: "state", entry: entry("drafts", catalogue.StorageKeyValue, catalogue.TemplateState, map[string]string{"history": "5"}),
|
||||
objects: "key-value mesh-knowledge_drafts {64 MiB, age 0, history 5, new, size 262144}; object-store mesh-knowledge_drafts-objects {16 MiB, age 0, history 0, new, size 0}",
|
||||
binding: "bucket mesh-knowledge_drafts"},
|
||||
{name: "state naming objects-max-mib and a time to live (A-314): the same bucket as the old section's, its objects store sized", entry: entry("steps", catalogue.StorageKeyValue, catalogue.TemplateState, map[string]string{"ttl-seconds": "172800", "objects-max-mib": "256"}),
|
||||
objects: "key-value mesh-knowledge_steps {64 MiB, age 172800, history 1, new, size 262144}; object-store mesh-knowledge_steps-objects {256 MiB, age 0, history 0, new, size 0}", binding: "bucket mesh-knowledge_steps"},
|
||||
{name: "state naming max-mib (A-283)", entry: entry("drafts", catalogue.StorageKeyValue, catalogue.TemplateState, map[string]string{"max-mib": "8"}),
|
||||
objects: "key-value mesh-knowledge_drafts {8 MiB, age 0, history 1, new, size 262144}; object-store mesh-knowledge_drafts-objects {16 MiB, age 0, history 0, new, size 0}",
|
||||
binding: "bucket mesh-knowledge_drafts"},
|
||||
|
||||
Reference in New Issue
Block a user