Hold an active effort's new version to the dated rules of the day it is proposed (hq issue 844)

This commit is contained in:
2026-10-15 21:26:55 +02:00
parent 24d05701d3
commit ebfec39937
2 changed files with 55 additions and 1 deletions
@@ -3,6 +3,7 @@ package main
import (
"strings"
"testing"
"time"
)
// effortAsk is a research effort proposal with the given documents.
@@ -76,3 +77,49 @@ func TestAGraduatedEffortAndADecisionStillTakeOnlyAnInsight(t *testing.T) {
t.Fatalf("a decision took a plain version: %v", err)
}
}
// An old active effort's new text is held to the rules as of the day it is proposed, not the day the effort began.
func TestANewVersionOfAnOldActiveEffortIsHeldToTodaysRules(t *testing.T) {
w := imported(t, newMemStore())
w.clock = time.Date(2026, 10, 1, 9, 0, 0, 0, time.UTC)
r, err := w.k.ReserveNumber("author@g14", KindResearch, "an old effort")
if err != nil {
t.Fatal(err)
}
overview := Section{Name: "00-overview.md", Text: "What an inference layer would be."}
first := effortAsk(r.Number, StatusActive, overview)
first.Date = "2026-10-01"
w.accepted(t, "author@g14", first)
w.clock = time.Date(2026, 10, 15, 9, 0, 0, 0, time.UTC)
next := effortAsk(r.Number, StatusActive, overview, Section{Name: "01-findings.md", Text: "The control plane wrote them."})
next.Date = "2026-10-01"
if _, err := w.k.Propose("author@g14", next); err == nil || !strings.Contains(err.Error(), "retired-word") {
t.Fatalf("a retired word in new text of an old effort: %v", err)
}
}
func TestAChangesVerdictLeavesTheServedVersionServedAndGraduatingNeedsABecameLink(t *testing.T) {
w := imported(t, newMemStore())
r, err := w.k.ReserveNumber("author@g14", KindResearch, "an effort")
if err != nil {
t.Fatal(err)
}
overview := Section{Name: "00-overview.md", Text: "What an inference layer would be."}
w.accepted(t, "author@g14", effortAsk(r.Number, StatusActive, overview))
key := Key{KindResearch, r.Number}
w.judge.review = `{"verdict":"changes","findings":["01-findings.md: say where the finding comes from"]}`
next := effortAsk(r.Number, StatusActive, overview, Section{Name: "01-findings.md", Text: "A new finding."})
if _, err := w.k.Propose("author@g14", next); err != nil {
t.Fatal(err)
}
w.reviewAll(t)
e := mustGet(t, w.k.Store, key)
if e.Pending == nil || e.Pending.Reviews[len(e.Pending.Reviews)-1].Verdict != VerdictChanges ||
e.Current.Status != StatusActive || e.Current.Section("01-findings.md") != "" {
t.Fatalf("after changes: pending %v, current %+v", e.Pending != nil, e.Current.Sections)
}
grad := effortAsk(r.Number, StatusGraduated, overview)
if _, err := w.k.Propose("author@g14", grad); err == nil || !strings.Contains(err.Error(), "became") {
t.Fatalf("graduated without a became link: %v", err)
}
}
@@ -379,7 +379,14 @@ func (k *KB) Propose(caller string, a ProposeAsk) (*Proposed, error) {
if !current && a.Kind == KindResearch && r.Effort == "" {
r.Effort = held.Current.Status
}
refusals = append(refusals, JudgeRecord(r, held, k.lookup(ctx), ref)...)
judged := r
if r.Pending != nil && !r.IsInsight() {
// A new version of an active effort is new text: the dated rules hold it from the day it is proposed, while
// the record keeps its own date (novox/hq issue 844).
judged = r.Clone()
judged.Date = k.now().Format("2006-01-02")
}
refusals = append(refusals, JudgeRecord(judged, held, k.lookup(ctx), ref)...)
if raw, _ := json.Marshal(r); len(raw) > MostRecordBytes {
refusals = append(refusals, Refusal{Rule: "size", Says: fmt.Sprintf("the record is %d bytes; a record holds at most %d", len(raw), MostRecordBytes)})
}