Documentation
¶
Overview ¶
Package activity is the port through which what people do in an interface is recorded (docs/adr/0034), so their work can be judged the way agents' calls are (docs/EVALUATING_PEOPLE.md): where a task goes wrong, where it waits, where it takes more than it needs. An act is recorded by its shape (the kind, the record, the step, the field's path, the action, its outcome and how long it took), never by what was written: no text a person typed, no name and no figure reaches a trace. An adapter keeps the acts; "off", the default, keeps none.
Index ¶
- Constants
- Variables
- func Budget() (map[string]int, error)
- func CheckBatch(session, iface string) error
- func FlowKinds(flows map[string]Flow) []string
- func Flows() (map[string]Flow, error)
- func IsOff(r Recorder) bool
- func Paths(flows map[string]Flow) (map[string]int, error)
- func PathsJSON(paths map[string]int) []byte
- func PeriodOf(period string, at time.Time, build string) string
- type Bar
- type Cause
- type Check
- type Criterion
- type Event
- type Flow
- type FlowField
- type LeadTime
- type Off
- type Options
- type Query
- type Reader
- type Recorder
- type Report
- type Series
- type StepStats
- type Stock
- type Task
- type TaskBrief
- type TaskStats
Constants ¶
const ( Server = "server" // the engine decided it, for any interface Interface = "interface" // only the interface saw it )
Sources of an act.
const ( OK = "ok" Refused = "refused" // the engine said no and why Failed = "failed" // the request could not be answered )
Outcomes of an act.
const ( DraftSave = "draft.save" // a draft kept, in a change set or the working copy DraftDiscard = "draft.discard" // a draft thrown away VersionSave = "version.save" // Save as version, ok or refused CheckLeave = "check.leave" // a check left open, with a reason ChangeSetStart = "changeset.start" // a change set opened ChangeSetSubmit = "changeset.submit" // a change set sent for review ChangeSetAccept = "changeset.accept" // a change set rolled in, ok or refused ChangeSetClose = "changeset.close" // a change set closed without rolling in ChangeSetReopen = "changeset.reopen" // a closed change set opened again )
Names of the acts the server records on a person's behalf.
const ( ScreenShow = "screen.show" // a screen drawn; Millis until its content, Sign whether a wait showed ScreenDeadEnd = "screen.deadend" // a screen with nothing to do: an empty state or an error with no action FlowOpen = "flow.open" // a flow opened on a record; Target new or existing StepEnter = "step.enter" // a step of a flow entered StepBack = "step.back" // a step left backwards FieldSet = "field.set" // a field's answer given (on change, never per key) GuideOpen = "guide.open" // a field's guide or examples opened PickerOpen = "picker.open" // a menu, popover or picker opened PickerClose = "picker.close" // closed; Target chosen or none Press = "press" // a press; Target action or none; Millis until the next frame Request = "request" // a request to the server; Millis, Outcome, Sign FindOpen = "find.open" // the search opened FindPick = "find.pick" // a record picked from it FindClose = "find.close" // closed with nothing picked ChangeSetSwitch = "changeset.switch" // another change set made the one worked in )
Names of the acts only an interface sees.
const ( Define = "define" // a record taken through its flow to a version Change = "change" // a record that had a version, saved again Review = "review" // a change set from opened to rolled in or closed Find = "find" // a record searched for and picked )
Task types.
const ( Finished = "finished" GivenUp = "given-up" Open = "open" // still being worked on when the trace ends )
Task statuses.
const ( PressBudget = 100 * time.Millisecond RequestBudget = time.Second // RepeatWithin is how close three presses on one thing must be to // count as pressing again because nothing seemed to happen. RepeatWithin = time.Second )
The answers' budgets, from DESIGN_RULES.md ("The interface answers").
const ( ValueAdding = "value-adding" // an answer kept, a version saved Necessary = "necessary" // moving through what the task needs Waste = "waste" // anything in the eight wastes )
Value classes of an act, as a value stream counts them.
const ( Day = "day" Week = "week" Build = "build" )
Periods a reading can be taken over.
Variables ¶
var NotMeasured = []string{
"defects: a version undone",
"overproduction: a record defined twice",
"overproduction: a record left alone",
"non-used knowledge: typed again",
"non-used knowledge: a reference made by hand",
"extra processing: a diff with noise",
"extra processing: a review of nothing",
}
NotMeasured are the document's criteria this analysis does not count yet, said in the report so a reader never takes a missing figure for a clean one.
Functions ¶
func Budget ¶
Budget is the committed budget of each task's shortest path, by "type/Kind": what Paths may not exceed without the budget changing in the same change, and what cartograph ux reads extra interactions against.
func CheckBatch ¶
CheckBatch says why a batch's session or interface is refused, or nil: both are tokens, never a name.
Types ¶
type Bar ¶
type Bar struct {
Type string `json:"type"`
Kind string `json:"kind,omitempty"`
// MaxDefects is the most defects the task may meet: 0 means it must
// pass first time. Absent, defects are not judged.
MaxDefects *int `json:"maxDefects,omitempty"`
// MaxSeconds is the longest the task may take, start to finish.
MaxSeconds float64 `json:"maxSeconds,omitempty"`
// MaxExtra is the most interactions the task may take, as a multiple
// of its shortest path (paths.json).
MaxExtra float64 `json:"maxExtra,omitempty"`
// MaxSlowPresses is the largest share of presses answered after
// 100 ms.
MaxSlowPresses *float64 `json:"maxSlowPresses,omitempty"`
// MaxDeadClicks is the most presses on nothing.
MaxDeadClicks *int `json:"maxDeadClicks,omitempty"`
}
Bar is what a run must meet. Type and Kind name the task; the rest are limits, each checked only when set.
type Cause ¶
type Cause struct {
Kind string `json:"kind"`
Step string `json:"step,omitempty"`
Field string `json:"field"`
Count int `json:"count"`
}
Cause is one place defects fell: a field of a kind, in a step.
type Criterion ¶
type Criterion struct {
Waste string `json:"waste"`
Name string `json:"name"`
Count int `json:"count"`
Base int `json:"base"`
Rate float64 `json:"rate"`
Per string `json:"per"`
}
Criterion is one waste criterion's figure: Count of Base, as a Rate per the unit Per names.
type Event ¶
type Event struct {
At time.Time `json:"time"`
Name string `json:"event.name"`
Source string `json:"cartograph.source"`
// Session groups one person's acts in one window of an interface;
// server acts have none and are joined to them by person and record.
Session string `json:"session.id,omitempty"`
// Build is the server's version, so readings can be taken per build.
Build string `json:"service.version,omitempty"`
Person string `json:"cartograph.person,omitempty"`
Interface string `json:"cartograph.interface,omitempty"`
// Surface is the screen, as its route pattern, never its address
// with a record's name in it: goals/$id, not goals/feed-the-town.
Surface string `json:"cartograph.surface,omitempty"`
Kind string `json:"cartograph.kind,omitempty"`
Record string `json:"cartograph.record,omitempty"`
Step string `json:"cartograph.step,omitempty"`
Field string `json:"cartograph.field,omitempty"`
ChangeSet string `json:"cartograph.change_set,omitempty"`
// Target is what an act was on, from a short list: new, existing,
// action, none, chosen.
Target string `json:"cartograph.target,omitempty"`
Outcome string `json:"cartograph.outcome,omitempty"`
Millis int64 `json:"cartograph.duration.ms,omitempty"`
// Sign is whether a wait showed it was waiting: a skeleton or a count.
Sign bool `json:"cartograph.sign,omitempty"`
// Problems counts what a refusal said is wrong; Paths are the fields
// it named, list items as "-".
Problems int `json:"cartograph.problems,omitempty"`
Paths []string `json:"cartograph.problem.paths,omitempty"`
// Checks are the ids of the checks still open on a version as it was
// saved: what was left unmet, never what was written.
Checks []string `json:"cartograph.checks.open,omitempty"`
}
Event is one act. Its names follow OpenTelemetry's general attributes where there is one (event.name, session.id, service.version); Cartograph's own are under cartograph.*.
func NewInterfaceAct ¶
NewInterfaceAct is the one way an interface's act enters the trace: it comes from the interface, and every field holds a shape, or it is refused with the reason. An act that could carry what a person wrote cannot be made.
type Flow ¶
type Flow struct {
Kind string
Steps []string
// StepOf is the step that asks each field, by its pointer.
StepOf map[string]string
// Fields is every field the flow asks, in order, with its step and
// whether it is a list a person adds items to.
Fields []FlowField
}
Flow is what the analysis needs of a kind's flow: its steps in order, which step asks each field, and its opportunities.
func (Flow) Opportunities ¶
Opportunities is how many places a Define or Change task on this kind can go wrong: each field the flow asks, and the decision to save it as a version. The same in every interface and every run, so defects per million compare across kinds.
type LeadTime ¶
type LeadTime struct {
Name string `json:"name"`
Count int `json:"count"`
Median float64 `json:"medianSeconds"`
P95 float64 `json:"p95Seconds"`
Average float64 `json:"averageSeconds"`
}
LeadTime is how long work waited, in seconds.
type Options ¶
type Options struct {
// Idle is how long a task may go untouched, before the trace ends,
// and still count as open rather than given up. An hour when zero.
Idle time.Duration
// Budget is each task's shortest path, by "type/Kind" (see Paths).
Budget map[string]int
}
Options tune the analysis.
type Query ¶
Query says which acts to read: those from From (inclusive) to To (exclusive), either open when zero, and one person's when Person is set.
type Reader ¶
Reader reads acts back for analysis, in the order they happened. It is the port every place a trace is kept answers, so the analysis never knows where that is.
type Recorder ¶
type Recorder interface {
Record(e Event)
}
Recorder keeps acts. Record never fails the act it records.
type Report ¶
type Report struct {
Acts int `json:"acts"`
From time.Time `json:"from"`
To time.Time `json:"to"`
// The whole: defects per million opportunities over Define and
// Change tasks closed (finished or given up), and its sigma level.
Opportunities int `json:"opportunities"`
Defects int `json:"defects"`
DPMO float64 `json:"dpmo"`
Sigma float64 `json:"sigma"`
FirstPassYield float64 `json:"firstPassYield"`
Completion float64 `json:"completion"`
// ValueAddedRatio is the share of acts in tasks that changed the
// record and were kept.
ValueAddedRatio float64 `json:"valueAddedRatio"`
Value map[string]int `json:"value"`
Tasks []TaskStats `json:"tasks"`
Steps []StepStats `json:"steps,omitempty"`
Waste []Criterion `json:"waste"`
// CrossCutting are the figures for what bears on several sections at
// once (risks, stances): raised where it bears, and placed when saved.
CrossCutting []Criterion `json:"crossCutting"`
LeadTimes []LeadTime `json:"leadTimes,omitempty"`
Inventory []Stock `json:"inventory"`
Pareto []Cause `json:"pareto,omitempty"`
// NotMeasured are the criteria the document names that this build
// does not count yet.
NotMeasured []string `json:"notMeasured"`
// Rebuilt are the tasks, for whoever reads further.
Rebuilt []Task `json:"-"`
}
Report is the analysis of a set of acts.
type Series ¶
type Series struct {
Name string `json:"name"`
Counts []int `json:"counts"`
Chart spc.Chart `json:"chart"`
// Split is the first period the limits were worked out from, when
// the readings were split at a release.
Split string `json:"split,omitempty"`
}
Series is one figure read once a period, with each reading's count (the tasks or presses it was worked out from) and its XmR chart.
func Readings ¶
Readings takes one reading per period of each figure that can be charted, and charts each series as an individuals and moving range chart (internal/spc). A task falls in the period it ended in; an act in the period it happened in. Periods are in the order they first appear, which for days and weeks is time order and for builds is the order they were served in. With split, the limits are worked out from that period on: a changed interface is a new process.
type StepStats ¶
type StepStats struct {
Kind string `json:"kind"`
Step string `json:"step"`
Tasks int `json:"tasks"`
Passed int `json:"passed"`
Yield float64 `json:"yield"`
}
StepStats is one step of a flow: how many tasks passed it first time, with no field it asks refused and no step back out of it.
type Stock ¶
type Stock struct {
Name string `json:"name"`
Count int `json:"count"`
MedianAgeSecs float64 `json:"medianAgeSeconds"`
}
Stock is work in progress at the end of the trace: how many, and how old in the median.
type Task ¶
type Task struct {
Type string `json:"type"`
Status string `json:"status"`
Person string `json:"person,omitempty"`
Session string `json:"session,omitempty"`
Kind string `json:"kind,omitempty"`
Record string `json:"record,omitempty"`
ChangeSet string `json:"changeSet,omitempty"`
Start time.Time `json:"start"`
End time.Time `json:"end"`
// Opportunities are the flow's fields and the decision to save.
Opportunities int `json:"opportunities,omitempty"`
// Defects are the problems refused versions named, and checks left
// open.
Defects int `json:"defects"`
// Left are the checks left open, counted in Defects too.
Left int `json:"left,omitempty"`
// Refused are the fields refused versions named, with their steps.
Refused []Cause `json:"refused,omitempty"`
// Interactions are the presses and answers given while it was open.
Interactions int `json:"interactions"`
Screens int `json:"screens"`
Switches int `json:"switches"`
Backs int `json:"backs"`
Reworked int `json:"reworked"`
Hunting int `json:"hunting"`
Drafts int `json:"drafts"`
// OpenAtVersion are the checks left open on the version that
// finished it.
OpenAtVersion []string `json:"openAtVersion,omitempty"`
// Build is the server build its last act was recorded on.
Build string `json:"build,omitempty"`
// Submitted is when a change set was sent for review.
Submitted time.Time `json:"submitted,omitzero"`
// contains filtered or unexported fields
}
Task is one piece of a person's work rebuilt from the trace.
type TaskBrief ¶
type TaskBrief struct {
// Name says what is judged.
Name string `json:"name"`
// Brief is what the person is told, word for word in every run.
Brief string `json:"brief"`
// Seed is a vault copied into each run's fresh vault before it is
// served, for a task that starts from records; empty starts empty.
Seed string `json:"seed,omitempty"`
// Runs is how many passing runs in a row close it: three when zero.
Runs int `json:"runs,omitempty"`
Bar Bar `json:"bar"`
}
TaskBrief is a task as data, kept beside the evaluation directory: what is asked, what finished means, and the bar a run must meet.
func ParseTaskBrief ¶
ParseTaskBrief reads a task from its JSON. Where the JSON comes from (a file beside an evaluation directory) is the caller's business: the domain reads no files.
type TaskStats ¶
type TaskStats struct {
Type string `json:"type"`
Kind string `json:"kind,omitempty"`
Started int `json:"started"`
Finished int `json:"finished"`
GivenUp int `json:"givenUp"`
Open int `json:"open"`
Completion float64 `json:"completion"`
FirstPassYield float64 `json:"firstPassYield"`
// RolledThroughputYield is the product of each step's yield along the
// kind's flow; Define and Change only.
RolledThroughputYield float64 `json:"rolledThroughputYield,omitempty"`
Opportunities int `json:"opportunities,omitempty"`
Defects int `json:"defects"`
DPMO float64 `json:"dpmo"`
Sigma float64 `json:"sigma"`
MedianSeconds float64 `json:"medianSeconds"`
P95Seconds float64 `json:"p95Seconds"`
MedianInteractions float64 `json:"medianInteractions"`
// ShortestPath is the budget's fewest interactions for the task, when
// a budget was given; Extra the median ratio of interactions to it.
ShortestPath int `json:"shortestPath,omitempty"`
Extra float64 `json:"extra,omitempty"`
}
TaskStats is one task type on one kind.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package conformance holds every place a people's trace is kept to the same promises: what is recorded is read back whole, in the order it happened, and a query keeps to its window and its person.
|
Package conformance holds every place a people's trace is kept to the same promises: what is recorded is read back whole, in the order it happened, and a query keeps to its window and its person. |
|
Package jsonl keeps people's acts as JSON lines appended to a file, one act a line, for any tool that reads JSON lines (and for cartograph ux) to analyse.
|
Package jsonl keeps people's acts as JSON lines appended to a file, one act a line, for any tool that reads JSON lines (and for cartograph ux) to analyse. |
|
Package memory keeps people's acts in the process, for tests and for a single process that analyses what it just recorded.
|
Package memory keeps people's acts in the process, for tests and for a single process that analyses what it just recorded. |
|
Package postgres keeps the people's trace in Postgres (docs/adr/0034), so every replica of a stateless deployment appends to one place and none keeps a file of its own.
|
Package postgres keeps the people's trace in Postgres (docs/adr/0034), so every replica of a stateless deployment appends to one place and none keeps a file of its own. |