shaped

package
v0.7.1 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package shaped is the one place the harness asks a model for an answer of a stated shape and reads what comes back.

── WHY IT IS ONE PLACE ──

Before it existed, every pass that wanted JSON out of a model built its own version of the same three-step sequence: send with some ceiling, decode, and decide what an unusable reply means. The planner had one, the delivery gate had another, the intent compiler had a third, and two of them scanned for braces by hand. They disagreed about everything that matters. The s4 sweep (bench/deepswe/AUTOPSY.md) cost two of five runs to that disagreement, on one model, in one afternoon:

  • the planner's fan-out was cut at the completion ceiling, the object was incomplete, and the run exited 1 with zero nodes and a third of a cent spent — nothing attempted, on a task that had scored 17/20 the sweep before;
  • the delivery gate's verdict came back unreadable, which its own caller treated as an abstention, so the work was "delivered as done, unjudged" and the run exited 0.

Neither is a failure of a model. Both are failures of a boundary that had no owner: a ceiling nobody derived from the ask, a truncation nobody continued, and a non-answer that meant something different at each door it arrived at.

── THE THREE THINGS THIS OWNS ──

SIZING. The ceiling on a structured reply is derived from the ask — how many objects it asks for and how much of the material it must echo back — and then raised by what this model has actually been seen to need on this lane. See ceiling.go; the derivation is documented in PERF.md.

REPAIR. A reply cut off mid-object is CONTINUED rather than re-bought: the expensive half of it is already in hand, and re-asking spends the same tokens to hit the same wall, which is precisely what the planner did before it gave up. A reply that never began an object is a different failure — prose, or a whole ceiling spent thinking — and there is nothing there to continue, so that one is asked again, once, with the format contract and its own offending words quoted back at it.

THE VERDICT ON FAILURE. When the repairs are spent, this returns a TYPED fault. A caller may not read it as "the model declined to answer" or as "nothing to judge": the answer was not delivered, which is a fact about the run and has to reach the exit code. FAILSAFE.md's floor — a fail-safe cannot deliver nothing as done — is enforced by that type existing and by callers switching on it.

What is NOT here: whether an answer that parsed is RIGHT. Only the call site can know that, and it reports it as it always did (provider.Report).

Index

Constants

This section is empty.

Variables

View Source
var ErrUnreadable = errors.New("the model did not answer in the shape this asked for")

ErrUnreadable is what a caller gets when the model would not answer in the shape that was asked for, after this seam has done everything it can.

IT IS A FAULT AND NEVER AN ABSTENTION. The distinction is the whole reason the type exists: the delivery gate used to read an unreadable verdict as "no opinion" and ship the work as done, which is the exact failure FAILSAFE.md's floor forbids. A caller that catches this must either retry the work or end the run short of whole; it may not proceed as though nothing had happened.

Functions

func Answer

func Answer(ctx context.Context, client Completer, ask Ask, into any) (*ai.Response, error)

Answer sends one ask, repairs what can be repaired, and decodes the result into the caller's destination.

The response it returns is the LAST one on the wire, so a caller adding up usage adds up the repair as well as the original — a repaired call costs what it costs, and a bill that hid the repair would make this seam look free. When an answer was continued, the returned response carries the joined text, so a caller that re-reads the text sees the whole answer rather than the fragment.

It reports the two verdicts it can determine by itself — a transport failure and a format failure — and leaves the semantic one to the caller, which is the contract plan.structured established and this inherits unchanged.

func ObjectShaped

func ObjectShaped(text string) bool

ObjectShaped reports whether the WHOLE of an answer is one data object.

It is a structural reading and never a reading of what the object says: the text, stripped of a code fence, opens on a brace, closes on its match, and parses. That is a fact about the answer's shape, which is what this repairs; what the object CONTAINS is the worker's business and none of this package's.

It is deliberately stricter than provider.DecodeJSONObject, which finds an object anywhere inside a reply. An answer that explains something and happens to quote a JSON snippet is prose and must be left alone; only an answer that IS an object is the failure being repaired.

func Prose

func Prose(ctx context.Context, client Completer, ask Ask, answered string) (string, bool)

Prose is Answer's mirror: one repair for an answer that came back as a data object where the ask wanted the answer itself.

It returns the answer to use and whether anything was repaired. An answer that was never object-shaped comes back untouched and unrepaired, which is every delivery in the system but the ones this exists for. A repair that could not be had — the model unreachable, an empty reply, a second object — comes back as the ORIGINAL, because a delivery whose shape could not be fixed is still the delivery and dropping it would lose the only account the run has.

Both endings are journaled. A reshape that failed is exactly as interesting to an autopsy as one that worked, and rather more so: it is a model that would not answer in the shape asked twice running.

func Room

func Room(ask Ask, model string) int

Room is what one ask's reply is COUNTED as being worth, never what it is sent with. See the derivation and its first paragraph above.

It takes the model rather than reading it from the context because the caller has already resolved it — Answer asks the router's slot once — and because a test can then state the memo's key without standing up a router.

func Unreadable

func Unreadable(err error) bool

Unreadable reports whether an error is that fault, wrapping included.

func WithJournal

func WithJournal(ctx context.Context, journal Journal) context.Context

WithJournal names where repairs made under ctx are recorded.

