Read a shrink against the item's own path, so a moved directory starts its size history again (hq issue 368)
A reading now keeps the path it was measured at, and the peak is read only from readings at the item's path now. Before, an agent's home that moved to its own account was compared with the operator's home it left, and data-shrank was raised for data that was never lost. Existing readings take their item's path now, so a shrink that is real stays raised.
This commit is contained in:
@@ -128,3 +128,47 @@ func TestAPartialMeasurementIsNeverAReading(t *testing.T) {
|
||||
t.Fatalf("%+v, %v", r, err)
|
||||
}
|
||||
}
|
||||
|
||||
// A shrink is read against what the same directory held (novox/hq issue 368): an item whose path moved
|
||||
// — an agent's home moved to its own account — starts its size history again at the new path, and a
|
||||
// genuine shrink at the new path is still read against what that path held.
|
||||
func TestThePeakIsReadAtTheItemsPathOnly(t *testing.T) {
|
||||
inv := fresh(t)
|
||||
ctx := t.Context()
|
||||
now := time.Date(2026, 10, 10, 0, 0, 0, 0, time.UTC)
|
||||
declared := []DeclaredData{{Module: "claude-code", Item: "agent-home", Class: "valuable", Owned: true}}
|
||||
measure := func(when time.Time, path string, s int64) {
|
||||
t.Helper()
|
||||
if _, err := inv.RecordData(ctx, "novox", declared, map[string]map[string]Measurement{"claude-code": {
|
||||
"agent-home": {Path: path, Size: size(s), MeasuredAt: at(when)}}}, "", when); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
measure(now, "/home/operator/.claude", 94_700_000)
|
||||
// The path moves ten minutes later: the new directory is measured at once, not an hour on.
|
||||
measure(now.Add(10*time.Minute), "/home/agent/.claude", 490)
|
||||
peaks, err := inv.DataPeaks(ctx, now.Add(-time.Hour))
|
||||
if err != nil || peaks["novox/claude-code/agent-home"] != 490 {
|
||||
t.Fatalf("after the path moved the peak is %v (%v), want 490: the old directory's size is no shrink "+
|
||||
"of the new one", peaks, err)
|
||||
}
|
||||
// The new directory grows, then genuinely loses most of it: that is read against the new path's peak.
|
||||
measure(now.Add(2*time.Hour), "/home/agent/.claude", 80_000_000)
|
||||
measure(now.Add(4*time.Hour), "/home/agent/.claude", 1_000)
|
||||
peaks, err = inv.DataPeaks(ctx, now.Add(-time.Hour))
|
||||
if err != nil || peaks["novox/claude-code/agent-home"] != 80_000_000 {
|
||||
t.Fatalf("a shrink at the new path is read against %v (%v), want 80000000", peaks, err)
|
||||
}
|
||||
// A measurement that names no path is the item's last known path's, not a new history.
|
||||
measure(now.Add(6*time.Hour), "", 2_000)
|
||||
peaks, err = inv.DataPeaks(ctx, now.Add(-time.Hour))
|
||||
if err != nil || peaks["novox/claude-code/agent-home"] != 80_000_000 {
|
||||
t.Fatalf("a measurement with no path started a new history: peak %v (%v)", peaks, err)
|
||||
}
|
||||
// Moving back to a directory measured before reads it against what it held then.
|
||||
measure(now.Add(8*time.Hour), "/home/operator/.claude", 94_000_000)
|
||||
peaks, err = inv.DataPeaks(ctx, now.Add(-time.Hour))
|
||||
if err != nil || peaks["novox/claude-code/agent-home"] != 94_700_000 {
|
||||
t.Fatalf("back at the first path the peak is %v (%v), want 94700000", peaks, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user