Repository navigation
Expand file tree
/
Copy pathinks9_test.go
More file actions
202 lines (184 loc) · 6.82 KB
/
Copy pathinks9_test.go
File metadata and controls
202 lines (184 loc) · 6.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package exec
import (
"context"
"strings"
"sync"
"testing"
"time"
"github.com/Agent-Field/agentfield/sdk/go/ai"
"github.com/Agent-Field/codeaf/internal/ctxbudget"
"github.com/Agent-Field/codeaf/internal/store"
)
// THE INK RUN OF 2026-08-29 (s9), AT THE MOMENT ITS LEAVES WERE CUT.
//
// Three leaves, all on the generalist, all landed early, all journaled as "it
// was still working when it ran out of its tokens" against a grant of 150,000.
// Not one of them reached that grant. What landed every one of them was the
// cumulative bound on prompt sent, at 240,000, four landing turns before the
// number the record printed:
//
// task-2 attempt 1 crossed 240,000 sent at turn 13, landed at 17
// task-2 attempt 2 crossed 240,000 sent at turn 12, landed at 16
// task-2-x1 crossed 240,000 sent at turn 9, landed at 13
//
// The figures below are attempt one's, read out of that store's usage_turns.
const (
inkS9Prompt = 365764
inkS9Completion = 7177
inkS9Cached = 298752
inkS9Sent = 365764
inkS9Turns = 17
)
// inkS9Attempt rebuilds that leaf's meter readings.
func inkS9Attempt() *Outcome {
outcome := &Outcome{
Turns: inkS9Turns,
Usage: Usage{
PromptTokens: inkS9Prompt,
CompletionTokens: inkS9Completion,
CachedTokens: inkS9Cached,
},
}
// One row carrying the whole of what was sent: contextPressure sums Sent
// over the turn rows, and the sum is what the bound reads.
outcome.PerTurn = []TurnUsage{{Turn: 1, Sent: inkS9Sent}}
return outcome
}
// WHAT LANDS A LEAF IS WHAT ITS WORK COSTS. The cumulative prompt bound cut this
// leaf at turn 13 of a 200-turn grant with 31% of its money unspent; it is a
// warning now and it lands nobody.
func TestTheInkLeafIsNotLandedByHowMuchTextWentPast(t *testing.T) {
outcome := inkS9Attempt()
// The bound that actually fired, still crossed — the evidence is kept.
pressure := outcome.contextPressure()
ceiling := reuseCeiling(ctxbudget.DefaultWorkingSetTokens)
if ceiling <= 0 {
t.Fatal("the reuse ceiling went inert on a known window; the rest of this test means nothing")
}
if !pressureReached(pressure, ceiling) {
t.Fatalf("the ink leaf sent %d prompt tokens against a %d ceiling — the fixture no longer reproduces the run",
pressure, ceiling)
}
// And it no longer stops the leaf.
if exhausted(outcome, DefaultLeafTokens) {
t.Fatalf("the ink leaf was landed with %d of %d tokens of billed work unspent",
DefaultLeafTokens-spent(outcome), DefaultLeafTokens)
}
if spent(outcome) >= DefaultLeafTokens {
t.Fatalf("spent() = %d, want a leaf still inside its %d grant", spent(outcome), DefaultLeafTokens)
}
// THE EVIDENCE IS NOT THROWN AWAY, IT IS DEMOTED. A leaf whose transcript
// has gone round many times over is told to wrap up — which costs a
// sentence — instead of being landed, which costs its work.
if used := budgetUsed(outcome, DefaultLeafTokens, ctxbudget.DefaultWorkingSetTokens); used <= wrapUpAt {
t.Fatalf("budgetUsed = %.2f, want the reuse pressure to still raise the wrap-up warning past %.2f",
used, wrapUpAt)
}
}
// AND THE BOUND THAT FIRES NAMES ITSELF. Three ceilings shared one StopReason,
// so the journal said "ran out of its tokens" and printed a grant the leaf had
// never reached — which is why the first three readings of ink s9 each blamed a
// different meter.
func TestALandedLeafSaysWhichBoundLandedIt(t *testing.T) {
space := workspace(t)
// A one-turn grant: the turn cap is the bound, and it must say so.
linear := NewLinear(&scriptedCompleter{turns: [][]ai.ToolCall{
{call("c1", "sh", `{"command":"true"}`)},
{call("c2", "sh", `{"command":"true"}`)},
}}, space, nil, 1, 1_000_000, time.Minute)
outcome, err := linear.Run(context.Background(), Task{NodeID: 1, Brief: "do the thing"})
if err != nil {
t.Fatalf("run: %v", err)
}
if outcome.Stop != StopTurnCap {
t.Fatalf("stop = %q, want the turn cap", outcome.Stop)
}
if !outcome.Meter.Named() {
t.Fatal("the leaf was landed by a bound that did not name itself")
}
if outcome.Meter.Name != "turns" {
t.Fatalf("meter = %q, want the bound that actually fired", outcome.Meter.Name)
}
if words := outcome.Meter.Words(); !strings.Contains(words, "turns") || !strings.Contains(words, "1") {
t.Fatalf("the meter reads %q, want its own two numbers in it", words)
}
}
// THE WORKER LEAVES A RECORD. exec.TranscriptFrom had one reader in the whole
// tree, and it was not the leaf belt — so a run left a store with no transcript
// at all: BankedRun found nothing, every continuation started cold, and the
// resumption the lease lane built could never fire. ink s9's store holds zero
// transcript rows across three leaves.
func TestTheGeneralistRecordsItsTurnsUnderTheNode(t *testing.T) {
space := workspace(t)
sink := &countingSink{}
ctx := WithTranscript(context.Background(), sink)
linear := NewLinear(&scriptedCompleter{turns: [][]ai.ToolCall{
{call("c1", "sh", `{"command":"echo one"}`)},
}}, space, nil, 4, 1_000_000, time.Minute)
if _, err := linear.Run(ctx, Task{NodeID: 7, Brief: "add grid layout"}); err != nil {
t.Fatalf("run: %v", err)
}
kinds := sink.kinds()
for _, want := range []store.TranscriptKind{
store.TranscriptAssistant, store.TranscriptToolCall, store.TranscriptToolResult,
} {
if kinds[want] == 0 {
t.Fatalf("the generalist recorded no %s entry; it left %v", want, kinds)
}
}
// A call and its result are matched by the provider's own id, or a reader
// of a parallel turn cannot say which answer belongs to which question.
if !sink.pairsCallsWithResults() {
t.Fatal("a recorded tool call and its result do not share a call id")
}
if !sink.flushed() {
t.Fatal("the record was never made durable; a leaf that dies mid-loop would leave nothing")
}
}
// countingSink is a TranscriptSink that only counts, so a belt can be asked
// what it recorded without a store.
type countingSink struct {
mutex sync.Mutex
entries []store.TranscriptEntry
flushes int
}
func (c *countingSink) Record(entry store.TranscriptEntry) {
c.mutex.Lock()
defer c.mutex.Unlock()
c.entries = append(c.entries, entry)
}
func (c *countingSink) Flush() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.flushes++
}
func (c *countingSink) kinds() map[store.TranscriptKind]int {
c.mutex.Lock()
defer c.mutex.Unlock()
counted := map[store.TranscriptKind]int{}
for _, entry := range c.entries {
counted[entry.Kind]++
}
return counted
}
func (c *countingSink) flushed() bool {
c.mutex.Lock()
defer c.mutex.Unlock()
return c.flushes > 0
}
func (c *countingSink) pairsCallsWithResults() bool {
c.mutex.Lock()
defer c.mutex.Unlock()
calls := map[string]bool{}
for _, entry := range c.entries {
if entry.Kind == store.TranscriptToolCall && entry.CallID != "" {
calls[entry.CallID] = true
}
}
for _, entry := range c.entries {
if entry.Kind == store.TranscriptToolResult && calls[entry.CallID] {
return true
}
}
return false
}