Types

type Ask

type Ask struct {
	// Lane names the pass making the ask, in the words a person would use for
	// it: "plan", "gate", "compile". It is the memo's key beside the model and
	// the subject of the line the stream prints, so it is a name and never a
	// class identifier.
	Lane string

	// Messages are the request as the caller assembled it. The seam appends to
	// a copy when it repairs and never rewrites what is here.
	Messages []ai.Message

	// Schema is the shape being asked for. It is used for two things: sent on
	// the wire when Routed, and read by the ceiling derivation, which counts
	// what one answer of this shape has to hold.
	Schema json.RawMessage

	// Routed says whether this client can carry a structured-output request. A
	// build with no router has no second rung to unlock and sends none — the
	// tolerance in provider.DecodeJSONObject is what stands in for it.
	Routed bool

	// JSON asks for an object on the wire without pinning its shape: JSON mode
	// rather than a strict schema. It is for an ask whose shape is the prompt's
	// to extend — the compile's menu, charter and model note are fields the
	// prompt adds when they apply, and a schema would have to know every one.
	// A prompt alone was not enough: a model handed an issue written in Markdown
	// answered in Markdown, twice, and the whole job was forfeit for $0.0007.
	// It goes out on every send of the ask, the repairs included.
	JSON bool

	// Answers is how many objects of the schema's item shape the ask expects
	// back — the fan-out's permitted width, a panel's seat count. Zero and one
	// both mean "one object", which is every other call in the system.
	//
	// IT IS THE ASK'S OWN NUMBER AND NEVER A GUESS. Where a prompt tells the
	// model how many parts it may return, that same figure is what is passed
	// here, so the sentence the model reads and the room it is given can never
	// drift apart.
	Answers int

	// Echo is the material this answer has to carry back verbatim, when there is
	// any. The intent compiler's brief restates the user's instruction twice —
	// once inside the goal and once under "Verbatim request:" — so its reply
	// cannot be smaller than the ask however small the schema is. A pass whose
	// answer quotes nothing leaves this empty.
	Echo string
}

Ask is one request for a shaped answer.

Everything on it except the messages is here because the seam needs it to size or to repair the call — there is no field a caller sets that only its own pass reads.

type Completer

type Completer interface {
	CompleteWithMessages(ctx context.Context, messages []ai.Message, options ...ai.Option) (*ai.Response, error)
}

Completer is the half of a model client this package uses. It is stated structurally rather than imported so that the planner's own Completer, the pooled client the gate holds, and a test's stub all satisfy it without any of them learning about this package.

type Journal

type Journal interface {
	Repaired(Repair)
}

Journal is where repairs go. One method, because a journal that could be asked questions would be a journal callers started reading during a request.

func JournalFrom

func JournalFrom(ctx context.Context) Journal

JournalFrom returns the journal in force for ctx, nil when none was installed.

type JournalFunc

type JournalFunc func(Repair)

JournalFunc lets a plain function be a journal, which is what a test and a one-line wiring both want.

func (JournalFunc) Repaired

func (f JournalFunc) Repaired(repair Repair)

type Repair

type Repair struct {
	Lane    string     `json:"lane"`
	Model   string     `json:"model,omitempty"`
	Kind    RepairKind `json:"kind"`
	Round   int        `json:"round,omitempty"`
	Spent   int        `json:"spent,omitempty"`
	Ceiling int        `json:"ceiling,omitempty"`

	// Note is WHY the answer could not be read, in the reader's own words.
	//
	// "The answer was not readable" is two different facts and this seam was
	// journaling one word for both. A reply that never contained an object at
	// all is a model reasoning out loud, and the re-ask is the mechanism
	// working. A reply that decoded and was refused by the caller's own
	// contract — a delivery verdict naming a file the record does not hold, or
	// quoting something the request never states — is a model answering a
	// question it was asked badly, and the re-ask may be buying nothing.
	//
	// textual v4-flash s13 holds two of these on lane `gate` and no way to tell
	// which: settling it meant reading token counts out of the usage table
	// three events either side. The error the decode returned says it in one
	// line, and it is the line nobody had.
	Note string `json:"note,omitempty"`
}

Repair is one thing the seam did to get an answer, as the record keeps it.

func (Repair) Line

func (r Repair) Line() string

Line is the whole narration line for one repair, subject included.

func (Repair) Words

func (r Repair) Words() string

Words is the repair as a person reads it, in the register the headless stream's other narration lines use: what happened, then what was done about it. No machinery vocabulary — a reader is told the answer was cut off, never that a finish reason was length.

type RepairKind

type RepairKind string

RepairKind is what the seam did.

const (
	// RepairContinued: the answer was cut at the ceiling with the object still
	// open, and the rest of it was asked for.
	RepairContinued RepairKind = "continued"
	// RepairReasked: the reply was not an object at all, and it was asked again
	// with the format contract and its own words quoted back.
	RepairReasked RepairKind = "reasked"
	// RepairFailed: the repairs are spent and the caller is getting a fault.
	RepairFailed RepairKind = "failed"
)
const RepairReshaped RepairKind = "reshaped"

RepairReshaped: the answer came back as a data object where the ask wanted the work itself, and it was asked once more for the shape it was asked for.

Jump to

Keyboard shortcuts

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