The knowledge base's review knows its round: from round 3 only a wrong record asks changes, at round 5 the operator decides (issue 784, ADR 0665)
Claude-Session: https://claude.ai/code/session_01JG73KK8HD1gufnqyFxMFdW
This commit is contained in:
@@ -92,6 +92,9 @@ const AskGlance = 1
|
||||
// again to hold the warrant to it — in the form it was asked in, so an ask made before a form changed is still
|
||||
// held to the words the operator was shown.
|
||||
func composeAsk(r *Record, a *OperatorAsk) oc.Ask {
|
||||
if a.Round > 0 {
|
||||
return changesAsk(r, a)
|
||||
}
|
||||
if a.Form == AskGlance {
|
||||
return glanceAsk(r, a)
|
||||
}
|
||||
@@ -124,6 +127,44 @@ func glanceAsk(r *Record, a *OperatorAsk) oc.Ask {
|
||||
return withOptions(r, a, oc.Ask{ID: a.ID, Headline: headline, Explanation: explanation, Details: details})
|
||||
}
|
||||
|
||||
// changesAsk is the ask of a record whose round-5 review asked changes (ADR 0665 §3): the findings, read at a glance,
|
||||
// and the two answers. It is composed from the record and its ask alone: the findings are the last review's.
|
||||
func changesAsk(r *Record, a *OperatorAsk) oc.Ask {
|
||||
name := r.Key().String()
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "The knowledge base's review of %s asked changes at round %d, the last round: you decide. Approve accepts the version as written; "+
|
||||
"Decline leaves it proposed for its author, and its next review starts at round 1.", name, a.Round)
|
||||
if t := strings.TrimSuffix(strings.TrimSpace(r.Title), "."); shown(t) {
|
||||
fmt.Fprintf(&b, "\n\nIts title: %s.", t)
|
||||
}
|
||||
if n := len(r.Reviews); n > 0 {
|
||||
b.WriteString("\n\nThe findings:")
|
||||
size, hidden := 0, 0
|
||||
for _, f := range strings.Split(r.Reviews[n-1].Findings, "\n") {
|
||||
if f = strings.TrimSpace(f); f == "" {
|
||||
continue
|
||||
}
|
||||
if rs := []rune(f); len(rs) > 300 {
|
||||
f = string(rs[:300]) + "..."
|
||||
}
|
||||
if !shown(f) || size+len(f) > 1500 {
|
||||
hidden++
|
||||
continue
|
||||
}
|
||||
size += len(f)
|
||||
fmt.Fprintf(&b, "\n- %s", f)
|
||||
}
|
||||
if hidden > 0 {
|
||||
fmt.Fprintf(&b, "\n(%d finding(s) not shown here)", hidden)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&b, "\n\nRead it whole with the knowledge base's get, number %d; its fingerprint is %s.", r.Number, fingerprint(r.Digest()))
|
||||
out := withOptions(r, a, oc.Ask{ID: a.ID, Headline: fmt.Sprintf("%s: accept it as written after round %d?", name, a.Round), Explanation: b.String()})
|
||||
out.Options[0].Does = "the version is accepted as written and its clauses are in force"
|
||||
out.Options[1].Does = "the record stays proposed for its author; its next review is round 1"
|
||||
return out
|
||||
}
|
||||
|
||||
// listedAsk is the ask as it was composed before the brief: every clause's lead listed. Composed only to hold
|
||||
// the warrant of an ask made then.
|
||||
func listedAsk(r *Record, a *OperatorAsk) oc.Ask {
|
||||
@@ -180,7 +221,11 @@ func newAskID(r *Record) string {
|
||||
// it. The caller holds the write lock. An ask that could not be made or published is taken back, and the review is
|
||||
// asked again after a pause, counted with the tries before it (tries): the record stays proposed, and is reviewed
|
||||
// at most MostReviewTries times.
|
||||
func (k *KB) askOperator(ctx context.Context, held *Entry, w *Record, by string, tries int) (string, error) {
|
||||
//
|
||||
// round is 0 for a record the review approved. For round MostReviewRounds it is that round: the review asked changes,
|
||||
// and the operator is asked to accept the version as written or leave it proposed (ADR 0665 §3). An ask not made
|
||||
// then takes the round's review back, so its retry is the same round.
|
||||
func (k *KB) askOperator(ctx context.Context, held *Entry, w *Record, by string, tries int, round int) (string, error) {
|
||||
version := held.CurrentVersion
|
||||
if held.Pending != nil {
|
||||
version = held.PendingVersion
|
||||
@@ -189,6 +234,10 @@ func (k *KB) askOperator(ctx context.Context, held *Entry, w *Record, by string,
|
||||
w.Ask = nil
|
||||
w.Judging = failedJudging(tries+1, why, k.now())
|
||||
said := fmt.Sprintf("approved by the knowledge base's review, and %s (%s", why, w.Judging.owedSays())
|
||||
if round > 0 {
|
||||
w.Reviews = w.Reviews[:len(w.Reviews)-1]
|
||||
said = fmt.Sprintf("round %d asked changes, and %s (%s", round, why, w.Judging.owedSays())
|
||||
}
|
||||
e, err := k.Store.Get(ctx, w.Key())
|
||||
if err != nil || e == nil {
|
||||
return "", fmt.Errorf("%s: %s, and that could not be kept (%v)", w.Key(), said, err)
|
||||
@@ -203,17 +252,21 @@ func (k *KB) askOperator(ctx context.Context, held *Entry, w *Record, by string,
|
||||
if k.Asks == nil {
|
||||
return unasked("the operator cannot be asked from here")
|
||||
}
|
||||
oa := &OperatorAsk{ID: newAskID(w), At: k.now(), Version: version, Said: AskWaiting, Form: AskGlance}
|
||||
oa := &OperatorAsk{ID: newAskID(w), At: k.now(), Version: version, Said: AskWaiting, Form: AskGlance, Round: round}
|
||||
ask := composeAsk(w, oa)
|
||||
if err := occ.Check(ask, k.now()); err != nil {
|
||||
return unasked(fmt.Sprintf("the ask could not be made (%v)", err))
|
||||
}
|
||||
w.Ask = oa
|
||||
if err := k.Store.Save(ctx, Version{By: by, At: k.now(), Why: "reviewed: approved; the operator is asked", Record: w, Insight: held.Pending != nil && held.Pending.IsInsight()},
|
||||
asked := "approved; the operator is asked"
|
||||
if round > 0 {
|
||||
asked = fmt.Sprintf("round %d asked changes; the operator is asked", round)
|
||||
}
|
||||
if err := k.Store.Save(ctx, Version{By: by, At: k.now(), Why: "reviewed: " + asked, Record: w, Insight: held.Pending != nil && held.Pending.IsInsight()},
|
||||
held.Pending == nil, false, held.Revision); err != nil {
|
||||
return "", fmt.Errorf("%s: the review could not be kept (%v); the operator was not asked", w.Key(), err)
|
||||
}
|
||||
k.emit(EventReviewed, w, by, "approved; the operator is asked", held.Versions+1)
|
||||
k.emit(EventReviewed, w, by, asked, held.Versions+1)
|
||||
if err := k.Asks.Publish(oc.AcceptSubjectAsk(Module), ask, ask.ID); err != nil {
|
||||
k.logf("[mesh-knowledge] the ask for %s could not be published: %v", w.Key(), err)
|
||||
return unasked(fmt.Sprintf("the operator could not be asked (%v)", err))
|
||||
@@ -351,6 +404,9 @@ func (k *KB) decide(ctx context.Context, e *Entry, w *Record, warrant oc.Warrant
|
||||
case OptionDecline:
|
||||
w = w.Clone()
|
||||
w.Ask.Warrant = occ.Says(warrant)
|
||||
if w.Ask.Round > 0 {
|
||||
w.CountFrom = len(w.Reviews) // the revision's review starts a new count at round 1 (ADR 0665 §3)
|
||||
}
|
||||
return k.endAsk(ctx, e, w, "declined by the operator")
|
||||
}
|
||||
return k.endAsk(ctx, e, w, "was answered with "+option.ID+", which it does not offer")
|
||||
|
||||
Reference in New Issue
Block a user