mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
fix(workgroup): the natural sample excludes experiments by construction
The protocol said the sample is ordinary use and leaves out benchmark and fixture runs. Nothing enforced it. The only thing keeping the twelve designed turns out was that they happened before the freeze, which says nothing at all about the next scripted run — and the session store already holds 481 project directories from past automated ones, every future sibling of which would have walked straight into a sample that calls itself natural. A driven run lives in a scratch directory. So a workspace under a temp root is not ordinary use, and its sessions never enter the sample. The check asks the host for the slug it writes such a path as, rather than looking for words in a directory name: the encoding is the host's own and reading it back is a fact, while matching "scratch" or "tmp" would be a guess about how someone names things. Seven of 488 project directories survive it, and they are the ones a person actually works in. The count of what was turned away is printed with the rest, so a sample that stays empty says why.
This commit is contained in:
1 parent
c2ffdf6d5e
commit
491016f8c9
4 files changed
+104
-16
No files matched your search
@@ -25,7 +25,11 @@ diff.
|
||||
A turn with nothing to fold is evidence about coverage, and dropping it would
|
||||
answer a different question and flatter the feature.
|
||||
- **Out**: turns written for this experiment, benchmark and fixture runs, and
|
||||
anything shaped to call more tools than the work needed.
|
||||
anything shaped to call more tools than the work needed. Enforced, not
|
||||
merely stated: a workspace under a temp root is where a driven run lives, so
|
||||
its sessions never enter the sample. Before that check the only thing keeping
|
||||
a scripted run out was that it happened before the freeze, which says nothing
|
||||
about the next one.
|
||||
- **No verdict before the sample is whole.** Under 20 the tool prints the count
|
||||
and stops.
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"reasonix/internal/config"
|
||||
"reasonix/internal/event"
|
||||
"reasonix/internal/eventwire"
|
||||
"reasonix/internal/workgroup"
|
||||
@@ -132,3 +133,39 @@ func TestOnlyNamedTurnsInACompleteLogAreEligible(t *testing.T) {
|
||||
t.Fatal("a log whose witness says truncated was read as complete")
|
||||
}
|
||||
}
|
||||
|
||||
// The protocol says the natural sample excludes experiments. Saying it is not
|
||||
// enough: before this, the only thing keeping a scripted run out was that it
|
||||
// happened before the freeze, which says nothing about the next one. A
|
||||
// workspace under a temp root is where a driven run lives, and the check reads
|
||||
// the host's own slug encoding rather than guessing at directory names.
|
||||
func TestWorkspacesUnderATempRootAreNotOrdinaryUse(t *testing.T) {
|
||||
slugs := scratchSlugs()
|
||||
if len(slugs) == 0 {
|
||||
t.Fatal("no temp-root slugs were derived, so nothing would ever be excluded")
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
dir string
|
||||
scratch bool
|
||||
}{
|
||||
{"a driven run's workspace", config.WorkspaceSlug(filepath.Join(os.TempDir(), "assay", "ws")), true},
|
||||
{"the system temp root itself", config.WorkspaceSlug(filepath.Join("/private/tmp", "run")), true},
|
||||
{"a person's own project", config.WorkspaceSlug(filepath.Join(home(t), "projects", "thing")), false},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := underScratch(tc.dir, slugs); got != tc.scratch {
|
||||
t.Fatalf("underScratch(%q) = %v, want %v", tc.dir, got, tc.scratch)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func home(t *testing.T) string {
|
||||
t.Helper()
|
||||
dir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Skip("no home directory to build a non-temp path from")
|
||||
}
|
||||
return dir
|
||||
}
|
||||
@@ -29,8 +29,9 @@ type turn struct {
|
||||
func main() {
|
||||
root := flag.String("root", "", "session root to scan (default: the configured one)")
|
||||
flag.Parse()
|
||||
dirs := scanRoots(*root)
|
||||
dirs, scratch := scanRoots(*root)
|
||||
turns, skipped := collect(dirs)
|
||||
skipped.scratchWorkspaces = scratch
|
||||
sort.Slice(turns, func(i, j int) bool {
|
||||
if !turns[i].at.Equal(turns[j].at) {
|
||||
return turns[i].at.Before(turns[j].at)
|
||||
@@ -40,47 +41,91 @@ func main() {
|
||||
report(turns, skipped)
|
||||
}
|
||||
|
||||
func scanRoots(root string) []string {
|
||||
func scanRoots(root string) ([]string, int) {
|
||||
if strings.TrimSpace(root) != "" {
|
||||
return []string{root}
|
||||
return []string{root}, 0
|
||||
}
|
||||
projects, scratch := projectSessionDirs()
|
||||
seen := map[string]bool{}
|
||||
var out []string
|
||||
for _, d := range append([]string{config.SessionDir()}, projectSessionDirs()...) {
|
||||
for _, d := range append([]string{config.SessionDir()}, projects...) {
|
||||
if d != "" && !seen[d] {
|
||||
seen[d] = true
|
||||
out = append(out, d)
|
||||
}
|
||||
}
|
||||
return out
|
||||
return out, scratch
|
||||
}
|
||||
|
||||
// projectSessionDirs finds the per-project session directories a Studio window
|
||||
// writes into, which is where ordinary use lands.
|
||||
func projectSessionDirs() []string {
|
||||
// writes into. Workspaces under a temp root are left out: a run driven from a
|
||||
// scratch directory is an experiment, and the protocol excludes those by
|
||||
// construction rather than by hoping none happen after the freeze.
|
||||
func projectSessionDirs() ([]string, int) {
|
||||
home := config.ReasonixHomeDir()
|
||||
if home == "" {
|
||||
return nil
|
||||
return nil, 0
|
||||
}
|
||||
entries, err := os.ReadDir(filepath.Join(home, "projects"))
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, 0
|
||||
}
|
||||
scratch := scratchSlugs()
|
||||
var out []string
|
||||
skipped := 0
|
||||
for _, e := range entries {
|
||||
if e.IsDir() {
|
||||
out = append(out, filepath.Join(home, "projects", e.Name(), "sessions"))
|
||||
if !e.IsDir() {
|
||||
continue
|
||||
}
|
||||
if underScratch(e.Name(), scratch) {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
out = append(out, filepath.Join(home, "projects", e.Name(), "sessions"))
|
||||
}
|
||||
return out, skipped
|
||||
}
|
||||
|
||||
// scratchSlugs is what a session directory's name starts with when its
|
||||
// workspace lives under a temp root. Built with the host's own slug function,
|
||||
// so this reads the encoding the host wrote rather than guessing at names.
|
||||
func scratchSlugs() []string {
|
||||
var out []string
|
||||
for _, root := range []string{os.TempDir(), "/tmp", "/private/tmp"} {
|
||||
for _, p := range []string{root, resolved(root)} {
|
||||
if abs, err := filepath.Abs(p); err == nil && abs != "" && abs != string(filepath.Separator) {
|
||||
if slug := config.WorkspaceSlug(abs); slug != "" {
|
||||
out = append(out, slug)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func resolved(path string) string {
|
||||
if p, err := filepath.EvalSymlinks(path); err == nil {
|
||||
return p
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func underScratch(name string, slugs []string) bool {
|
||||
for _, s := range slugs {
|
||||
if strings.HasPrefix(name, s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// skipReasons counts what the protocol turned away, so a small sample can say
|
||||
// why rather than look like nothing happened.
|
||||
type skipReasons struct {
|
||||
beforeFreeze int
|
||||
truncatedLogs int
|
||||
unnamedTurns int
|
||||
beforeFreeze int
|
||||
truncatedLogs int
|
||||
unnamedTurns int
|
||||
scratchWorkspaces int
|
||||
}
|
||||
|
||||
func collect(dirs []string) ([]turn, skipReasons) {
|
||||
@@ -183,8 +228,10 @@ func report(turns []turn, skipped skipReasons) {
|
||||
fmt.Printf(" protocol frozen at %s; sample is the first %d eligible authored turns after it\n",
|
||||
frozenAt, sampleSize)
|
||||
fmt.Printf(" eligible so far: %d\n", len(turns))
|
||||
fmt.Printf(" turned away: %d session(s) before the freeze, %d truncated, %d unnamed turns\n",
|
||||
fmt.Printf(" turned away: %d session(s) before the freeze, %d truncated, %d unnamed turns,\n",
|
||||
skipped.beforeFreeze, skipped.truncatedLogs, skipped.unnamedTurns)
|
||||
fmt.Printf(" %d workspace(s) under a temp root — experiments, not ordinary use\n",
|
||||
skipped.scratchWorkspaces)
|
||||
if len(turns) < sampleSize {
|
||||
fmt.Printf("\nNo result yet. %d more eligible authored turn(s) are owed.\n", sampleSize-len(turns))
|
||||
fmt.Printf("Reading a partial sample is the sequential decision this protocol exists to prevent,\n")
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user