package stdio import ( "bufio" "encoding/json" "io" "strings" "sync" "testing" "time" ) // historying serves a bundle whose one tool, "history", runs run, answering each mesh/state ask with // answer beside the loop, as the runtime does; it returns what the bundle asked. func historying(t *testing.T, answer func(message) map[string]any, run func()) []message { t.Helper() t.Setenv(ServedAs, "issues") inR, inW := io.Pipe() outR, outW := io.Pipe() go func() { _ = ServeOn("", []Tool{{Name: "history", Run: func(map[string]any) (any, error) { run(); return "done", nil }}}, inR, outW) }() var wmu, amu sync.Mutex var asked []message send := func(m map[string]any) { m["jsonrpc"] = "2.0" b, _ := json.Marshal(m) wmu.Lock() defer wmu.Unlock() _, _ = inW.Write(append(b, '\n')) } done := make(chan struct{}) go func() { lines := bufio.NewScanner(outR) for lines.Scan() { var m message if json.Unmarshal(lines.Bytes(), &m) != nil { continue } if strings.HasPrefix(m.Method, "mesh/state.") { amu.Lock() asked = append(asked, m) amu.Unlock() a := answer(m) a["id"] = m.ID send(a) continue } if m.Method == "" { close(done) return } } }() send(map[string]any{"id": 1, "method": "tools/call", "params": map[string]any{"name": "history"}}) t.Cleanup(func() { _ = inW.Close() }) select { case <-done: case <-time.After(10 * time.Second): t.Fatal("the bundle did not answer") } amu.Lock() defer amu.Unlock() return asked } // History asks mesh/state.history with the state and the key alone, and hands back every kept value oldest // first, a delete with its null value; nothing kept is an empty history; a refusal is the runtime's error // (novox/hq ADR 0307). func TestHistoryIsEveryKeptValueOldestFirst(t *testing.T) { kept := []map[string]any{ {"key": "401", "value": map[string]any{"status": "open"}, "revision": 4, "op": "put", "at": "2026-10-10T19:46:00Z"}, {"key": "401", "value": map[string]any{"status": "fixing"}, "revision": 9, "op": "put", "at": "2026-10-11T08:01:02Z"}, {"key": "401", "value": nil, "revision": 12, "op": "delete", "at": "2026-10-11T09:30:00+02:00"}, } var got, none, null []StateRevision var refused error asked := historying(t, func(m message) map[string]any { var p map[string]any _ = json.Unmarshal(m.Params, &p) switch { case p["state"] != "issues": return map[string]any{"error": map[string]any{"code": -32000, "message": "issues was issued no state " + p["state"].(string)}} case p["key"] == "401": return map[string]any{"result": kept} case p["key"] == "402": return map[string]any{"result": nil} } return map[string]any{"result": []any{}} }, func() { var err error if got, err = State("issues").History("401"); err != nil { t.Errorf("history of 401: %v", err) } if none, err = State("issues").History("999"); err != nil { t.Errorf("history of 999: %v", err) } if null, err = State("issues").History("402"); err != nil { t.Errorf("history of 402: %v", err) } var h []StateRevision h, refused = State("elsewhere.issues").History("401") if h != nil { t.Errorf("a refused history handed back %v", h) } }) if len(asked) != 4 { t.Fatalf("asked %d times, not 4", len(asked)) } var p map[string]any _ = json.Unmarshal(asked[0].Params, &p) if asked[0].Method != "mesh/state.history" || p["state"] != "issues" || p["key"] != "401" || len(p) != 2 { t.Fatalf("asked %s %v", asked[0].Method, p) } if len(got) != 3 { t.Fatalf("history of 401 is %d values, not 3: %+v", len(got), got) } want := []struct { rev uint64 op string value string at time.Time }{ {4, "put", `{"status":"open"}`, time.Date(2026, 10, 10, 19, 46, 0, 0, time.UTC)}, {9, "put", `{"status":"fixing"}`, time.Date(2026, 10, 11, 8, 1, 2, 0, time.UTC)}, {12, "delete", `null`, time.Date(2026, 10, 11, 7, 30, 0, 0, time.UTC)}, } for i, w := range want { r := got[i] if r.Key != "401" || r.Revision != w.rev || r.Op != w.op || string(r.Value) != w.value || !r.At.Equal(w.at) { t.Fatalf("value %d is %+v, not %+v", i, r, w) } } if none == nil || len(none) != 0 || null == nil || len(null) != 0 { t.Fatalf("nothing kept read as %v and %v, not an empty history", none, null) } if refused == nil || !strings.Contains(refused.Error(), "issued no state elsewhere.issues") { t.Fatalf("a state not issued answered %v", refused) } }