Add initial Go CLI skeleton
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
inboxcli "ai-workflow-skill/internal/cli/inbox"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := inboxcli.NewRootCmd().Execute(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
orchcli "ai-workflow-skill/internal/cli/orch"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := orchcli.NewRootCmd().Execute(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
module ai-workflow-skill
|
||||||
|
|
||||||
|
go 1.26
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/spf13/cobra v1.10.1
|
||||||
|
modernc.org/sqlite v1.40.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/spf13/pflag v1.0.9 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||||
|
golang.org/x/sys v0.36.0 // indirect
|
||||||
|
modernc.org/libc v1.66.10 // indirect
|
||||||
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
|
modernc.org/memory v1.11.0 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||||
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||||
|
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||||
|
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||||
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
||||||
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||||
|
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||||
|
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||||
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
|
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||||
|
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||||
|
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4=
|
||||||
|
modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||||
|
modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A=
|
||||||
|
modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q=
|
||||||
|
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
|
||||||
|
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||||
|
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||||
|
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||||
|
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||||
|
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||||
|
modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A=
|
||||||
|
modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I=
|
||||||
|
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||||
|
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||||
|
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||||
|
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||||
|
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||||
|
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||||
|
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||||
|
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||||
|
modernc.org/sqlite v1.40.1 h1:VfuXcxcUWWKRBuP8+BR9L7VnmusMgBNNnBYGEe9w/iY=
|
||||||
|
modernc.org/sqlite v1.40.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE=
|
||||||
|
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||||
|
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||||
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
|
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package inbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"ai-workflow-skill/internal/db"
|
||||||
|
"ai-workflow-skill/internal/protocol"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newInitCmd(opts *rootOptions) *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "init",
|
||||||
|
Short: "Initialize the shared SQLite database schema",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
sqlDB, err := db.Open(ctx, opts.dbPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sqlDB.Close()
|
||||||
|
|
||||||
|
if err := db.ApplyMigrations(ctx, sqlDB); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := protocol.Success{
|
||||||
|
OK: true,
|
||||||
|
Command: "init",
|
||||||
|
Data: map[string]any{
|
||||||
|
"db_path": opts.dbPath,
|
||||||
|
"status": "initialized",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.json {
|
||||||
|
return protocol.WriteJSON(cmd.OutOrStdout(), resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = fmt.Fprintf(cmd.OutOrStdout(), "initialized database: %s\n", opts.dbPath)
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package inbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
type rootOptions struct {
|
||||||
|
dbPath string
|
||||||
|
json bool
|
||||||
|
agent string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRootCmd() *cobra.Command {
|
||||||
|
opts := &rootOptions{}
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "inbox",
|
||||||
|
Short: "Worker-facing durable coordination bus",
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.PersistentFlags().StringVar(&opts.dbPath, "db", ".agents/coord.db", "SQLite database path")
|
||||||
|
cmd.PersistentFlags().BoolVar(&opts.json, "json", false, "Emit machine-readable JSON")
|
||||||
|
cmd.PersistentFlags().StringVar(&opts.agent, "agent", "", "Agent identity")
|
||||||
|
|
||||||
|
cmd.AddCommand(newInitCmd(opts))
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package orch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
type rootOptions struct {
|
||||||
|
dbPath string
|
||||||
|
json bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRootCmd() *cobra.Command {
|
||||||
|
opts := &rootOptions{}
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "orch",
|
||||||
|
Short: "Leader-facing scheduler and control plane",
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.PersistentFlags().StringVar(&opts.dbPath, "db", ".agents/coord.db", "SQLite database path")
|
||||||
|
cmd.PersistentFlags().BoolVar(&opts.json, "json", false, "Emit machine-readable JSON")
|
||||||
|
|
||||||
|
cmd.AddCommand(newRunCmd())
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package orch
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
func newRunCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "run",
|
||||||
|
Short: "Run management commands",
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(&cobra.Command{
|
||||||
|
Use: "init",
|
||||||
|
Short: "Stub for future run initialization",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return cmd.Help()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed schema/*.sql
|
||||||
|
var schemaFS embed.FS
|
||||||
|
|
||||||
|
func ApplyMigrations(ctx context.Context, db *sql.DB) error {
|
||||||
|
files, err := schemaFS.ReadDir("schema")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read embedded schema directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
names := make([]string, 0, len(files))
|
||||||
|
for _, file := range files {
|
||||||
|
if file.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
names = append(names, file.Name())
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
|
||||||
|
tx, err := db.BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("begin schema transaction: %w", err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
content, err := schemaFS.ReadFile("schema/" + name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read embedded schema file %q: %w", name, err)
|
||||||
|
}
|
||||||
|
if _, err := tx.ExecContext(ctx, string(content)); err != nil {
|
||||||
|
return fmt.Errorf("apply schema file %q: %w", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return fmt.Errorf("commit schema transaction: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
_ "modernc.org/sqlite"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Open(ctx context.Context, dbPath string) (*sql.DB, error) {
|
||||||
|
if err := ensureParentDir(dbPath); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := sql.Open("sqlite", dbPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("open sqlite database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := applyPragmas(ctx, db); err != nil {
|
||||||
|
_ = db.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureParentDir(dbPath string) error {
|
||||||
|
parent := filepath.Dir(dbPath)
|
||||||
|
if parent == "." || parent == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.MkdirAll(parent, 0o755)
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func applyPragmas(ctx context.Context, db *sql.DB) error {
|
||||||
|
pragmas := []string{
|
||||||
|
"PRAGMA foreign_keys = ON;",
|
||||||
|
"PRAGMA journal_mode = WAL;",
|
||||||
|
"PRAGMA busy_timeout = 5000;",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pragma := range pragmas {
|
||||||
|
if _, err := db.ExecContext(ctx, pragma); err != nil {
|
||||||
|
return fmt.Errorf("apply pragma %q: %w", pragma, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS threads (
|
||||||
|
thread_id TEXT PRIMARY KEY,
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
task_id TEXT NOT NULL,
|
||||||
|
subject TEXT NOT NULL,
|
||||||
|
created_by TEXT NOT NULL,
|
||||||
|
assigned_to TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL,
|
||||||
|
priority TEXT NOT NULL DEFAULT 'normal',
|
||||||
|
latest_message_id TEXT,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
message_id TEXT PRIMARY KEY,
|
||||||
|
thread_id TEXT NOT NULL,
|
||||||
|
from_agent TEXT NOT NULL,
|
||||||
|
to_agent TEXT NOT NULL,
|
||||||
|
kind TEXT NOT NULL,
|
||||||
|
summary TEXT NOT NULL,
|
||||||
|
body TEXT NOT NULL DEFAULT '',
|
||||||
|
payload_json TEXT NOT NULL DEFAULT '{}',
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
FOREIGN KEY(thread_id) REFERENCES threads(thread_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS leases (
|
||||||
|
thread_id TEXT PRIMARY KEY,
|
||||||
|
agent_id TEXT NOT NULL,
|
||||||
|
lease_token TEXT NOT NULL,
|
||||||
|
claimed_at TEXT NOT NULL,
|
||||||
|
expires_at TEXT NOT NULL,
|
||||||
|
released_at TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS artifacts (
|
||||||
|
artifact_id TEXT PRIMARY KEY,
|
||||||
|
message_id TEXT NOT NULL,
|
||||||
|
path TEXT NOT NULL,
|
||||||
|
kind TEXT NOT NULL,
|
||||||
|
metadata_json TEXT NOT NULL DEFAULT '{}',
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
FOREIGN KEY(message_id) REFERENCES messages(message_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_threads_status_assigned
|
||||||
|
ON threads(status, assigned_to, updated_at);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_messages_thread_created
|
||||||
|
ON messages(thread_id, created_at);
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS runs (
|
||||||
|
run_id TEXT PRIMARY KEY,
|
||||||
|
goal TEXT NOT NULL,
|
||||||
|
summary TEXT NOT NULL DEFAULT '',
|
||||||
|
status TEXT NOT NULL DEFAULT 'active',
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tasks (
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
task_id TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
summary TEXT NOT NULL DEFAULT '',
|
||||||
|
status TEXT NOT NULL,
|
||||||
|
default_to TEXT,
|
||||||
|
priority TEXT NOT NULL DEFAULT 'normal',
|
||||||
|
acceptance_json TEXT NOT NULL DEFAULT '[]',
|
||||||
|
latest_attempt_no INTEGER,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (run_id, task_id),
|
||||||
|
FOREIGN KEY(run_id) REFERENCES runs(run_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS task_dependencies (
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
task_id TEXT NOT NULL,
|
||||||
|
depends_on_task_id TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (run_id, task_id, depends_on_task_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS task_attempts (
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
task_id TEXT NOT NULL,
|
||||||
|
attempt_no INTEGER NOT NULL,
|
||||||
|
assigned_to TEXT NOT NULL,
|
||||||
|
thread_id TEXT NOT NULL,
|
||||||
|
base_ref TEXT,
|
||||||
|
base_commit TEXT,
|
||||||
|
branch_name TEXT,
|
||||||
|
worktree_path TEXT,
|
||||||
|
workspace_status TEXT,
|
||||||
|
result_commit TEXT,
|
||||||
|
status TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (run_id, task_id, attempt_no)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tasks_run_status
|
||||||
|
ON tasks(run_id, status, priority, updated_at);
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS events (
|
||||||
|
event_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
task_id TEXT NOT NULL,
|
||||||
|
thread_id TEXT,
|
||||||
|
source TEXT NOT NULL,
|
||||||
|
event_type TEXT NOT NULL,
|
||||||
|
message_id TEXT,
|
||||||
|
summary TEXT NOT NULL DEFAULT '',
|
||||||
|
payload_json TEXT NOT NULL DEFAULT '{}',
|
||||||
|
created_at TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_events_run_event
|
||||||
|
ON events(run_id, event_id);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_events_thread_event
|
||||||
|
ON events(thread_id, event_id);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS council_runs (
|
||||||
|
run_id TEXT PRIMARY KEY,
|
||||||
|
mode TEXT NOT NULL,
|
||||||
|
target_type TEXT NOT NULL,
|
||||||
|
output_mode TEXT NOT NULL,
|
||||||
|
only_unanimous INTEGER NOT NULL DEFAULT 0,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS council_reviewers (
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
reviewer_role TEXT NOT NULL,
|
||||||
|
task_id TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (run_id, reviewer_role)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS council_findings (
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
reviewer_role TEXT NOT NULL,
|
||||||
|
finding_id TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
summary TEXT NOT NULL,
|
||||||
|
proposal TEXT NOT NULL,
|
||||||
|
rationale TEXT NOT NULL,
|
||||||
|
confidence TEXT NOT NULL,
|
||||||
|
tags_json TEXT NOT NULL DEFAULT '[]',
|
||||||
|
target_refs_json TEXT NOT NULL DEFAULT '{}',
|
||||||
|
PRIMARY KEY (run_id, reviewer_role, finding_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS council_groups (
|
||||||
|
run_id TEXT NOT NULL,
|
||||||
|
group_id TEXT NOT NULL,
|
||||||
|
proposal TEXT NOT NULL,
|
||||||
|
bucket TEXT NOT NULL,
|
||||||
|
support_count INTEGER NOT NULL,
|
||||||
|
supporters_json TEXT NOT NULL DEFAULT '[]',
|
||||||
|
dissenters_json TEXT NOT NULL DEFAULT '[]',
|
||||||
|
rationale_summary TEXT NOT NULL DEFAULT '',
|
||||||
|
tags_json TEXT NOT NULL DEFAULT '[]',
|
||||||
|
source_finding_ids_json TEXT NOT NULL DEFAULT '[]',
|
||||||
|
PRIMARY KEY (run_id, group_id)
|
||||||
|
);
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Success struct {
|
||||||
|
OK bool `json:"ok"`
|
||||||
|
Command string `json:"command"`
|
||||||
|
Data map[string]any `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
OK bool `json:"ok"`
|
||||||
|
Error ErrorPayload `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrorPayload struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteJSON(w io.Writer, v any) error {
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
return enc.Encode(v)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package store
|
||||||
|
|
||||||
|
// Package store contains higher-level database access helpers.
|
||||||
Reference in New Issue
Block a user