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
- Variables
- func AppendEntry(path string, e Entry) error
- func KnownKind(kind string) bool
- func Line(prefix string, answers map[string]Answer, floor float64) string
- func Mechanical(kind string) bool
- func ParseQuestions(data []byte) (map[string]Question, error)
- func QuestionHash(state, name string, q Question) string
- func StartHeight(kind string) (int, bool)
- func ValidFloor(floor float64) error
- func ValidateAnswers(qs map[string]Question, answers map[string]Answer) error
- type Answer
- type Attempt
- type Client
- type Decider
- type DecisionDriver
- type DecisionRow
- type Entry
- type FloorStat
- type HelpResult
- type HelpState
- type KindSummary
- type Mind
- type Question
- type Registry
- func (r *Registry) AtHeight(h int) []Mind
- func (r *Registry) ByName(name string) (Mind, bool)
- func (r *Registry) DesignatedFor(kind string) []Mind
- func (r *Registry) Heights() []int
- func (r *Registry) ModelFor(name string) (string, bool)
- func (r *Registry) RungName(h int) string
- func (r *Registry) TopHeight() int
- type RouteResult
- type RouteUsage
- type Summary
- type TuneOptions
- type TuneResult
- type Unit
- type Usage
Constants ¶
const ( HelpContinue = "continue" HelpAskAllFriends = "ask-all-friends" HelpAskGlenn = "ask-glenn" )
The three answers.
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.
const ( OutcomeOK = "ok" OutcomeFailed = "failed" OutcomeTimeout = "timeout" OutcomeAbandoned = "abandoned" )
The outcome of one attempt.
const ( SourceRules = "rules" SourceJev = "jev" )
Where a route answer came from.
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.
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.
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.
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.
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.
const DefaultBaseURL = "https://api.typesafe.ai/v1/systemone"
DefaultBaseURL is the TypeSafe Jev endpoint New uses when baseURL is empty.
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.
const DefaultKeyEnv = "JEV_API_KEY"
DefaultKeyEnv is the environment variable New reads when keyEnv is empty. TYPESAFE_API_KEY is accepted as a fallback.
const DefaultMaxEscalation = 0.7
DefaultMaxEscalation is the escalation-rate cap Tune uses to pick the best floor when none is given.
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.
const DefaultModel = "jev-latest"
DefaultModel is the model every request names.
const DesignationFreshTake = "fresh-take"
DesignationFreshTake is the kind designation for a fresh take: the rungs below failed, or a design with one author.
const FallbackKeyEnv = "TYPESAFE_API_KEY"
FallbackKeyEnv is accepted when the named variable is unset.
const MinLabeled = 10
MinLabeled is the fewest labeled rows a floor can be set from.
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.
const RungQuestion = "rung"
RungQuestion is the name of the one choice Jev is asked.
Variables ¶
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).
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.
var Kinds = []string{ KindRebase, KindStack, KindFixtureRetarget, KindFleetChore, KindFixWithRedTest, KindNewVerb, KindSpec, KindDesign, KindGuard, KindCauseToFind, }
Kinds is every kind a unit may name, in the order the spec names them.
var Touches = []string{TouchGuard, TouchSecrets, TouchSandbox, TouchSudo, TouchDeployKeys, TouchNetwork}
Touches is every touch a unit may name.
Functions ¶
func AppendEntry ¶
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 Line ¶
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 ¶
Mechanical reports whether a kind is mechanical -- the only kinds a DeepSeek rung is eligible for.
func ParseQuestions ¶
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 ¶
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 ¶
StartHeight is the starting rung for a kind before any evidence adjusts it.
func ValidFloor ¶
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 ¶
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.
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.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to one Jev endpoint with one key the caller named.
func New ¶
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 ¶
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 ¶
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 ¶
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) EscalationRate ¶
EscalationRate is the share of labeled rows the floor left below it.
type HelpResult ¶
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 ¶
ParseHelpState reads the help evidence from JSON, refusing a field it does not hold.
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 ¶
DesignatedFor reports whether this mind is the rung for that kind by designation -- by KIND, never by height.
func (Mind) Dispatchable ¶
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.
type Question ¶
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.
type Registry ¶
type Registry struct {
Minds []Mind `json:"minds"`
}
Registry is the ladder: every mind, in height then name order.
func DefaultRegistry ¶
DefaultRegistry is the embedded ladder, the one a bench with no registry file runs on.
func LoadRegistry ¶
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 ¶
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) DesignatedFor ¶
DesignatedFor is every mind designated for a kind, in height then name order.
func (*Registry) ModelFor ¶
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.
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.
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 ¶
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 ¶
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 ¶
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.
type Usage ¶
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).