question

package
v0.13.3 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package question holds what a question abcd puts to a person may contain: the field limits, written once (Limits, Default), the field view every front door finally shows (Fields), and the limits check (CheckLimits) that refuses a badly built question naming the part, the value, and the limit (spc-2610030944505997; itd-2610030810350727, itd-201).

Nothing else in the tree states a limit. The question check in the guard hook, the GRILL rule text and the interview pages read Default, so changing a limit here changes every statement of it (itd-2610030810350727 criterion A7).

The package is a library: it returns values and never prints. It measures text through internal/textwidth, a pure leaf, and imports nothing that does terminal I/O.

Index

Constants

View Source
const (
	KindParagraph = "paragraph"
	KindList      = "list"
)

The kinds a material block takes.

View Source
const EmDashListItemPattern = "^\\s*(?:[-*+]|[0-9]+\\.)\\s.*\u2014"

EmDashListItemPattern is rule 12's pattern: a line opening a list item that carries an em dash. It is the docs-lint token punctuation/em-dash-in-list-item, whose definition lives in ahoy's docs-lint seed; a test in internal/core/ahoy holds the two equal.

View Source
const KnowledgeFloorPage = ".abcd/development/brief/glossary/interview/knowledge-floor.md"

KnowledgeFloorPage is where the knowledge floor is stated in full: a glossary entry in abcd's development record, which every install of the plugin carries under its plugin root (spc-2610030944505997, open question 4, decided (a)). The asking rules point at it in one line rather than restating it (itd-201 decision 5).

View Source
const ProductRole = "Product"

ProductRole is the chip role word that names the product thinker. Where no mode names the addressee, a chip carrying it stands in for the mode (rule 9).

View Source
const RecommendedRemedy = "" /* 275-byte string literal not displayed */

RecommendedRemedy is rule 8's remedy. It names the cause, so the agent does not loop (itd-201 criterion R6).

View Source
const TypedRowLabel = "Type my own answer"

TypedRowLabel is the label of the one option a front door adds to a question with a typed part when the host's question tool takes fewer listed options than the question has (a typed part and decide later alone): it points at the host's free-text row and answers nothing itself, so an interview that receives it asks the question again.

View Source
const TypedTextPrefix = "Or type in the row below:"

TypedTextPrefix opens the line of the question text that says what the typed part takes.

Variables

View Source
var Default = Limits{
	HeaderColumns:    12,
	ChipRoles:        []string{ProductRole, "Tech", "Setup"},
	QuestionsPerCall: [2]int{1, 4},
	OptionsPerQ:      [2]int{2, 4},
	LabelWords:       5,
	MeaningSentences: 2,
	LaterLabels:      []string{"Decide later", "None of these"},
	Columns:          80,
	Rows:             24,

	HostTextColumns:   76,
	HostChromeRows:    8,
	HostOptionColumns: 74,
	NowPrefix:         "Now:",
	ChangeLaterPrefix: "Change later:",
	NotApplicable:     "not applicable",
}

Default is the one statement of every limit.

Functions

func AskingRecall

func AskingRecall() []string

AskingRecall returns the GRILL domain's recall terms, a fresh copy each call.

func AskingRules

func AskingRules(l Limits) []string

AskingRules returns the asking rules every abcd interview follows, the text the GRILL rule domain carries in every repository abcd manages (spc-2610030944505997, "GRILL generated from one Go source"). Every limit it states is filled from l, numbers written as words, so the text and the question check read one statement of each limit (itd-2610030810350727 criterion A7). The text names no record and no source-tree command: it reaches repositories that have neither (itd-201 decision 8).

The register rule, the ask-the-role-first rule and the mode rules open with "In abcd's own interviews": they hold for abcd's command pages, never for another tool's questions in a managed repository (itd-201 decision 10).

func ChipRole

func ChipRole(header string, l Limits) (string, bool)

ChipRole reads the role word from a header in the chip grammar, "<role> Q<n>" with an optional "/<total>", the role one of l.ChipRoles ("Product Q2", "Tech Q3", "Setup Q1/4"). It judges the grammar alone, not the width. A header in the grammar is abcd's: only abcd's interview pages are taught to write it.

func Matches

func Matches(filter string, o Option) bool

Matches is the narrowing rule (spc-2610030911534855, "The answer loop"): the typed text, matched case-insensitively as a substring of the option's label or of its value. Empty text matches every option. The plain-Terminal list narrows with it and so does guided connect's session (spc-2610031241482088), so a fragment narrows the same in both places.

Types

type Addressee

type Addressee struct {
	Person Person
	Verbs  []string
}

Addressee is the check's input about whom a question is for. Verbs is the binary's verb list, which the surface reads from its command tree and passes in, so the core holds no copy of it (rule 9).

type Ask

type Ask struct {
	Questions []Question `json:"questions"`
}

Ask is what one turn puts to the person: one question, or up to four parts of one thing shown as tabs (itd-2610030810350727 decision 10). It is the structured question both front doors use (spc-2610030911534855, "One question type, defined here first"): abcd draws it in a plain Terminal, and Fields maps it onto the host's question tool.

func Safe

func Safe(a Ask) Ask

Safe returns a copy of a with every part sanitised for the screen (spc-2610030911534855, "Sanitising before drawing"). Every string in a question is runtime-read: a runner wrote it, a record supplied it, or a model service listed it. Each single-line part (the id, the chip, the ask, every option's and list choice's value, label and meaning, Now, Change later and the typed part's prompt) passes termsafe.Sanitize, so a line break inside a label cannot forge a line; each material block passes termsafe.SanitizeBlock. An injected escape, a C1 control, a bidi override, a zero-width rune or a bare carriage return reaches the screen as a visible '?'. a itself is left unchanged. The drawing (internal/surface/cli/ask) and the AI-written interviews' check (internal/core/interview) both sanitise through it, so what is measured is what is drawn.

func (Ask) Fields

func (a Ask) Fields() Fields

Fields maps the Ask onto the field view the limits are checked on (spc-2610030944505997, "The field view"): the chip to the header; the material's blocks, then the Now: and Change later: lines, then the ask, to the question text; the options (a long list's choices) and then Later to the options; the typed part to the free-text row (Tab.Typed), its prompt said in the text just before the ask. A line the question does not carry is left out, so the limits check names the gap rather than the mapping inventing a value.

type Block

type Block struct {
	Kind  string   `json:"kind"` // KindParagraph or KindList
	Text  string   `json:"text,omitempty"`
	Items []string `json:"items,omitempty"`
}

Block is one piece of a question's material: a paragraph, or a list.

type Choice

type Choice struct {
	Label       string // a few words
	Description string // what choosing it means
	Preview     string // the host's side preview, which abcd's questions never carry (rule 14)
}

Choice is one option of a question, as the host shows it.

type Fields

type Fields struct {
	Tabs []Tab
}

Fields is the field view of one call to the host's question tool: one question, or up to four parts of one thing shown as tabs. It is what every front door finally shows, so the limits are checked on it. The guard hook decodes the host's tool input into it (the JSON key names are the host's, so the decoding lives in the surface); the companion's structured question type is mapped onto it by that type's own method.

type Finding

type Finding struct {
	Tab    int
	Part   string
	Rule   Rule
	Value  string
	Limit  string
	Remedy string
}

Finding is one broken rule: the question's ordinal (its tab, counted from one; zero is the call as a whole), the part, the rule, the offending value (sanitised and capped, as the mode store's echo is), the limit, and what to do about it.

func Check

func Check(a Ask) []Finding

Check is the structural check: every question has an id (unique within the Ask), a chip, an ask, a Later option with a value, and options, a list, or a typed part; every option and list choice has a value and a label; values are unique within a question, Later's included; no answer's meaning points at text above a question that carries no material (pointsAbove); an Ask holds as many questions as Default.QuestionsPerCall admits. It returns every finding at once, each naming the question (its tab, counted from one; zero is the Ask as a whole) and the part, and holds no limit of its own: how much each part may hold is CheckLimits's, run on the field view (Fields).

func CheckLimits

func CheckLimits(f Fields, l Limits, who Addressee) []Finding

CheckLimits holds a call's fields to l and returns every finding at once, so one refusal names every part to fix and the agent fixes them in one retry. It refuses and never rewrites: a rewritten question puts words in the agent's mouth that neither the agent nor the person chose. No finding means the question is admitted.

func (Finding) String

func (f Finding) String() string

String is the finding as one line of plain text.

type Limits

type Limits struct {
	HeaderColumns     int      // 12: the host's header chip
	ChipRoles         []string // "Product", "Tech", "Setup": the chip's first word
	QuestionsPerCall  [2]int   // 1..4: one question, or up to four tabs
	OptionsPerQ       [2]int   // 2..4, the decide-later option included
	LabelWords        int      // 5
	MeaningSentences  int      // 2: an option's description
	LaterLabels       []string // "Decide later", "None of these"
	Columns           int      // 80: the narrow window promised
	Rows              int      // 24: one question, or one tab, at Columns
	HostTextColumns   int      // 76: the question text's measure inside the host's frame at Columns
	HostChromeRows    int      // 8: rows the frame draws around a question, the chip included
	HostOptionColumns int      // 74: the measure of an option's label and description at Columns
	NowPrefix         string   // "Now:"
	ChangeLaterPrefix string   // "Change later:"
	NotApplicable     string   // "not applicable"
}

