Files
so-many-crows/main.go
T
SmokeyandClaude Opus 5.5 4499291231 Jev classifier in tandem with the LLM Sentry
- Jev (TypeSafe, direct) triages mode and task type with confidence
- Its call stands at >= 70% on both and no split; otherwise the LLM
  Sentry decides (unsure, split needs subtasks, or Jev down)
- Jev flights obey the same budget, flock cap, timeout and log
- Tests for every path; flight log is nil-safe
- start.command reads TYPESAFE_API_KEY and threshold from .env

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UQnSw4RRWp8uqpj3nsnnXF
2026-10-27 17:13:48 -06:00

236 lines
6.5 KiB
Go

package main
import (
"bufio"
"context"
"flag"
"fmt"
"os"
"os/signal"
"path/filepath"
"sort"
"strings"
"time"
)
const dataDir = ".crows"
func main() {
if len(os.Args) < 2 {
usage()
}
switch os.Args[1] {
case "run":
cmdRun(os.Args[2:])
case "serve":
cmdServe(os.Args[2:])
case "trust":
cmdTrust()
case "log":
cmdLog(os.Args[2:])
default:
usage()
}
}
func usage() {
fmt.Fprintln(os.Stderr, `So Many Crows
crows run <todo.txt> [-as name] [-nest id] hand the flock a todo list
crows serve [-addr 127.0.0.1:8080] run the web server (API + SSE)
crows trust show trust ledger
crows log [-n 20] show recent flight log entries`)
os.Exit(2)
}
func cmdRun(args []string) {
fs := flag.NewFlagSet("run", flag.ExitOnError)
as := fs.String("as", defaultRequester(), "requester id")
nestID := fs.String("nest", defaultNestID, "nest whose core crows fly first")
var pos []string
for fs.Parse(args); fs.NArg() > 0; fs.Parse(args) {
pos = append(pos, fs.Arg(0))
args = fs.Args()[1:]
}
if len(pos) != 1 {
usage()
}
todoPath := pos[0]
g := DefaultGuardrails()
ledger, err := LoadLedger(filepath.Join(dataDir, "ledger.json"))
must(err)
flog, err := OpenFlightLog(filepath.Join(dataDir, "flight.jsonl"))
must(err)
defer flog.Close()
nests, err := LoadNests(filepath.Join(dataDir, "nests.json"))
must(err)
nest, found := nests.Get(*nestID)
if !found {
must(fmt.Errorf("there is no nest called %q", *nestID))
}
p := &Pipeline{Ledger: ledger, Log: flog, G: g, Approver: &StdinApprover{in: bufio.NewReader(os.Stdin)}}
if ok, msg, _ := ledger.Admit(*as, time.Now(), g); !ok {
fmt.Println(msg)
flog.Write(Event{Kind: "denied", Requester: *as, Note: msg})
p.save()
os.Exit(1)
}
data, err := os.ReadFile(todoPath)
must(err)
items, err := parseTodo(string(data), g)
must(err)
if len(items) > g.MaxItemsPerList {
fmt.Printf("That list has %d items. The flock takes at most %d at a time.\n", len(items), g.MaxItemsPerList)
p.save()
os.Exit(1)
}
brain := NewBrain()
p.Flock = NewFlock(brain, g, flog)
p.Flock.SetClassifier(NewJev())
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
fmt.Printf("Brain: %s · requester: %s · nest: %s · %d items\n", brain.Name(), *as, nest.ID, len(items))
l := List{ID: "cli", Requester: *as, Source: todoPath, Items: items, Nest: nest}
results, listBudget := p.Run(ctx, l, &cliEmitter{items: items, seen: map[string]bool{}})
resultPath := strings.TrimSuffix(todoPath, filepath.Ext(todoPath)) + ".crows.md"
must(writeResults(resultPath, todoPath, results))
fmt.Printf("\nResults: %s · tokens used: %d/%d\n", resultPath, listBudget.Spent(), listBudget.limit)
}
// cliEmitter prints the events a person at a terminal cares about.
type cliEmitter struct {
items []string
seen map[string]bool
}
func (c *cliEmitter) Emit(event string, f map[string]any) {
if id, ok := f["item_id"].(string); ok && !c.seen[id] {
c.seen[id] = true
var n int
fmt.Sscanf(id[strings.LastIndex(id, "-")+1:], "%d", &n)
fmt.Printf("\n[%d/%d] %s\n", n, len(c.items), c.items[n-1])
}
switch event {
case "item.triaged":
fmt.Printf(" Sentry: %s · %s · %s\n", f["mode"], f["task_type"], f["reason"])
for _, s := range f["subtasks"].([]string) {
fmt.Printf(" - %s\n", s)
}
case "item.answered":
fmt.Printf(" Crows: %s\n%s\n", strings.Join(f["crows"].([]string), ", "), indent(f["answer"].(string), " > "))
case "trust.changed":
fmt.Printf(" Trust: %s on %s went %s → %s\n", f["holder"], f["task_type"], levelNames[f["from"].(int)], levelNames[f["to"].(int)])
case "item.skipped":
fmt.Printf(" %s\n", f["reason"])
}
}
var levelNames = []string{"stranger", "regular", "trusted"}
// parseTodo turns todo text (markdown checkboxes, bullets or plain lines) into items.
func parseTodo(text string, g Guardrails) ([]string, error) {
var items []string
for _, line := range strings.Split(text, "\n") {
line = strings.TrimSpace(line)
for _, p := range []string{"- [ ]", "- [x]", "-", "*"} {
line = strings.TrimSpace(strings.TrimPrefix(line, p))
}
if line == "" || strings.HasPrefix(line, "#") {
continue
}
if len(line) > g.MaxItemChars {
return nil, fmt.Errorf("an item is %d characters; the cap is %d", len(line), g.MaxItemChars)
}
items = append(items, line)
}
return items, nil
}
func writeResults(path, source string, results []itemResult) error {
var sb strings.Builder
fmt.Fprintf(&sb, "# So Many Crows: %s\n\n_%s_\n\n", filepath.Base(source), time.Now().Format("2006-01-02 15:04"))
for _, r := range results {
if r.Skipped != "" {
fmt.Fprintf(&sb, "- [ ] %s\n - skipped: %s\n\n", r.Item, r.Skipped)
continue
}
box := "x"
if r.Verdict == "rejected" || r.Verdict == "timeout" {
box = " "
}
fmt.Fprintf(&sb, "- [%s] %s\n - %s · %s · %s · %s\n%s\n\n", box, r.Item, r.Mode, r.TaskType, strings.Join(r.Crows, ", "), r.Verdict, indent(r.Answer, " > "))
}
return os.WriteFile(path, []byte(sb.String()), 0o644)
}
func cmdTrust() {
l, err := LoadLedger(filepath.Join(dataDir, "ledger.json"))
must(err)
show := func(title string, m map[string]*Record) {
fmt.Println(title)
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
if len(keys) == 0 {
fmt.Println(" (none yet)")
}
for _, k := range keys {
r := m[k]
fmt.Printf(" %-28s %-9s +%d -%d streak %d\n", k, levelNames[r.Level], r.Approved, r.Rejected, r.Streak)
}
}
show("Crows", l.Crows)
show("\nFlock", l.Flock)
fmt.Println("\nRequesters")
for id, r := range l.Requesters {
cd := "none"
if time.Now().Before(r.CooldownUntil) {
cd = time.Until(r.CooldownUntil).Round(time.Second).String()
}
fmt.Printf(" %-20s strikes %d · cooldown %s\n", id, r.Strikes, cd)
}
}
func cmdLog(args []string) {
fs := flag.NewFlagSet("log", flag.ExitOnError)
n := fs.Int("n", 20, "entries to show")
fs.Parse(args)
data, err := os.ReadFile(filepath.Join(dataDir, "flight.jsonl"))
must(err)
lines := strings.Split(strings.TrimSpace(string(data)), "\n")
if len(lines) > *n {
lines = lines[len(lines)-*n:]
}
fmt.Println(strings.Join(lines, "\n"))
}
func indent(s, prefix string) string {
lines := strings.Split(strings.TrimSpace(s), "\n")
for i := range lines {
lines[i] = prefix + lines[i]
}
return strings.Join(lines, "\n")
}
func defaultRequester() string {
if u := os.Getenv("USER"); u != "" {
return u
}
return "local"
}
func must(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
}
}