decide

package
v0.16.0-dev.c839379e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

An answer is checked against the question that asked it (edges 22 and 23 of the non-author's read of #1327).

A typed decision is typed at BOTH ends. The question carries a closed set of criteria, and until this file existed nothing ever compared the answer to it: an answer of "deepseek-flash" to a question offering continue, ask-all- friends and ask-glenn printed `HELP help=deepseek-flash conf=0.94 below=-` at exit 0, and `{"type":"choice","confidence":0.99}` -- an answer naming nothing at all -- printed an empty value ABOVE the floor at exit 0. Both are the provider failing to answer the question, and a decision that was never made cannot be authorized by the confidence attached to it.

So: a choice answer must name one of the options its question offered, and the refusal names the answer and the offered set, because a reader has to see the gap to act on it.

Package decide makes one typed decision per call through TypeSafe Jev.

The provider is POST <baseURL> with header Authorization: Bearer <key> and a JSON body {"state": <text>, "model": "jev-latest", "questions": {...}}. Each question is one of three kinds: a choice among named options, a score against ordered levels, or a noul (null) statement. The response carries one typed answer per question plus a usage count.

The key comes ONLY from the environment variable the caller names (New's keyEnv, default JEV_API_KEY with TYPESAFE_API_KEY also accepted): never a file, never argv, and it is never printed. A decision below the floor is a suggestion, never an authorization: callers keep today's behaviour as the fallback.

The decisions table (rule 8): a decision is logged beside the outcome it predicted so a floor is re-tuned from data. The row is (question_hash, kind, answer, provider_confidence, floor, outcome).

Exactly one writer appends to the table -- the decision client itself, after every call -- and every other verb only reads it. The table is a projection of the decision journal and never an authority over the machinery.

Postgres is the durable record, reached through a database/sql driver named by the DSN, where a build links one. A bench with no Postgres falls back to a TSV file, so the files stay the record and the table is an index; the fallback is the same contract and never a second one.

The second decision (Glenn 2026-09-18): do I keep going, ask all my friends, or ask Glenn?

The evidence is what a line can count about itself: hours on the SAME problem, retries on one rung, failures in the last hour and how many of those it caused itself, whether a class of failure is recurring, whether landing moved at all, and the uncertainty it states out loud.

One rule stands over the rest: ask-glenn only AFTER ask-all-friends. A line that has not asked its friends has not earned the interrupt.

The ladder is the retry policy (Glenn 2026-09-18).

One unit of work, one decision: WHICH MIND does it. The answer is the lowest rung the evidence supports with confidence that the FIRST attempt is right. Below the floor the answer steps UP a rung, never down. A failed attempt re-enters the decision carrying its evidence -- what failed, how -- and the answer is the next rung, automatically: sideways first, where the same height holds another lineage, then up.

Two rungs are chosen by KIND and not by height, and the machinery decides them, not the provider: security -- a guard, secrets, the sandbox, sudo, deploy keys, the network -- is Johnny's always; and so is a fresh take, where the rungs below failed or a design has one author.

Friends first: the DeepSeek rungs take MECHANICAL kinds and nothing else.

Jev advises and the machinery decides (SPEC-DECIDE rules 5, 6 and 7): the provider is offered the eligible rungs at the supported height and the one above it -- never a rung below what the evidence already burned -- and an answer below the floor, an answer naming a rung nobody offered, or no answer at all leaves the rules' own rung standing.

The registry of minds: the ladder nova-decide routes a unit of work over (Glenn 2026-09-18).

A rung is a HEIGHT, not a name: Flash and Pro at the bottom on the DeepSeek lineage, then the child rungs -- Opus (Rowan's) and Sol (Stella's) -- at ONE height in two lineages, so a failure moves SIDEWAYS before it moves up; then the friends, each a mind with an owned lane; then Astra and Fable as the top pair, all friends at once above them, and Glenn above that.

Two rungs are chosen by KIND and not by height: a guard, secrets, the sandbox, sudo, deploy keys or the network is Johnny's always, and so is a fresh take -- the rungs below failed, or a design with one author. The `kinds` column is that designation and nothing else.

The registry is a DATA FILE. A path names one; an empty path is the default embedded below, so the loop runs on a bench with no file of its own. Every row is validated on the way in: a bad row is a refusal, never a guess.

The escalation log (Glenn 2026-09-18): every routing decision is written down with the evidence that produced it, the rung it tried, what followed, the rung that finally succeeded -- and, beside all of it, what Rowan would have picked. That last column is the point: it is how we find out whether the decision route is better than the coordinator's own hand, one row at a time.

The log is append-only JSON lines, one object per decision, at a path the caller names. Nothing here reads a working directory and nothing is rewritten in place; the rows are the record, and the summary is a projection of them.

The summary regenerates the STARTING RUNG per kind from the rows: the lowest rung that is carrying its own weight -- successes at that height, and at least as many successes as failures. A kind with no success keeps the rung the table started from, because a starting rung with no rows behind it is not regenerated (SPEC-DECIDE rule 8).

Tuning a confidence floor from a decisions log (rule 8): a decision is logged beside the outcome it predicted, and the floor is re-tuned from those rows, never from a feeling about the model.

A decisions log is JSONL, one row per decision. Each row joins the decision (the field named by TuneOptions.Choice, default "decision"), its confidence (TuneOptions.Conf, default "confidence") and the outcome (TuneOptions.Label, default "label"). A row without a label is counted in Lines and skipped as unlabeled. For each floor, a row at or above the floor was decided: Tune reports how many of those agreed with their label (agree_rate) and how many fell below it (escalation_rate, against every labeled row). The best floor is the one with the highest agree_rate whose escalation_rate is at most TuneOptions.MaxEscalation; a tie keeps the higher (more selective) floor. Fewer than MinLabeled labeled rows cannot set a floor, so the caller refuses rather than guesses.

Index

Constants

View Source
const (
	HelpContinue      = "continue"
	HelpAskAllFriends = "ask-all-friends"
	HelpAskGlenn      = "ask-glenn"
)

The three answers.

View Source
const (
	KindRebase          = "rebase"
	KindStack           = "stack"
	KindFixtureRetarget = "fixture-retarget"
	KindFleetChore      = "fleet-chore"
	KindFixWithRedTest  = "fix-with-red-test"
	KindNewVerb         = "new-verb"
	KindSpec            = "spec"
	KindDesign          = "design"
	KindGuard           = "guard"
	KindCauseToFind     = "cause-to-find"
)

The kinds of unit a decision is asked about. They are the evidence's first field and the log's key: the starting rung is regenerated per kind.

View Source
const (
	OutcomeOK        = "ok"
	OutcomeFailed    = "failed"
	OutcomeTimeout   = "timeout"
	OutcomeAbandoned = "abandoned"
)

The outcome of one attempt.

View Source
const (
	SourceRules = "rules"
	SourceJev   = "jev"
)

Where a route answer came from.

View Source
const (
	TouchGuard      = "guard"
	TouchSecrets    = "secrets"
	TouchSandbox    = "sandbox"
	TouchSudo       = "sudo"
	TouchDeployKeys = "deploy-keys"
	TouchNetwork    = "network"
)

The six things that make a unit security work. They are an enumeration and not free text: a touch the table does not hold is a refusal.

View Source
const (
	// WaitNone is the absence, rendered as a dash so every line carries the
	// field and no reader has to infer it.
	WaitNone = "-"
	// WaitAwaitingTermination is the lease rule: an attempt timed out, its
	// expiry is UNKNOWN, and nothing is dispatched until it is known dead.
	WaitAwaitingTermination = "awaiting_termination"
)

RouteResult is one routing decision: the rung, the number the floor was applied to, the floor, why, and -- for the log -- what the rules alone would have picked. The typed actions a route answers with beside the rung. A wait is NOT permission to retry: the rung named is the one an attempt may still be running on, and the caller's next move is to establish what happened to it.

View Source
const (
	// AskBus is a note on the bus: a friend, the top pair, all friends, Glenn.
	AskBus = "bus"
	// AskCard is a swarm card: the DeepSeek rungs take work as cards.
	AskCard = "card"
	// AskChild is a child of the coordinator that owns that lineage.
	AskChild = "child"
)

How a rung is asked. A mind is reached one of three ways and the row says which, because the caller has to hand the unit over after the decision.

View Source
const (
	AvailabilityAvailable = "available"
	AvailabilityAsleep    = "asleep"
	AvailabilityReserved  = "reserved"
)

A mind's availability. A reserved mind is OFF the height ladder and reached only by a kind designation -- which is exactly Johnny: reserved for a different view, and security's rung regardless.

View Source
const DecisionsEnv = "NOVA_DSN"

DecisionsEnv names the environment variable a decisions table DSN is read from when a verb is not given one on the command line.

View Source
const DefaultBaseURL = "https://api.typesafe.ai/v1/systemone"

DefaultBaseURL is the TypeSafe Jev endpoint New uses when baseURL is empty.

View Source
const DefaultFloor = 0.9

DefaultFloor is the confidence floor a decision is gated on when the caller names none, matching nova-decide's --floor default.

View Source
const DefaultKeyEnv = "JEV_API_KEY"

DefaultKeyEnv is the environment variable New reads when keyEnv is empty. TYPESAFE_API_KEY is accepted as a fallback.

View Source
const DefaultMaxEscalation = 0.7

DefaultMaxEscalation is the escalation-rate cap Tune uses to pick the best floor when none is given.

View Source
const DefaultMaxSteps = 3

DefaultMaxSteps is how many decisions --step-up makes before it stops. Three is the ladder's own shape: the rung the evidence supports, one sideways, one up. A step-up that has not landed by then is not a confidence problem.

View Source
const DefaultModel = "jev-latest"

DefaultModel is the model every request names.

View Source
const DesignationFreshTake = "fresh-take"

DesignationFreshTake is the kind designation for a fresh take: the rungs below failed, or a design with one author.

View Source
const FallbackKeyEnv = "TYPESAFE_API_KEY"

FallbackKeyEnv is accepted when the named variable is unset.

View Source
const MinLabeled = 10

MinLabeled is the fewest labeled rows a floor can be set from.

View Source
const PGDriverName = "postgres"

PGDriverName is the database/sql driver a postgres:// DSN opens. A build that links a Postgres driver (lib/pq, pgx) registers this name; a build with none refuses rather than guessing.

View Source
const RungQuestion = "rung"

RungQuestion is the name of the one choice Jev is asked.

Variables

View Source
var (
	// SizeBuckets are the buckets a file, package or lane count falls into.
	SizeBuckets = []string{"none", "1-3", "4-9", "10-19", "20+"}
	// AttemptBuckets are the buckets a prior-attempt count falls into.
	AttemptBuckets = []string{"0", "1", "2", "3+"}
	// PlatformBuckets say whether a platform need is one of the benches we run
	// all day, or one outside them -- never which.
	PlatformBuckets = []string{"ordinary", "named"}
	// DeadlineBuckets are the buckets a deadline falls into.
	DeadlineBuckets = []string{"none", "under-10m", "under-2h", "over-2h"}
)

The buckets the evidence is reduced to before any of it leaves this process. They are ENUMERATIONS: every value the provider ever sees is one of these tokens, so no title, path, branch name, error text or attempt reason can ride out on a state line (SPEC-DECIDE rule 4).

View Source
var DefaultFloors = []float64{0.5, 0.7, 0.8, 0.9, 0.95}

DefaultFloors are the confidence floors Tune reports on when none are given.

Kinds is every kind a unit may name, in the order the spec names them.

Touches is every touch a unit may name.

Functions

func AppendEntry

func AppendEntry(path string, e Entry) error

AppendEntry appends one row to the log at path, creating it if it is not there. The file is the tool's own (0600) and is never rewritten.

func KnownKind

func KnownKind(kind string) bool

KnownKind reports whether the kind is one of the ten.

func Line

func Line(prefix string, answers map[string]Answer, floor float64) string

Line renders one status line for a decision: the prefix, one <name>=<value> conf=<0-1> pair per answer in name order, then the floor and the below list naming every answer under it. A decision below the floor is a suggestion, never an authorization.

func Mechanical

func Mechanical(kind string) bool

Mechanical reports whether a kind is mechanical -- the only kinds a DeepSeek rung is eligible for.

func ParseQuestions

func ParseQuestions(data []byte) (map[string]Question, error)

ParseQuestions parses a questions file: either a bare map of name to question, or {"questions": {...}}. Each entry carries a type (choice/score/noul), instructions, and criteria (a map for choice, a list for score, absent for noul). Anything else is a refusal, never a guess.

func QuestionHash

func QuestionHash(state, name string, q Question) string

QuestionHash is the stable hash of one question over its state: the kind, the name, the instructions and the state text. A replay names the same hash, so an answer already journaled is reproduced without calling the provider.

func StartHeight

func StartHeight(kind string) (int, bool)

StartHeight is the starting rung for a kind before any evidence adjusts it.

func ValidFloor

func ValidFloor(floor float64) error

ValidFloor refuses a floor that is not a number between 0 and 1, with the one remedy in the message. NaN compares false against every bound, so a bare `floor < 0 || floor > 1` lets it through -- which is exactly how it got in.

func ValidateAnswers

func ValidateAnswers(qs map[string]Question, answers map[string]Answer) error

ValidateAnswers checks each typed answer against the question it answers. It is the last gate before an answer becomes a decision: a choice outside the criteria, a choice naming nothing, an answer of the wrong type, and an answer to a question nobody asked are all PROVIDER ERRORS rather than decisions.

The check is deterministic: questions are walked in name order, so the same bad response always names the same first offence.

Types

type Answer

type Answer struct {
	Type          string
	Choice        string
	Probabilities map[string]float64
	Score         float64
	Noul          float64
	Confidence    float64
}

Answer is one typed answer. Type names which of the three it is ("choice", "score" or "noul"). Choice and Probabilities are set for choice answers, Score for score answers, Noul for noul answers; Confidence is set for choice and score answers from the response, and for a noul answer it is the noul value itself: the confidence that the question is null.

func (Answer) Value

func (a Answer) Value() string

Value renders one answer as the table's answer column: the chosen option, the score, or the noul value.

type Attempt

type Attempt struct {
	Rung       string `json:"rung"`
	Outcome    string `json:"outcome"`
	Reason     string `json:"reason,omitempty"`
	Terminated bool   `json:"terminated,omitempty"`
}

Attempt is one prior attempt on this unit: the rung, what happened, why, and -- for a timeout -- whether the attempt is known to have TERMINATED. It is what makes the ladder a retry policy: a confirmed failure re-enters the decision carrying its own evidence.

Terminated is the lease rule (Stella): a timeout is a silence, not a death. Until something proves the attempt is dead, its expiry is UNKNOWN, and a rung whose attempt may still be running is not a rung to step off.

func (Attempt) Failed

func (a Attempt) Failed() bool

Failed reports whether this attempt is a CONFIRMED failure -- one the ladder may step past. A timeout counts only once termination is proved: an attempt that may still be running has not failed, it has not finished.

func (Attempt) Open

func (a Attempt) Open() bool

Open reports whether this attempt timed out with no proof that it died. The answer for an open attempt is the same rung, not the next one.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to one Jev endpoint with one key the caller named.

func New

func New(baseURL, keyEnv string) (*Client, error)

New reads the key from the environment variable keyEnv (DefaultKeyEnv when empty, with FallbackKeyEnv also accepted) and refuses with an error naming the variable when it is unset. baseURL empty means DefaultBaseURL. The key is never printed.

func (*Client) Decide

func (c *Client) Decide(ctx context.Context, state string, qs map[string]Question) (map[string]Answer, Usage, error)

Decide asks the provider one typed decision and parses the answers. It applies a 10 s deadline of its own. A decision below the caller's floor is a suggestion, never an authorization: the caller keeps today's behaviour as the fallback.

func (*Client) SetFloor

func (c *Client) SetFloor(f float64)

SetFloor sets the confidence floor the client logs beside a decision. The zero value keeps DefaultFloor.

func (*Client) UseDecisions

func (c *Client) UseDecisions(d DecisionDriver)

UseDecisions attaches the client's decisions table. It is the one writer rule 8 names: Decide appends a row per answer after every call. A nil driver leaves the client without a table.

type Decider

type Decider interface {
	Decide(ctx context.Context, state string, qs map[string]Question) (map[string]Answer, Usage, error)
}

Decider is the seam a route asks a typed decision through. *Client is one; a test passes a fake, so no unit test ever dials the provider.

type DecisionDriver

type DecisionDriver interface {
	Append(row DecisionRow) error
	Rows(kind string) ([]DecisionRow, error)
	Close() error
}

DecisionDriver is the storage seam for the decisions table. The tool opens one driver per process. Append is the one writer; Rows is the read every other verb uses; Close releases the handle.

func OpenDecisions

func OpenDecisions(dsn string) (DecisionDriver, error)

OpenDecisions opens the decisions table a DSN names. A postgres:// or postgresql:// DSN opens the linked Postgres driver; any other value is a path to the TSV fallback, where the files stay the record. An empty DSN is a refusal, never a guess.

type DecisionRow

type DecisionRow struct {
	QuestionHash       string
	Kind               string
	Answer             string
	ProviderConfidence float64
	Floor              float64
	Outcome            string
}

DecisionRow is one row of the decisions table: the question that was asked, the kind of judgment, the answer, the provider's confidence, the floor it was gated on, and the outcome that followed (empty until known).

type Entry

type Entry struct {
	Time          string  `json:"time"`
	Unit          string  `json:"unit"`
	Kind          string  `json:"kind"`
	Evidence      Unit    `json:"evidence"`
	RungTried     string  `json:"rung_tried"`
	Height        int     `json:"height"`
	Confidence    float64 `json:"confidence"`
	Floor         float64 `json:"floor"`
	SteppedUp     bool    `json:"stepped_up"`
	Escalated     bool    `json:"escalated"`
	Designated    bool    `json:"designated,omitempty"`
	Source        string  `json:"source"`
	RowanPick     string  `json:"rowan_pick"`
	Reason        string  `json:"reason,omitempty"`
	Outcome       string  `json:"outcome,omitempty"`
	RungSucceeded string  `json:"rung_succeeded,omitempty"`

	// Wait is the typed action beside the rung: "-" for a decision the caller
	// may act on, awaiting_termination for one it may not.
	Wait string `json:"wait,omitempty"`
	// Refusal is why the route ended in a refusal, where it did. The row is
	// still written: a call that was already made is still a cost, and a
	// decision that could not be made is still evidence.
	Refusal string `json:"refusal,omitempty"`
	// AwaitingTermination is the same fact as a boolean, for a reader that
	// gates on it: the rung named is the one an attempt may still be running
	// on, and the lease rule keeps its expiry UNKNOWN until termination.
	AwaitingTermination bool `json:"awaiting_termination,omitempty"`

	// What the decision spent. Calls is the number of provider calls it made;
	// TokensIn and TokensOut are ABSENT rather than zero where no call was made
	// or the call failed, because a zero is a measurement and an absence is not
	// (SPEC-TOKENS rule 14). UsageFailed marks a call whose cost is unknown.
	Calls       int  `json:"calls,omitempty"`
	TokensIn    *int `json:"tokens_in,omitempty"`
	TokensOut   *int `json:"tokens_out,omitempty"`
	UsageFailed bool `json:"usage_failed,omitempty"`
}

Entry is one row of the escalation log.

func EntryFor

func EntryFor(res RouteResult, u Unit, now time.Time) Entry

EntryFor is the row one route decision writes. The outcome and the rung that succeeded are filled in later, by the caller that watched the work: a decision never writes them for itself.

func ReadEntries

func ReadEntries(path string) ([]Entry, error)

ReadEntries reads the log back. A missing file, or a line that is not one JSON object, is a refusal naming what it could not read.

type FloorStat

type FloorStat struct {
	Floor     float64
	Decided   int
	Agree     int
	Escalated int
}

FloorStat is one floor's line: how many rows the floor decided, how many of those agreed with their label, and how many it escalated.

func (FloorStat) AgreeRate

func (s FloorStat) AgreeRate() float64

AgreeRate is the share of decided rows that agreed with their label.

func (FloorStat) EscalationRate

func (s FloorStat) EscalationRate(labeled int) float64

EscalationRate is the share of labeled rows the floor left below it.

type HelpResult

type HelpResult struct {
	Answer string
	Reason string
}

HelpResult is the answer and why.

func Help

func Help(s HelpState) (HelpResult, error)

Help answers the second decision. Nothing here is a judgment call at run time: the same evidence gives the same answer, on any bench, with no network.

func (HelpResult) Line

func (r HelpResult) Line() string

Line is the one line the help decision prints.

type HelpState

type HelpState struct {
	Hours            float64 `json:"hours"`
	RetriesOnRung    int     `json:"retries_on_rung"`
	FailuresLastHour int     `json:"failures_last_hour"`
	SelfInflicted    int     `json:"self_inflicted"`
	ClassRecurring   bool    `json:"class_recurring"`
	LandingMoved     bool    `json:"landing_moved"`
	Uncertainty      float64 `json:"uncertainty"`
	AskedAllFriends  bool    `json:"asked_all_friends"`
}

HelpState is the evidence for the help decision.

func ParseHelpState

func ParseHelpState(data []byte) (HelpState, error)

ParseHelpState reads the help evidence from JSON, refusing a field it does not hold.

func (HelpState) Validate

func (s HelpState) Validate() error

Validate refuses a state that cannot be, rather than answering over it.

type KindSummary

type KindSummary struct {
	Kind        string
	Decisions   int
	Escalations int
	Successes   int
	Failures    int
	StartHeight int
	StartRung   string
	DefaultRung string
	Regenerated bool
}

KindSummary is one kind's read of the log: how many decisions, how many were escalations, and the starting rung regenerated from the rows beside the default it replaces.

type Mind

type Mind struct {
	Name         string   `json:"name"`
	Lineage      string   `json:"lineage"`
	Height       int      `json:"height"`
	Kinds        []string `json:"kinds"`
	Lanes        []string `json:"lanes"`
	Availability string   `json:"availability"`
	Ask          string   `json:"ask"`

	// Model is the model id a unit dispatched to this mind RUNS with, where
	// this mind is a model at all. It is registry data and never a constant
	// here: the ladder comes from the file, and so do the ids on it. A mind
	// asked on the bus or as a child is a person or a coordinator and carries
	// none, so a caller that can only dispatch a model keeps today's model and
	// says so.
	Model string `json:"model,omitempty"`
}

Mind is one rung of the ladder: its name, the lineage it thinks in, its height, the kinds it is designated for, the lanes it owns, its availability and how it is asked.

func (Mind) DesignatedFor

func (m Mind) DesignatedFor(kind string) bool

DesignatedFor reports whether this mind is the rung for that kind by designation -- by KIND, never by height.

func (Mind) Dispatchable

func (m Mind) Dispatchable() bool

Dispatchable reports whether this mind can be handed a unit as a MODEL: it is asked as a card and the registry gives the model id to run it with.

func (Mind) Owns

func (m Mind) Owns(lane string) bool

Owns reports whether this mind owns the named lane. An empty lane is owned by nobody, so a unit that names none has no owner to prefer.

func (Mind) Usable

func (m Mind) Usable() bool

Usable reports whether the height ladder may pick this mind at all. A reserved or asleep mind is not on the ladder; a reserved one is still reachable by a designation.

type Question

type Question struct {
	Instructions string
	Choice       map[string]string
	Score        []string
	Noul         bool
}

Question is one typed question. Exactly one of Choice, Score or Noul must be set: a non-nil Choice is a choice question with per-option descriptions, a non-nil Score is a score question with ordered level texts, and Noul true is a noul question carrying only its statement in Instructions.

func (Question) Kind

func (q Question) Kind() string

Kind names which of the three question types q is, or "" for a malformed question.

type Registry

type Registry struct {
	Minds []Mind `json:"minds"`
}

Registry is the ladder: every mind, in height then name order.

func DefaultRegistry

func DefaultRegistry() (*Registry, error)

DefaultRegistry is the embedded ladder, the one a bench with no registry file runs on.

func LoadRegistry

func LoadRegistry(path string) (*Registry, error)

LoadRegistry reads the registry a path names. An empty path is the embedded default; an unreadable or invalid file is a refusal naming the path.

func ParseRegistry

func ParseRegistry(data []byte) (*Registry, error)

ParseRegistry parses and validates a registry. Every row must name a mind, a lineage, a height at or above zero, an availability of the three, and an ask of the three (a row naming none is asked on the bus). A duplicate name, an empty table or anything else is a refusal.

func (*Registry) AtHeight

func (r *Registry) AtHeight(h int) []Mind

AtHeight is every mind on one rung, in name order.

func (*Registry) ByName

func (r *Registry) ByName(name string) (Mind, bool)

ByName finds one mind.

func (*Registry) DesignatedFor

func (r *Registry) DesignatedFor(kind string) []Mind

DesignatedFor is every mind designated for a kind, in height then name order.

func (*Registry) Heights

func (r *Registry) Heights() []int

Heights is every rung height the registry holds, ascending.

func (*Registry) ModelFor

func (r *Registry) ModelFor(name string) (string, bool)

ModelFor is the model id a rung runs a unit with, and whether the registry gives it one at all. A rung with no model is not a refusal: it is a mind a card cannot be dispatched to, and the caller keeps today's model.

func (*Registry) RungName

func (r *Registry) RungName(h int) string

RungName names a height: one mind, or every mind on that rung joined by "/" -- the two lineages of one rung are one rung.

func (*Registry) TopHeight

func (r *Registry) TopHeight() int

TopHeight is the highest rung: above it there is nothing to escalate to.

type RouteResult

type RouteResult struct {
	Unit       string
	Kind       string
	Rung       Mind
	Confidence float64
	Floor      float64
	Reason     string
	Wait       string
	Refusal    string
	SteppedUp  bool
	Escalated  bool
	Designated bool
	Source     string
	RulesRung  string
	Offered    []string
	Usage      RouteUsage
	// Next is the rung ABOVE the one answered, named whenever the answer is
	// below the floor. The step-up signal used to name only the question that
	// fell short, which left a reader to work out where the work goes next from
	// a ladder they cannot see (edge 24). It is empty at or above the floor,
	// and empty where there is no rung above.
	Next string
	// Steps is how many decisions this answer took: 1 for an ordinary route,
	// and one more for each re-ask --step-up made.
	Steps int
}

RouteResult is one routing decision: the rung, the number the floor was applied to, the floor, why, the typed wait, what it spent, and -- for the log -- what the rules alone would have picked.

A REFUSED decision is still a RouteResult. Where the route ends in an error, the result comes back populated with everything that was already true -- above all what a completed provider call spent -- and Refusal says why it ended. A refusal cannot unspend tokens, so the caller persists the row and then exits on the refusal (Stella, #1327).

func RouteJev

func RouteJev(ctx context.Context, d Decider, reg *Registry, u Unit, floor float64) (RouteResult, error)

RouteJev asks the provider which rung, among the eligible ones the rules offer, and keeps the machinery's word everywhere it matters: security and a designation are never asked, a rung that may still be running is never asked (there is no choice to make while an attempt is alive), a choice below the floor steps up, and a provider error or a rung nobody offered leaves the rules' answer standing.

func RouteRules

func RouteRules(reg *Registry, u Unit, floor float64) (RouteResult, error)

RouteRules answers by the rules alone: no provider, no key, no network, the same answer every time. It is what --no-jev runs, and it is the answer the provider's is measured against in the log.

func RouteStepUp

func RouteStepUp(ctx context.Context, d Decider, reg *Registry, u Unit, floor float64, maxSteps int) ([]RouteResult, error)

RouteStepUp turns the step-up SIGNAL into the rung above it (edge 24).

Exit 3 said "below the floor" and named the question that fell short, and there it stopped: nothing re-asked, and the caller was left to read a ladder it cannot see. This asks, and where the answer is below the floor it EXCLUDES that rung from the criteria and asks the same question again, up to maxSteps times.

Every step is a decision in its own right: the slice returned holds them all, in order, each carrying its own reason and its own step number, and the caller logs every one of them. The last is the answer, and its exit code is the ordinary one -- a step-up that never got above the floor is still a suggestion, never an authorization.

func (RouteResult) AwaitingTermination

func (r RouteResult) AwaitingTermination() bool

AwaitingTermination reports whether this decision is a wait on an attempt that is not known to have terminated.

func (RouteResult) Dispatchable

func (r RouteResult) Dispatchable() bool

Dispatchable reports whether the caller may hand the unit to the rung named. A wait is an answer about WHO owns the work, not permission to start it.

func (RouteResult) Line

func (r RouteResult) Line() string

Line is the one line a route decision prints: the unit (the evidence pointer), the rung, the confidence, the floor it was gated on, the rung ABOVE it where the answer fell below that floor, how many steps the answer took, the reason and how that rung is asked. Every field is on every line: next is the dash where there is nothing above and nothing to step to, so no reader has to infer an absence.

type RouteUsage

type RouteUsage struct {
	Calls        int
	InputTokens  int
	OutputTokens int
	HasInput     bool
	HasOutput    bool
	Failed       bool
}

RouteUsage is what one routing decision spent with the provider: how many calls it made, the counters the provider reported, and -- PER COUNTER -- whether it reported them at all. A call that failed, and a call that answered without saying what it cost, both spent something we cannot measure, and UNKNOWN is not zero (SPEC-TOKENS rule 14).

func (RouteUsage) Known

func (u RouteUsage) Known() bool

Known reports whether any counter was measured.

type Summary

type Summary struct {
	Entries int
	Kinds   []KindSummary
}

Summary is the whole read of the log.

func Summarize

func Summarize(reg *Registry, entries []Entry) (Summary, error)

Summarize counts the escalations per kind and regenerates the starting rung from the rows. An entry naming a kind the table does not hold is a refusal: a summary over evidence nobody can read is not a summary.

func (Summary) Render

func (s Summary) Render() string

Render is the summary, one line per kind then the finish.

type TuneOptions

type TuneOptions struct {
	Label         string
	Choice        string
	Conf          string
	Floors        []float64
	MaxEscalation float64
}

TuneOptions names the fields a decisions log carries and the floors to try. An empty field name or floor list takes the default; an empty label is a row to skip, never a field to guess.

type TuneResult

type TuneResult struct {
	Lines     int
	Labeled   int
	Floors    []FloorStat
	BestFloor float64
}

TuneResult is the whole read of a decisions log: the line and labeled counts, one stat per floor, and the best floor under the escalation cap.

func Tune

func Tune(data []byte, opts TuneOptions) (TuneResult, error)

Tune parses a decisions log and reports, per floor, the decisions it made and the rows it escalated, then the best floor under the escalation cap. A line that is not a JSON object, or a labeled line with no confidence, is a refusal, never a guess.

func (TuneResult) Render

func (r TuneResult) Render() string

Render is the tune read, one line per floor then the finish. Every rate is printed to two places and every floor verbatim.

type Unit

type Unit struct {
	ID        string    `json:"id"`
	Kind      string    `json:"kind"`
	Files     int       `json:"files,omitempty"`
	Packages  int       `json:"packages,omitempty"`
	Lanes     int       `json:"lanes,omitempty"`
	LaneOwner string    `json:"lane_owner,omitempty"`
	Attempts  []Attempt `json:"attempts,omitempty"`
	Platform  string    `json:"platform,omitempty"`
	Guard     bool      `json:"guard,omitempty"`
	Secrets   bool      `json:"secrets,omitempty"`
	Touches   []string  `json:"touches,omitempty"`
	FreshTake bool      `json:"fresh_take,omitempty"`
	Deadline  string    `json:"deadline,omitempty"`
}

Unit is the evidence for one unit of work: its kind, its size (files, packages, lanes), the lane's owner, the prior attempts, any platform need, whether a guard or secrets are touched, whether it wants a fresh take, and the deadline. The ID is the evidence pointer every decision line carries (SPEC-DECIDE rule 10), so a person can retrieve the original.

func ParseUnit

func ParseUnit(data []byte) (Unit, error)

ParseUnit reads one unit of evidence from JSON. Anything that is not an object, or an object whose evidence cannot be, is a refusal.

func (Unit) Public

func (u Unit) Public(reg *Registry) (map[string]string, error)

Public is the unit's public projection: the typed, enumerated evidence the provider is given, and the whole of what it is given about the unit. The unit's id, its lane's spelling, its platform's name, its deadline and every attempt reason stay here. A value that is not on the allowlist is a refusal rather than a payload.

func (Unit) Security

func (u Unit) Security() bool

Security reports whether this unit is security work: a guard, secrets, the sandbox, sudo, deploy keys or the network. It is a KIND and not a height, and it is answered here rather than by any provider.

func (Unit) Validate

func (u Unit) Validate() error

Validate checks the evidence itself, before any registry is consulted.

type Usage

type Usage struct {
	InputTokens  int
	OutputTokens int
	HasInput     bool
	HasOutput    bool
}

Usage counts the tokens one call spent, and says PER COUNTER whether the provider reported it at all. A 200 carrying a valid answer is not evidence of reported usage: a response with no usage object, or one naming only some of the counters, has said nothing about the rest -- and nothing is not zero. An explicitly reported 0 is a measurement and is kept as one (SPEC-TOKENS rule 14).

func (Usage) Known

func (u Usage) Known() bool

Known reports whether the provider measured anything at all.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL