tools

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: 15 Imported by: 0

Documentation

Overview

Package tools is abcd's explain-then-install mode (itd-63): the curated registry of the external tools abcd knows, the plain-language explanation a verb gives when it finds one missing, and the one place a confirmed install step is run.

It is a MODE other verbs call, never a surface of its own (the product thinker's decision 3, 2026-09-21): a verb that finds a tool missing asks Explain for what to say and, where it offers the install, hands Install a Confirm function its front door supplies. The package has no transport knowledge — it never reads a terminal and never writes to stdout — so the CLI asks on the terminal, the plugin page asks through the host's question tool, and this code is the same under both (criterion 5).

The trust boundary is Install. What it runs is fixed data in this file, compiled into the binary: an argv per platform, never composed from a flag, a repository file or an environment value, never a shell string. It runs only after the caller's Confirm returns yes, never in CI, and never a program that resolves inside the repository it was asked from. See install.go.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Known

func Known(name string) bool

Known reports whether the registry holds an entry for name.

func Missing

func Missing(cause error, name string, capability Capability) error

Missing wraps cause with the explanation for name as capability uses it.

func Names

func Names() []string

Names returns the registered tool names, sorted.

func WithinTree added in v0.12.0

func WithinTree(p, resolved, guard string) bool

WithinTree reports whether the program at p, which resolves to resolved after symlinks, lies inside the tree at guard, judged lexically and after symlink resolution on both sides. It is the one in-checkout judgement for a program: the installer refuses to run what it holds, and ahoy's presence check does not count it as installed. Both p and guard are absolute; the caller has already resolved p.

Types

type Answer

type Answer struct {
	Yes bool
	Why string
}

Answer is a caller's reply to the install question: yes or no, and in words how the reply was reached (typed at a terminal, named with a flag, no terminal to ask at), which the result repeats so a no is never silent.

type Capability

type Capability string

Capability names what a verb is doing when it finds a tool missing. The same tool is optional for one capability and required for another, so an explanation is always for a (tool, capability) pair.

const (
	// TranscriptScan is the secret scan of captured session transcripts in a
	// repository that has NOT armed gitleaks: the native scanner covers it.
	TranscriptScan Capability = "transcript-scan"
	// TranscriptScanArmed is the same scan in a repository that armed gitleaks
	// in .abcd/config/gitleaks.json: without the binary a release refuses,
	// while the history store still stores the transcript on the native
	// scanner and names the gap in its receipt (the 2026-09-25 ruling on
	// iss-2608291814575788).
	TranscriptScanArmed Capability = "transcript-scan-armed"
	// GitHubSettings is every verb that reads or changes the repository's
	// settings on GitHub (ahoy remote, site setup), which abcd does only
	// through gh.
	GitHubSettings Capability = "github-settings"
)

type Confirm

type Confirm func(Explanation) Answer

Confirm asks the person whether to run the install the explanation shows. The front door supplies it; a nil Confirm is a no.

type Explanation

type Explanation struct {
	Tool           string      `json:"tool"`
	Known          bool        `json:"known"`
	Capability     Capability  `json:"capability"`
	CapabilityName string      `json:"capability_name,omitempty"`
	Requirement    Requirement `json:"requirement,omitempty"`
	What           string      `json:"what,omitempty"`
	Homepage       string      `json:"homepage,omitempty"`
	Does           string      `json:"does,omitempty"`
	WithoutIt      string      `json:"without_it,omitempty"`
	NativeDefault  string      `json:"native_default,omitempty"`
	OnDecline      string      `json:"on_decline,omitempty"`
	StepManager    string      `json:"step_manager,omitempty"`
	// Step is the exact argv Install would run on this platform; empty when
	// the registry names none (an unknown tool, or a platform without a step).
	Step    []string `json:"step,omitempty"`
	Effects string   `json:"effects,omitempty"`
	Verify  []string `json:"verify,omitempty"`
	// RegistryGap is set for a tool the registry does not know: the gap is
	// abcd's own, and this names the capture that records it.
	RegistryGap string `json:"registry_gap,omitempty"`
}

Explanation is what a verb says when it finds a tool missing (criterion 1): the tool, whether it is optional or required for this capability, what works without it, what it would do, and the exact install step, all from the registry. It is structured so each front door renders it its own way (the plugin page reads it from a verb's --json); Lines is the plain-text rendering every front door shares.

func Explain

func Explain(name string, capability Capability) Explanation

Explain renders the explanation for name as capability uses it, on the running platform.

func (Explanation) Lines

func (e Explanation) Lines() []string

Lines is the plain-text explanation, one line per part, the first naming the tool and whether it is optional or required.

func (Explanation) StepText

func (e Explanation) StepText() string

StepText is the install step as a person would type it, or the reason there is none.

type Installer

type Installer struct {
	// LookPath resolves a bare program name on the operator's PATH.
	LookPath func(string) (string, error)
	// Run executes an argv whose argv[0] is already resolved, without a shell.
	Run func(context.Context, []string) ([]byte, error)
	// Getenv reads the environment (CI detection).
	Getenv func(string) string
	// GOOS selects the platform's step.
	GOOS string
	// Guard is the directory a resolved program must lie outside: the
	// repository the verb was run from. A PATH entry pointing into it is
	// repository content, which is trusted to choose nothing that runs.
	Guard string
}

Installer runs confirmed install steps. Every process-touching seam is a field so the whole decision path is exercised in tests with no package manager; Default is the production wiring.

func Default

func Default(guard string) *Installer

Default is the production installer for a verb run from guard (its repository root, or its working directory outside one).

func (*Installer) Install

func (in *Installer) Install(name string, capability Capability, confirm Confirm) Result

Install is the trust boundary. In order, and each refusal runs nothing:

  1. An unknown tool is refused: nothing is composed from a name.
  2. A platform without a step is refused.
  3. CI never installs, and is not asked.
  4. The caller's Confirm must return yes; nil is a no.
  5. The step's program must resolve on PATH to an absolute path outside the guarded tree, lexically and after symlinks.

The step then runs as an argv (no shell), with stdin closed, in its own process group, bounded in time (runArgv names the one limit of that bound's kill); the verify command follows under the same rules.

type MissingError

type MissingError struct {
	Cause       error
	Explanation Explanation
}

MissingError is a verb's refusal for a missing tool with the registry's explanation appended: the refusal stands exactly as it was (its cause stays reachable through errors.Is), and only its message grows to say what the tool is, whether this capability needs it, and the exact install step.

func (*MissingError) Error

func (m *MissingError) Error() string

func (*MissingError) Unwrap

func (m *MissingError) Unwrap() error

type Requirement

type Requirement string

Requirement is whether a capability needs a tool or merely works better with it (adr-22: most dependencies are optional adapters over a native default).

const (
	// Optional: the capability runs on its native default without the tool.
	Optional Requirement = "optional"
	// Required: the capability cannot run without the tool.
	Required Requirement = "required"
)

type Result

type Result struct {
	Tool string `json:"tool"`
	// Ran reports that the install step was executed.
	Ran bool `json:"ran"`
	// Argv is the step as run (argv[0] resolved), when Ran.
	Argv []string `json:"argv,omitempty"`
	// Installed reports that the step exited zero.
	Installed bool `json:"installed"`
	// Verified reports that the verify command exited zero afterwards.
	Verified bool `json:"verified"`
	// Declined reports that nobody said yes (a no, no confirmation, CI).
	Declined bool `json:"declined"`
	// Why is the reason nothing ran, or what failed.
	Why string `json:"why,omitempty"`
	// Output is the bounded tail of the step's output on a failure, or the
	// verify command's first line on success.
	Output string `json:"output,omitempty"`
	// OnDecline is the capability's standing after a no or a failure.
	OnDecline string `json:"on_decline,omitempty"`
	// contains filtered or unexported fields
}

Result reports one Install: what it ran and whether it worked, or why it ran nothing and what the capability continues on (criterion 2).

func Install

func Install(name string, capability Capability, confirm Confirm, guard string) Result

Install explains name as capability uses it, asks confirm, and on a yes runs the registry's step for this platform and then its verify command. It is the package-level spelling of Default(guard).Install.

func (Result) Summary

func (r Result) Summary() string

Summary is the one line a verb reports for the result. Every path that installed nothing ends with the capability's standing ("continuing on the native secret scanner"), so a no is loud rather than silent (spec scope 4).

type Step

type Step struct {
	Manager string
	Argv    []string
}

Step is one platform's install step: the package manager it uses, by name, and the exact argv run. Argv[0] is a bare program name resolved on PATH at run time; the rest are literal arguments.

type Tool

type Tool struct {
	Name     string
	What     string // what the tool is, plainly
	Homepage string // where to read what it is
	Uses     map[Capability]Use
	Install  map[string]Step // keyed by runtime.GOOS
	// Effects is what the install does on the machine and over the network, and
	// what it does not.
	Effects string
	// Verify is the argv that proves the tool runs once installed.
	Verify []string
}

Tool is one registry entry.

type Use

type Use struct {
	// Capability is the capability's human name.
	Capability string
	// Requirement is optional or required, for this capability.
	Requirement Requirement
	// Does is what abcd uses the tool for here.
	Does string
	// WithoutIt is what works without the tool (for an optional use, the
	// native default; for a required one, what fails and the way back).
	WithoutIt string
	// NativeDefault is what the capability continues on after a no; empty when
	// there is none.
	NativeDefault string
	// OnDecline is the loud line's tail after a no or a failed install:
	// "continuing on <native default>" for an optional use, the standing
	// refusal for a required one.
	OnDecline string
}

Use is what one capability does with a tool, in the words a person reads.

Jump to

Keyboard shortcuts

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