mesh-knowledge: review every proposal in a judgement of its own, and serve no review verb (hq issue 425, ADR 0290 as updated)
mesh/merge-gate pass: builds mesh-knowledge → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate pass: builds mesh-knowledge → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
The mesh proves which machine called, not which agent on it (hq issue 365), so a review verb could not tell a reviewer from the author. Each version proposed is now judged by claude-code.claude_code_judge in a separate call that sees only the record, the records it links and the rules: approve accepts (or asks the operator for a needs-operator record), changes keeps it proposed with the findings for its author, and a judgement that cannot be had or read leaves it proposed, says so, and never counts as approval.
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
// bundle the control-node's runtime launches. It holds every decision record and research effort whole — its
|
||||
// fields, its clauses each with a status and a source, its typed links read from both ends, its reasoning — with
|
||||
// every version kept, in a database in the store; answers what holds in one bounded call; takes a record proposed,
|
||||
// checked when it is written, reviewed by someone who did not write it and accepted, on the operator's proven
|
||||
// word when it needs it; and imports hq's records at a commit. stdout is the MCP channel; what this module says,
|
||||
// checked when it is written, reviewed by its own judgement and accepted, on the operator's proven word when it
|
||||
// needs it; and imports hq's records at a commit. stdout is the MCP channel; what this module says,
|
||||
// it says on stderr.
|
||||
//
|
||||
// mesh-knowledge the bundle: the seat's verbs and the health tool
|
||||
@@ -37,7 +37,7 @@ import (
|
||||
const Seat = "knowledge-base"
|
||||
|
||||
// Verbs are the seat's verbs, as the manifest declares and claims them (ADR 0290 rule 6).
|
||||
var Verbs = []string{"ask", "get", "holds", "links", "history", "reserve", "propose", "review", "import", "return"}
|
||||
var Verbs = []string{"ask", "get", "holds", "links", "history", "reserve", "propose", "import", "return"}
|
||||
|
||||
// HealthTool is the module's own tool the node-engine asks how it is.
|
||||
const HealthTool = "knowledge_health"
|
||||
@@ -95,6 +95,7 @@ func newKB(store Store) *KB {
|
||||
|
||||
// serve runs the bundle: the verbs, the operator's answers heard, and the background work.
|
||||
func serve(k *KB, status string) {
|
||||
k.kick = make(chan struct{}, 1)
|
||||
go hear(k)
|
||||
go background(k)
|
||||
if err := stdio.Serve("", append(Tools(k, callerOf), healthTool(status, k.now))); err != nil {
|
||||
@@ -128,11 +129,26 @@ func hear(k *KB) {
|
||||
}
|
||||
|
||||
// background reads the router's record of every waiting ask once a minute, withdraws reservations never
|
||||
// proposed, and drafts and confirms clauses one step at a time.
|
||||
// proposed, reviews every proposal waiting for its review — at once when one is proposed — and drafts and
|
||||
// confirms clauses one step at a time, a review always before the next drafting step: the agent judges one
|
||||
// question at a time, and a proposal does not wait behind the import's drafting.
|
||||
func background(k *KB) {
|
||||
tick := time.NewTicker(time.Minute)
|
||||
defer tick.Stop()
|
||||
time.Sleep(5 * time.Second)
|
||||
review := func() {
|
||||
for {
|
||||
said, err := k.ReviewStep()
|
||||
if err != nil {
|
||||
logf("[mesh-knowledge] %v", err)
|
||||
return
|
||||
}
|
||||
if said == "" {
|
||||
return
|
||||
}
|
||||
logf("[mesh-knowledge] %s", said)
|
||||
}
|
||||
}
|
||||
for {
|
||||
if said, err := k.Reconcile(); err != nil {
|
||||
logf("[mesh-knowledge] reading the operator's answers: %v", err)
|
||||
@@ -146,6 +162,7 @@ func background(k *KB) {
|
||||
} else if n > 0 {
|
||||
logf("[mesh-knowledge] withdrew %d reservation(s) never proposed", n)
|
||||
}
|
||||
review()
|
||||
for {
|
||||
said, err := k.DraftStep()
|
||||
if err != nil {
|
||||
@@ -156,8 +173,12 @@ func background(k *KB) {
|
||||
break
|
||||
}
|
||||
logf("[mesh-knowledge] %s", said)
|
||||
review()
|
||||
}
|
||||
select {
|
||||
case <-tick.C:
|
||||
case <-k.kick:
|
||||
}
|
||||
<-tick.C
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,7 +815,10 @@ func Tools(k *KB, caller func(map[string]any) string) []stdio.Tool {
|
||||
"every reason at once and writing nothing, when it breaks one of the 29 rules that judge one record or its prose — a " +
|
||||
"link to nothing, a clause without a bold lead, a superseded record cited alone, an unknown topic, a retired word. A " +
|
||||
"proposal is revised by proposing it again; an accepted record changes only by a progressive insight (insight: what " +
|
||||
"stood before). Nothing proposed is in force.",
|
||||
"stood before). The knowledge base then reviews each version itself, in a judgement that sees only the record, the " +
|
||||
"records it links and the rules: on approve it is accepted (a record that needs the operator waits for the operator's " +
|
||||
"Approve), on changes it stays proposed with the findings for its author to revise, and when no judgement can be had " +
|
||||
"it stays proposed and says so. Nothing proposed is in force.",
|
||||
Input: schema([]string{"number", "title"}, map[string]any{
|
||||
"kind": kindArg(), "number": integer("the number reserve gave"), "title": text("one line"),
|
||||
"topic": text("for a decision: a topic of the reading order, such as the mesh"),
|
||||
@@ -851,32 +875,6 @@ func Tools(k *KB, caller func(map[string]any) string) []stdio.Tool {
|
||||
}
|
||||
return k.Propose(caller(m), p)
|
||||
}},
|
||||
{Name: Seat + ".review",
|
||||
Description: "Review a proposed record you did not write: approve, or ask for changes with your findings (name the section " +
|
||||
"and clause). Approved, it is accepted and its clauses are in force, and every clause it changes or supersedes moves; a " +
|
||||
"record that needs the operator is asked of the operator first, on a channel that proves who answered, and accepted only " +
|
||||
"on their Approve. Refused: a review by the record's author, a record not proposed, changes without findings.",
|
||||
Input: schema([]string{"number", "verdict"}, map[string]any{"kind": kindArg(), "number": integer("the record's number"),
|
||||
"verdict": map[string]any{"type": "string", "enum": []string{VerdictApprove, VerdictChanges}},
|
||||
"findings": text("what you found, by section and clause")}),
|
||||
Run: func(m map[string]any) (any, error) {
|
||||
a, err := readArgs("review", m, "kind", "number", "verdict", "findings")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := a.key()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := ReviewAsk{Kind: key.Kind, Number: key.Number}
|
||||
if r.Verdict, err = a.str("verdict"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Findings, err = a.str("findings"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return k.Review(caller(m), r)
|
||||
}},
|
||||
{Name: Seat + ".import",
|
||||
Description: "Import hq's decision records and research efforts, read through the records module at the commit its checkout " +
|
||||
"stands at, each whole at its own number as its first version naming that commit. It only creates a record that is not " +
|
||||
|
||||
Reference in New Issue
Block a user