Limits is every bound a question's fields are held to. question.Default is the one value the check, the GRILL domain, and the interview pages read (itd-2610030810350727 decision 14, criterion A7).

type List

type List struct {
	Choices []Option `json:"choices"`
}

List is a choice among many (300 models): the question's Options stay empty and the choices live here; the Later option still applies.

type Option

type Option struct {
	Value   string `json:"value"`
	Label   string `json:"label"`
	Meaning string `json:"meaning"`
}

Option is one answer: the value recorded, a label of a few words, and what choosing it means, with its trade-off.

type Person

type Person int

Person is whom a question is addressed to, as the mode records it.

const (
	// Unnamed is no mode naming anyone: a repository abcd does not manage has
	// no mode store, and a managed mode parks on nobody. The chip's role word
	// then stands in, since the chip names whom the question is for.
	Unnamed Person = iota
	// ProductThinker is the mode naming the product thinker.
	ProductThinker
	// Facilitator is the mode naming the technical facilitator.
	Facilitator
)

type Question

type Question struct {
	ID          string   `json:"id"`                     // stable: a setup key, or the turn's ordinal
	Chip        string   `json:"chip"`                   // who it is for and which question: "Setup Q1"
	Material    []Block  `json:"material"`               // the thing being decided: paragraphs and lists
	Ask         string   `json:"ask"`                    // the one plain question
	Options     []Option `json:"options"`                // the substantive answers
	Later       Option   `json:"later"`                  // the way to decide later, always present
	Now         string   `json:"now,omitempty"`          // what holds now (itd-2610030810350727 decision 4)
	ChangeLater string   `json:"change_later,omitempty"` // how to change the answer later (decision 4)
	List        *List    `json:"list,omitempty"`         // the long-list variant
	// Typed is the prompt for a typed answer: a question with a typed part
	// takes any text as its answer besides its options (spc-2610031241482088,
	// "The typed part on the question type"). The host's question tool takes
	// it in its free-text row, so such a question carries no side preview,
	// which would remove that row; the Terminal draws it as one line after
	// the options. It counts as one option toward the limits' floor.
	Typed string `json:"typed,omitempty"`
}

Question is one question: the thing being decided first, then the one plain question, then the answers and the way to decide later.

type Rule

type Rule string

Rule names one of the limits check's rules (spc-2610030944505997, "The limits check"). Each is reported as its own finding.

const (
	RuleHeader            Rule = "header"               // 1: present, within HeaderColumns, in the chip grammar
	RuleQuestionsPerCall  Rule = "questions-per-call"   // 2: one to four; more than one is tabs
	RuleOptions           Rule = "options"              // 3: two to four, decide-later included
	RuleLabelWords        Rule = "label-words"          // 4: at most LabelWords words
	RuleMeaningSentences  Rule = "meaning-sentences"    // 5: a description present, at most MeaningSentences
	RuleDecideLater       Rule = "decide-later"         // 6: exactly one LaterLabels option, last
	RuleNoBold            Rule = "no-bold"              // 7: no ** or __ outside previews
	RuleNeverRecommended  Rule = "never-recommended"    // 8: no (Recommended), no star mark
	RuleRegister          Rule = "register"             // 9: the product thinker sees no handle or command
	RuleNowAndChangeLater Rule = "now-and-change-later" // 10: a Now: and a Change later: line, each with a value
	RuleThingFirst        Rule = "thing-first"          // 11: material first, the question last
	RuleEmDashListItem    Rule = "em-dash-in-list-item" // 12: no em dash in a list item
	RuleRows              Rule = "rows"                 // 13: within Rows at Columns
	RuleNoPreview         Rule = "no-preview"           // 14: no option carries a side preview
)

The rules, in the spec's order, rule 14 appended by the layout intent's decision 20.

const RuleStructure Rule = "structure"

RuleStructure names a structural finding: a part a question cannot be drawn, answered or recorded without. Check reports it; the limits are CheckLimits's.

type Tab

type Tab struct {
	Header  string   // the chip: whom the question is for and which it is
	Text    string   // the material, the Now: and Change later: lines, then the question
	Options []Choice // the answers, the decide-later option last
	// Typed is the prompt of the question's typed part, taken in the host's
	// free-text row: it is no option the host lists, and the limits count it
	// as one toward their floor. The host's own input carries none.
	Typed string
}

Tab is one question of a call: the four fields the host's question tool takes. A call with one question has one tab.

Jump to

Keyboard shortcuts

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