Files
weichenandCursor 4a662ec2d3 feat(events): gate shared-dev consumer mode changes
Add ValidateOpsCutover, eventmode CLI, and a host script that pin agent_system_dev and refuse FAV plus test/main before any cluster mode write.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 14:11:44 +00:00

114 lines
2.8 KiB
Go

package main
import (
"context"
"encoding/json"
"fmt"
"os"
"time"
"chat-agent-system/internal/config"
"chat-agent-system/internal/events"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
if len(os.Args) < 2 {
usage()
os.Exit(2)
}
envPath := os.Getenv("EVENTMODE_ENV")
if envPath == "" {
envPath = "configs/.env.dev"
}
cfg, err := config.Load(envPath)
if err != nil {
fmt.Fprintln(os.Stderr, "eventmode: load env")
os.Exit(1)
}
if cfg.Env != events.OpsCutoverEnvironment {
fmt.Fprintln(os.Stderr, "eventmode: env must be dev")
os.Exit(1)
}
if cfg.ContextDbName != "agent_system_dev" {
fmt.Fprintln(os.Stderr, "eventmode: database must be agent_system_dev")
os.Exit(1)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
pool, err := pgxpool.New(ctx, cfg.ContextDSN())
if err != nil {
fmt.Fprintln(os.Stderr, "eventmode: pool")
os.Exit(1)
}
defer pool.Close()
switch os.Args[1] {
case "inventory":
if err := runInventory(ctx, pool); err != nil {
fmt.Fprintln(os.Stderr, "eventmode: inventory failed")
os.Exit(1)
}
case "set":
if len(os.Args) != 4 {
usage()
os.Exit(2)
}
consumer, mode := os.Args[2], os.Args[3]
before, _, _ := events.LoadMode(ctx, pool, cfg.Env, consumer)
if err := events.ApplyOpsCutover(ctx, pool, cfg.Env, consumer, mode); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
after, rev, _ := events.LoadMode(ctx, pool, cfg.Env, consumer)
enc := json.NewEncoder(os.Stdout)
_ = enc.Encode(map[string]any{
"environment": cfg.Env, "consumer": consumer,
"before": before, "after": after, "revision": rev,
})
case "quarantine-illegal":
n, err := events.QuarantineIllegalPending(ctx, pool, "cursor-ops", "phase2-shared-live")
if err != nil {
fmt.Fprintln(os.Stderr, "eventmode: quarantine failed")
os.Exit(1)
}
_ = json.NewEncoder(os.Stdout).Encode(map[string]any{"quarantined": n})
default:
usage()
os.Exit(2)
}
}
func runInventory(ctx context.Context, pool *pgxpool.Pool) error {
modes, err := events.ListModes(ctx, pool)
if err != nil {
return err
}
backlog, err := events.ListBacklog(ctx, pool)
if err != nil {
return err
}
pending, err := events.ClassifyPending(ctx, pool)
if err != nil {
return err
}
type wire struct {
EventID string `json:"event_id"`
Consumer string `json:"consumer"`
Classification string `json:"classification"`
Reason string `json:"reason"`
}
class := make([]wire, 0, len(pending))
for _, r := range pending {
class = append(class, wire{r.EventID, r.Consumer, r.Classification, r.Reason})
}
return json.NewEncoder(os.Stdout).Encode(map[string]any{
"modes": modes, "backlog": backlog, "pending_classifications": class,
})
}
func usage() {
fmt.Fprintln(os.Stderr, "usage: eventmode inventory | set <consumer> <mode> | quarantine-illegal")
}