Research limit: a new version of an active effort is never refused; holds and tool text follow (issue 1970, ADR 0629)
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
@@ -16,7 +16,7 @@ func (w *world) effort(t *testing.T, status string) int {
|
||||
return r.Number
|
||||
}
|
||||
|
||||
// ADR 0629 §1, §4: at most three efforts are active; a fourth, new or taken up from an idea, is refused and the
|
||||
// ADR 0629 §3, §4: at most three efforts are active; a fourth, new or taken up from an idea, is refused and the
|
||||
// refusal names the active ones; the limit is the setting's.
|
||||
func TestAtMostThreeResearchEffortsAreActive(t *testing.T) {
|
||||
w := imported(t, newMemStore())
|
||||
@@ -50,11 +50,15 @@ func TestAtMostThreeResearchEffortsAreActive(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// An active effort takes a new version at the limit; the setting raises the limit, and an idea taken up and
|
||||
// ADR 0629 §4: an active effort takes a new version at the limit (even over it); the setting raises the limit, and an idea taken up and
|
||||
// still waiting for its review counts as active.
|
||||
if _, err := w.k.Propose("author@g14", effortAsk(active[0], StatusActive, Section{Name: "00-overview.md", Text: "More."})); err != nil {
|
||||
t.Fatalf("an active effort refused a new version at the limit: %v", err)
|
||||
}
|
||||
w.k.Settings = func() (Settings, error) { return Settings{ResearchActiveAtMost: 1}, nil }
|
||||
if _, err := w.k.Propose("author@g14", effortAsk(active[1], StatusActive, Section{Name: "00-overview.md", Text: "Over the limit."})); err != nil {
|
||||
t.Fatalf("an active effort refused a new version over the limit: %v", err)
|
||||
}
|
||||
w.k.Settings = func() (Settings, error) { return Settings{ResearchActiveAtMost: 4}, nil }
|
||||
if _, err := w.k.Propose("author@g14", effortAsk(idea, StatusActive, Section{Name: "00-overview.md", Text: "Taken up."})); err != nil {
|
||||
t.Fatalf("an idea taken up under a limit of 4: %v", err)
|
||||
@@ -65,6 +69,16 @@ func TestAtMostThreeResearchEffortsAreActive(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ADR 0629 §2: holds answers nothing from an idea.
|
||||
func TestHoldsAnswersNothingFromAnIdea(t *testing.T) {
|
||||
w := imported(t, newMemStore())
|
||||
k := Key{KindResearch, w.effort(t, StatusIdea)}
|
||||
h, err := w.k.Holds("", &k, 0)
|
||||
if err != nil || len(h.Clauses) != 0 {
|
||||
t.Fatalf("holds from an idea: %+v, %v", h, err)
|
||||
}
|
||||
}
|
||||
|
||||
// ADR 0629 §1, §2: list at idea is the roadmap; ask, holds and get never answer an idea as a record in force.
|
||||
func TestAnIdeaIsListedAndNeverServedAsTruth(t *testing.T) {
|
||||
w := imported(t, newMemStore())
|
||||
|
||||
@@ -397,7 +397,7 @@ func (k *KB) Propose(caller string, a ProposeAsk) (*Proposed, error) {
|
||||
if !current && a.Kind == KindResearch && r.Effort == "" {
|
||||
r.Effort = held.Current.Status
|
||||
}
|
||||
if a.Kind == KindResearch && r.Effort == StatusActive {
|
||||
if a.Kind == KindResearch && r.Effort == StatusActive && (held == nil || held.Current.Status != StatusActive) {
|
||||
if why := k.activeLimitRefusal(ctx, key); why != "" {
|
||||
refusals = append(refusals, Refusal{Rule: "research-active-at-most", Says: why})
|
||||
}
|
||||
@@ -446,7 +446,7 @@ func (k *KB) Propose(caller string, a ProposeAsk) (*Proposed, error) {
|
||||
return &Proposed{Record: key.String(), Version: n, Status: StatusProposed, Says: says + "."}, nil
|
||||
}
|
||||
|
||||
// activeLimitRefusal (ADR 0629 §4, a check of the record set beside the one-record rules of ADR 0290 §4) says why a research effort may not be active now: the limit of efforts other than this one
|
||||
// activeLimitRefusal (ADR 0629 §4 names only a new effort or one taken up from an idea, never a new version of an active one; a check of the record set beside the one-record rules of ADR 0290 §4) says why a research effort may not be active now: the limit of efforts other than this one
|
||||
// already active (accepted at active, or proposed at active and waiting for review) is reached (ADR 0629). Empty
|
||||
// when it may.
|
||||
func (k *KB) activeLimitRefusal(ctx context.Context, key Key) string {
|
||||
|
||||
@@ -974,7 +974,7 @@ func Tools(k *KB, caller func(map[string]any) string) []stdio.Tool {
|
||||
"links (supersedes, changes \"0276 §4\", extends, became, cites), and whether it needs the operator, with the brief its ask shows. Refused, naming " +
|
||||
"every reason at once and writing nothing, when it breaks one of the 30 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 (an active research effort excepted, which takes new versions) changes only by a progressive insight (insight: what " +
|
||||
"proposal is revised by proposing it again; an accepted record (an active research effort or an idea excepted, which take new versions; at most three research efforts are active) changes only by a progressive insight (insight: what " +
|
||||
"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. A decision that names no home and that no accepted record links is not judged: " +
|
||||
"its review asks changes for the whole-set rule cited, which its acceptance would break. On approve it is accepted (a record that needs the operator waits for the operator's " +
|
||||
|
||||
Reference in New Issue
Block a user