consent

package
v0.7.0 Latest Latest
Warning

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

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

Documentation

Overview

Package consent is the price before the purchase.

Every number in this system used to be retrospective. Cost was computed after spending, the rail fired after crossing, and the first quantity a user ever saw about a fifty-leaf job was a step count emitted well after the planning that produced it had been paid for. There was no moment at which a person could look at what they had asked for and decline it.

This is that moment, and it is deliberately small: one question, quoting a count and a price, with two options, on the last tick at which not starting is free — the claim. Below the threshold nothing is asked at all, because a resident that asks permission for two dollars of work is not a resident.

It is a package rather than a corner of the chat window because the desk has to be reachable from wherever work is admitted. A window-side desk answers only for the process holding the terminal; a resident-side orchestrator — the August 2026 chat-rebuild audit's 4.6 v2 (no longer in the tree) — admits work with no window attached at all, and until this moved it had no way to price anything (Part 9.10).

Index

Constants

View Source
const (
	// Approve and Hold are the two answers. The gate reads the recorded
	// resolution rather than decoding an option value, so the labels are the
	// contract and are matched exactly.
	Approve = "yes, start it"
	Hold    = "hold it — I'll trim it first"
)
View Source
const Category = store.QuestionCategory("plan-consent")

Category names this ask for the empirical gate the way every other durable question is named. It is its own class because its answer is the one thing no default may be assumed for: the whole point is that a person said yes before the money moved.

Variables

This section is empty.

Functions

func JobRootOf

func JobRootOf(graph *store.Store, node store.Node) (store.Node, bool)

JobRootOf walks to the top-level node an errand hangs from. It is the unit a price is quoted for, because it is the unit a person asked for.

func MedianLeafCost

func MedianLeafCost(measured *profile.Profile) float64

MedianLeafCost is what one leaf of ordinary planned work has cost this model. The median rather than the mean because leaf costs are long-tailed and one runaway must not set the price of the next fifty.

Types

type Desk

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

Desk holds the jobs waiting on an answer and releases them when one arrives. It is in-memory because it is a watch loop, not a record: the question and the hold are both durable, so a restart rebuilds the watch from the graph rather than from anything kept here.

func NewDesk

func NewDesk(graph *store.Store) *Desk

NewDesk builds a desk over one durable graph.

func (*Desk) Gate

func (d *Desk) Gate(settings config.Config, measured *profile.Profile, node store.Node) bool

Gate is the last free moment. It returns true when the caller must not run.

The hold is what makes this work without a new mechanism: a held node is not ready, the runner's landing path already treats a held claim as a release rather than a failure, and the leaf that got this far has spent nothing yet because this is the first thing its executor does.

func (*Desk) Rehydrate

func (d *Desk) Rehydrate()

Rehydrate rebuilds the watch after a restart. Held nodes and unanswered questions are both durable, so a resident that died between the question and the answer comes back knowing exactly what it was waiting for — and a job approved while it was down is released on the way up rather than sitting held forever.

func (*Desk) Serve

func (d *Desk) Serve(ctx context.Context)

Serve is the release loop. It sleeps on a channel while nothing is waiting, which is the difference between a feature and a tax on every idle resident.

func (*Desk) WithHeadless

func (d *Desk) WithHeadless(answer func(store.Node, Estimate) bool) *Desk

WithHeadless installs the answer a desk with nobody at it gives. Nil — the default — is the ordinary desk: it asks, and the job waits.

type Estimate

type Estimate struct {
	Leaves  int
	PerLeaf float64
	Dollars float64
}

Estimate is the honest arithmetic behind the question: how many steps, and what a step has cost on this machine. Both halves are measurements. When there is no measurement there is no estimate and no question — a forecast the model made up would be worse than the silence it replaced.

func EstimateJob

func EstimateJob(graph *store.Store, measured *profile.Profile, root string) (Estimate, bool)

EstimateJob prices a spliced subtree. The unit cost is the median of what a run has actually cost here, preferring the executor's own profile records (which know the shape of the work) and falling back to the journal's own median (which knows this machine). A job with no measured history anywhere returns nothing at all.

Jump to

Keyboard shortcuts

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