mesh-config and mesh-healers record into the hand-act seat alone, and gitea consumes no event of the controller (ADR 0565 clause 11, ADR 0571 clause 13, issues 1953 and 1955)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -2,7 +2,4 @@
|
||||
# the fallback of a recorder (mesh-sdk handacts.Recorder) while the seat mesh-hand-acts has no holder that answers, until
|
||||
# the controller's lease is written to a holder that is no controller. The check of this directory (handacts) refuses any
|
||||
# other, and an entry whose module no longer invokes it: the list only shrinks, and it is empty before the lease write
|
||||
# (novox/hq ADR 0565 §11; issue 1953, issue 774).
|
||||
mesh-config hand-act fallback until the lease write: its sets, clears and held values record through mesh-hand-acts first
|
||||
mesh-config warranted fallback until the lease write: its warrants record through mesh-hand-acts first
|
||||
mesh-healers drill fallback until the lease write: a drill records through mesh-hand-acts first
|
||||
# (novox/hq ADR 0565 §11; issue 1953, issue 774). It is empty: no manifest invokes the controller's log (issue 1953, 1955).
|
||||
|
||||
+7
-17
@@ -9,13 +9,13 @@
|
||||
//
|
||||
// module.gitea.pull.closed — a pull request closed unmerged: the delivery it was is stopped (novox/hq ADR 0239)
|
||||
//
|
||||
// Consumes mesh-controller.checked — a pull request's merge check, judged — and sets it as the head
|
||||
// commit's statuses: `mesh/merge-gate`, the modules of the mesh's graph the change touches, and
|
||||
// Once consumed mesh-controller.checked — a pull request's merge check, judged — and set it as the head
|
||||
// commit's statuses (setVerdict, kept below for a revert, and bound to no event since ADR 0571 clause 13): `mesh/merge-gate`, the modules of the mesh's graph the change touches, and
|
||||
// `mesh/repo-check`, the repository's own merge-check.sh (novox/hq ADR 0237 as amended); with a comment
|
||||
// saying why when the gate is not a pass or the repository's own check failed. Of the two, only those the base
|
||||
// still requires are written (issue 1301): main requires `mesh/check` — the checker's — everywhere, hq included since
|
||||
// ADR 0527 §2, and since R4g no controller judges a merge (its merge gate went with build-agent, ADR 0524 §5), so nothing
|
||||
// publishes mesh-controller.checked and these two are written for no base.
|
||||
// publishes a merge check's verdict, this module consumes no event of the controller, and these two are written for no base.
|
||||
//
|
||||
// Reads mesh-delivery-checker.owed — what the checker owes the forge, mesh/check on each head it judged — by a watch, and
|
||||
// writes it (check.ts; ADR 0521, R4e finding R2-1). No tool writes mesh/check (finding K1), and no event: the watch hands
|
||||
@@ -43,7 +43,7 @@
|
||||
// The polling is deliberately unhurried: an event a minute late is still an event, whereas hammering
|
||||
// the forge for an immediacy nobody asked for is not.
|
||||
|
||||
import { emit, on } from "@novox/mesh-sdk/events";
|
||||
import { emit } from "@novox/mesh-sdk/events";
|
||||
import { registerModuleTools } from "@novox/mesh-sdk/tools";
|
||||
import { statesAnnouncement } from "./kept.js";
|
||||
import { commitStatusTool } from "./delivery.js";
|
||||
@@ -649,19 +649,9 @@ if (gitea) {
|
||||
setTimeout(() => { catchUpAsked = false; void pass(); }, 30_000);
|
||||
};
|
||||
void listenOk.then((ok) => (ok ? pass() : undefined));
|
||||
// Bound again until they hold, and not awaited (bind.ts, issue 1793): the runtime kills a bundle that has not answered its
|
||||
// handshake in 10 s, so the import must end while a refused bind is still asked again.
|
||||
bindInBackground([
|
||||
["mesh-controller.checked", () => on("mesh-controller.checked", (event) => {
|
||||
const c = (event.body ?? {}) as Checked;
|
||||
// A head's own verdict takes its turn after every write of that head's gate already asked for (gate.ts).
|
||||
// A verdict of a check asked before the one now pending is an older run's, and dropped (novox/hq issue 456).
|
||||
if (!c.group && c.owner && c.repo && c.commit) {
|
||||
return gates.verdict(c.owner, c.repo, c.commit, () => setVerdict(client, event), c.id);
|
||||
}
|
||||
return setVerdict(client, event);
|
||||
})],
|
||||
], () => console.log("[gitea] watching for new repositories and merged pull requests"));
|
||||
// No consumer is bound since ADR 0571 clause 13 took the controller's checked out of this module; a consumer added later
|
||||
// is bound again until it holds, and not awaited (bind.ts, issue 1793).
|
||||
bindInBackground([], () => console.log("[gitea] watching for new repositories and merged pull requests"));
|
||||
// The checker's mesh/check, from its owed state (check.ts; ADR 0521): a read not granted yet is said once and asked again,
|
||||
// apart from the binds above, so neither waits for the other.
|
||||
void watchOwed((handler) => state<OwedChange["value"]>(CHECKER_OWED).watch((change) => handler(change)), checks);
|
||||
|
||||
@@ -86,9 +86,6 @@
|
||||
"forge.wiki.changed",
|
||||
"forge.other"
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-controller.checked"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
|
||||
@@ -75,8 +75,9 @@ func (runtimeStore) Read(log string) ([]LogEntry, error) {
|
||||
|
||||
func (runtimeStore) Emit(event string, body any) error { return stdio.Emit(event, body) }
|
||||
|
||||
// recorder records into the hand-act log of the seat mesh-hand-acts, falling back to the controller's while the seat
|
||||
// has no holder that answers and the controller still holds its lease (novox/hq ADR 0565 §11).
|
||||
// recorder records into the hand-act log of the seat mesh-hand-acts (novox/hq ADR 0565 §11). The manifest invokes no verb
|
||||
// of the controller (issue 1953), so the SDK recorder's fall back to the controller's log, while the seat has no holder,
|
||||
// is refused by the bus and said in the answer: nothing is recorded in two logs.
|
||||
var recorder = handacts.Recorder{Ask: stdio.Ask, LeaseAway: func() bool {
|
||||
e, err := stdio.State(LeaseRead).Get(buscompose.ControllerLeaseKey)
|
||||
var raw []byte
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
"invokes": [
|
||||
"seat:mesh-hand-acts.hand-act",
|
||||
"seat:mesh-hand-acts.warranted",
|
||||
"seat:mesh-controller.hand-act",
|
||||
"seat:mesh-controller.warranted",
|
||||
"gitea.gitea_get_pull_request"
|
||||
],
|
||||
"reads": [
|
||||
|
||||
@@ -442,8 +442,8 @@ func TestTheVerbsAndReads(t *testing.T) {
|
||||
if a["acting"] != true || len(a["acts"].([]Attempt)) != 1 || len(a["healers"].([]map[string]any)) != 3 {
|
||||
t.Errorf("healers answered %v", a)
|
||||
}
|
||||
// drill records into mesh-hand-acts as a drill; while that seat has no holder, into the controller's drill until
|
||||
// the lease is handed away (ADR 0565 §11).
|
||||
// drill records into mesh-hand-acts as a drill, and never into the controller's log, whoever holds the lease
|
||||
// (ADR 0565 §11, issue 1955).
|
||||
drills := []struct {
|
||||
name string
|
||||
seatGone bool
|
||||
@@ -452,8 +452,9 @@ func TestTheVerbsAndReads(t *testing.T) {
|
||||
log, err string
|
||||
}{
|
||||
{"into the seat", false, true, map[string]any{"what": "stopped records", "why": "does it raise"}, handacts.LogSeat, ""},
|
||||
{"no holder: the controller's", true, false, map[string]any{"what": "stopped records", "why": "x"}, handacts.LogController, ""},
|
||||
{"no holder, lease away", true, true, map[string]any{"what": "stopped records", "why": "x"}, "", "handed its lease away"},
|
||||
{"into the seat under a controller's lease", false, false, map[string]any{"what": "stopped records", "why": "x"}, handacts.LogSeat, ""},
|
||||
{"no holder: refused, the controller's not asked", true, false, map[string]any{"what": "stopped records", "why": "x"}, "", "nothing was recorded"},
|
||||
{"no holder, lease away", true, true, map[string]any{"what": "stopped records", "why": "x"}, "", "nothing was recorded"},
|
||||
{"says nothing", false, true, map[string]any{}, "", "says what"},
|
||||
}
|
||||
for _, d := range drills {
|
||||
@@ -489,6 +490,11 @@ func TestTheVerbsAndReads(t *testing.T) {
|
||||
case d.log == handacts.LogSeat && !strings.Contains(asked[0], `"verb":"hand-act drill"`):
|
||||
t.Errorf("drill %s asked %v", d.name, asked)
|
||||
}
|
||||
for _, k := range asked {
|
||||
if strings.Contains(k, "mesh-controller") {
|
||||
t.Errorf("drill %s asked the controller: %v", d.name, asked)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, err := w.h.read(WouldState, ""); err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestTheManifestSaysWhatTheCodeDoes(t *testing.T) {
|
||||
}{
|
||||
{"emits (healer-acted is the seat's, said on its subject)", m.Emits, nil},
|
||||
{"consumes", m.Consumes, []string{RaisedEvent, ChangedEvent, RecordedEvent}},
|
||||
{"invokes", m.Invokes, []string{AssertTool, "seat:mesh-hand-acts.hand-act", "seat:mesh-controller.drill"}},
|
||||
{"invokes", m.Invokes, []string{AssertTool, "seat:mesh-hand-acts.hand-act"}},
|
||||
{"reads", m.Reads, []string{LeaseRead, ConditionsRead, HandActsRead}},
|
||||
} {
|
||||
if !slices.Equal(c.got, c.want) {
|
||||
|
||||
@@ -57,8 +57,7 @@ func Tools(h *Healers) []stdio.Tool {
|
||||
}},
|
||||
{Name: DrillTool,
|
||||
Description: "Record a drill: something broken on purpose to see the mesh raise and clear it, with what it " +
|
||||
"tests, in the hand-act log of the seat mesh-hand-acts (the controller's drill while that seat has no " +
|
||||
"holder and the controller holds its lease). A drill is never a repair: S15 never counts it.",
|
||||
"tests, in the hand-act log of the seat mesh-hand-acts. A drill is never a repair: S15 never counts it.",
|
||||
Input: obj(map[string]any{"what": map[string]any{"type": "string", "description": "what was done on purpose"},
|
||||
"why": map[string]any{"type": "string", "description": "what the drill tests"},
|
||||
"condition": map[string]any{"type": "string", "description": "the condition it is meant to raise, if any"}}),
|
||||
@@ -85,8 +84,8 @@ func Tools(h *Healers) []stdio.Tool {
|
||||
}
|
||||
|
||||
// Drill records a drill (ADR 0565 §11, which ends ADR 0564 Limits 1's refusal): through the seat mesh-hand-acts as
|
||||
// the act `hand-act drill`, and while that seat has no holder that answers and the controller still holds its lease,
|
||||
// through the controller's own `drill`, which records it as a drill too. It answers which log took it.
|
||||
// the act `hand-act drill`. The controller's own `drill` is not asked (issue 1955): a seat with no holder that answers
|
||||
// refuses the drill, said whole, and nothing is recorded in a second log.
|
||||
func (h *Healers) Drill(what, why, condition string) (any, error) {
|
||||
if what == "" || why == "" {
|
||||
return nil, errors.New("a drill says what was done on purpose and what it tests: nothing was recorded")
|
||||
@@ -95,27 +94,14 @@ func (h *Healers) Drill(what, why, condition string) (any, error) {
|
||||
return nil, errors.New("the hand-act log cannot be reached from here: nothing was recorded")
|
||||
}
|
||||
body := map[string]any{"what": what, "why": why, "verb": handacts.VerbDrill}
|
||||
controller := map[string]any{"what": what, "why": why}
|
||||
if condition != "" {
|
||||
body["condition"], controller["condition"] = condition, condition
|
||||
body["condition"] = condition
|
||||
}
|
||||
answer, err := h.Ask("seat:"+handacts.Seat+".hand-act", body)
|
||||
if err == nil {
|
||||
return map[string]any{"log": handacts.LogSeat, "answer": answer}, nil
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s.hand-act refused the drill, so nothing was recorded: %w", handacts.Seat, err)
|
||||
}
|
||||
if !handacts.NoResponder(err) {
|
||||
return nil, fmt.Errorf("%s.hand-act refused the drill: %w", handacts.Seat, err)
|
||||
}
|
||||
if acting, _ := h.Acting(); acting {
|
||||
return nil, fmt.Errorf("%s has no holder that answers, and the controller handed its lease away: nothing was "+
|
||||
"recorded (%w)", handacts.Seat, err)
|
||||
}
|
||||
answer, cerr := h.Ask("seat:mesh-controller.drill", controller)
|
||||
if cerr != nil {
|
||||
return nil, fmt.Errorf("%s has no holder that answers (%v), and the controller's drill refused too: %w", handacts.Seat,
|
||||
err, cerr)
|
||||
}
|
||||
return map[string]any{"log": handacts.LogController, "answer": answer}, nil
|
||||
return map[string]any{"log": handacts.LogSeat, "answer": answer}, nil
|
||||
}
|
||||
|
||||
// Heal is the verb heal: one condition judged now by its healer.
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
],
|
||||
"invokes": [
|
||||
"mesh-grants.grants_assert",
|
||||
"seat:mesh-hand-acts.hand-act",
|
||||
"seat:mesh-controller.drill"
|
||||
"seat:mesh-hand-acts.hand-act"
|
||||
],
|
||||
"reads": [
|
||||
"mesh-controller.lease",
|
||||
|
||||
Reference in New Issue
Block a user