launch

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package launch is abcd's transport-agnostic launch engine: it assembles the release bundle under a default-deny taxonomy, runs the native secret+PII scan, checks manifest lockstep, and previews newest-per-line retention — all as a dry-run that renders decisions without writing an artefact or touching the network. It performs no printing and no os.Exit, so it is fully testable and reusable across surfaces.

The load-bearing invariant (adr-18/adr-28): the .abcd/** namespace and every other denied namespace can NEVER enter the bundle. This is a STRUCTURAL deny, not an allowlist toggle — no include pattern can promote a denied path.

Index

Constants

This section is empty.

Variables

View Source
var DenyNamespaces = map[string]struct{}{
	".git": {}, ".abcd": {}, ".flow": {}, ".work": {}, ".specstory": {}, "memory": {},
}

DenyNamespaces are namespace names that never ship. The structural deny (adr-18) binds EVERY path component case-insensitively (see pathContainsDeniedSegment), not just the first segment: a denied name nested under an included tree, or spelled in a different case, is denied all the same (GHSA-g2v7-wfmv-v28r, #335). NOT overridable by any allowlist. Mirrors launch_resolve DENY_NAMESPACES.

View Source
var ErrPayloadDrift = errors.New("the rendered payload failed the public lockstep check")

ErrPayloadDrift reports that the rendered payload failed the public lockstep check. It is its own error because it means the render itself is wrong (a pinned location was missed), not that the caller's input was.

View Source
var ErrPayloadScanRefused = errors.New("the payload failed the secret/PII scan gate")

ErrPayloadScanRefused reports that the payload the render would materialise carries a secret/PII hard-fail, an unscannable coverage gap, or was scanned by an unavailable scanner — the fail-closed secret/PII gate the materialising path must pass before any write (gh-328). It is the render's twin of the ship gate's scan refusal: DryRun runs the scan advisory-only and Ship (the gated path) has no production caller, so the live `launch ship --payload-dir` render was the sole materialising door that never invoked the scanner.

View Source
var ErrPayloadUninstallable = errors.New("the rendered payload failed the installability smoke")

ErrPayloadUninstallable reports that the rendered payload declares a surface it does not carry. It is distinct from ErrPayloadDrift because the fault is the payload's CONTENTS, not the version stamp: the manifests agree perfectly and the plugin still would not install.

View Source
var ErrShipBlocked = errors.New("ship blocked by a launch gate")

ErrShipBlocked is returned when any gate hard-fails.

Functions

func BumpTier

func BumpTier(prev, next Semver) string

BumpTier names the SemVer component that moved from prev to next: "major", "minor", "patch", or "" when the two cores are equal.

It reads the actual version delta rather than mapping an impact, because the mapping is not fixed: pre-1.0, changelog.DeriveNext turns a breaking impact into a MINOR bump and an additive one into a PATCH. A tier derived from the impact would therefore mislabel every pre-1.0 release in the published manifest, while the delta is true at any point on the 0.x/1.x boundary.

func CoreGreater

func CoreGreater(a, b Semver) bool

CoreGreater reports whether a is strictly newer than b by core version. It is exported because release ordering is decided in more than one place — the retention plan here and the tag anchor the changelog derivation resolves — and a second hand-rolled field comparison would be a second, silently divergent definition of "newer".

func IsStrictSemver

func IsStrictSemver(value string) bool

IsStrictSemver reports whether value is a strict SemVer 2.0.0 string.

func LoadIncludes

func LoadIncludes(repoRoot string) ([]string, error)

LoadIncludes reads .abcd/config/launch-payload.json, hand-validates its shape (no schema dependency — see §1.1), and returns the normalised, de-duplicated include patterns. A missing/malformed config, or an absolute / ".." / denied-rooted include, is a PreflightError.

Types

type Bundle

type Bundle struct {
	Included []IncludedFile `json:"files"`
	Excluded []ExcludedFile `json:"excluded"`
	Rejected []RejectedFile `json:"rejected"`
	Warnings []string       `json:"warnings"`
}

Bundle is the classified resolution outcome.

func ResolveBundle

func ResolveBundle(repoRoot string, includes []string) (Bundle, error)

ResolveBundle walks repoRoot, matches candidates against includes, and classifies each into Included / Excluded / Rejected under the ordered algorithm. includes==nil loads the committed config via LoadIncludes (a preflight fault is returned as an error).

func (Bundle) HasViolation

func (b Bundle) HasViolation() bool

HasViolation reports whether any rejected[] entry exists. ship hard-fails on true; dry-run reports it but still exits 0.

type ChangelogEntry

type ChangelogEntry struct {
	// Tier is the SemVer component the cut moved: patch, minor or major.
	Tier string
	// Reason is the human sentence explaining the bump, e.g. "additive itd-67 shipped".
	Reason string
	// Date is the release date; only its calendar day is recorded.
	Date time.Time
	// SourceSHA is the commit the release was cut from.
	SourceSHA string
}

ChangelogEntry is the marketplace plugin entry's per-release record (adr-20 R3), minus its version.

The version is deliberately NOT a field: the render writes the one derived version into this entry and into both version pointers from a single input, so the entry cannot disagree with the manifest it travels in. Everything here is supplied by the caller — a core that read the clock or the git HEAD itself would put two unpinnable inputs inside a durable release artefact.

type CitationPreflight

type CitationPreflight struct {
	// Unreadable, when non-empty, means the measurement could not be taken at
	// all — a docs-lint config that arms the rule but does not parse, or a
	// baseline the loader refuses. It is a separate state from "not armed"
	// because reporting a broken gate as an absent one is a false statement
	// about a real requirement, and it refuses.
	Unreadable string
	// Present reports whether a baseline exists at all.
	Present bool
	// Cited, Recorded and Missing describe coverage.
	Cited    int
	Recorded int
	Missing  int
	// Broken counts citations recorded as dead.
	Broken int
	// Approaching counts entries inside the nag window before the blocking
	// threshold; Overdue counts those past it.
	Approaching int
	Overdue     int
	// ApproachingURLs and OverdueURLs name them, so a nag and a refusal tell an
	// operator WHICH links to deal with rather than only how many.
	ApproachingURLs []string
	OverdueURLs     []string
}

CitationPreflight is the citation baseline's state, measured by the caller. A nil pointer means the repo has not armed the citation gate, and the gate reports itself as not run rather than silently passing.

type ClosureFn

type ClosureFn func(repoRoot string) (map[string]struct{}, error)

ClosureFn returns the runtime-closure set (repo-relative POSIX paths) for the scripts/ include — the AST-reachable set the shipped plugin ships, never the whole dev tree. Since the Go payload layout is not yet settled, the default reads a pinned closure list from config rather than re-deriving via Python AST (spec §1 step 10 — the single open dependency). A nil map means no closure scoping is applied (scripts/ then behaves like any other include).

type DryRunReport

type DryRunReport struct {
	Version       string             `json:"version"`
	Bundle        Bundle             `json:"bundle"`
	Scan          scanner.ScanResult `json:"scan"`
	Lockstep      LockstepResult     `json:"lockstep"`
	Retention     RetentionPlan      `json:"retention"`
	Smoke         SmokeReport        `json:"smoke"`
	Gates         []GateSummary      `json:"gates"`
	WouldPublish  bool               `json:"would_publish"` // always false in dry-run
	WouldRefuseOn []string           `json:"would_refuse_on,omitempty"`
}

DryRunReport is the full dry-run preview. No artefact is written.

func DryRun

func DryRun(req DryRunRequest) (DryRunReport, error)

DryRun assembles the bundle, scans it, checks lockstep and previews retention, then reports what a real ship WOULD refuse on. It ALWAYS returns exit-0 semantics: an error is returned only for a preflight fault (bad include config) that makes a report impossible — never on a finding.

type DryRunRequest

type DryRunRequest struct {
	RepoRoot string
	// Version is the release version this launch would publish, SUPPLIED by the
	// caller. adr-19 leaves no version key in the source tree, so there is
	// nothing here for the core to read: the version is a fact about the release
	// cut, and the front door that knows the cut injects it. Empty is honest —
	// it means the caller could not name one, and retention says so.
	Version      string
	ExistingTags []Semver // injected; nil → default `git tag -l v*` provider
	// Citations is the citation baseline's state, MEASURED by the caller.
	// Grading it needs internal/core/lint, which imports this package for its
	// semver — so the front door that holds both hands the result in as data
	// rather than this package reaching back. Nil means the repo has not armed
	// the citation gate.
	Citations *CitationPreflight
	// Receipts is the semantic-pass receipts' state, MEASURED by the caller for
	// the same reason as Citations: it needs a git rev-parse and a directory
	// read, and this package does not reach back through the front door. Nil
	// means the measurement was not taken, which the gate reports as such rather
	// than as an absence of receipts.
	Receipts *ReceiptPreflight
}

DryRunRequest is the input to a dry-run.

type ExcludedFile

type ExcludedFile struct {
	LogicalPath string         `json:"logical_path"`
	Reason      ExcludedReason `json:"reason"`
}

ExcludedFile is a benign exclusion.

type ExcludedReason

type ExcludedReason string

ExcludedReason is why a candidate was benignly excluded (never fails a ship).

const (
	ExcludedGitignored      ExcludedReason = "gitignored"
	ExcludedUnmatchedGlob   ExcludedReason = "unmatched_glob"
	ExcludedDeniedNamespace ExcludedReason = "denied_namespace"
)

type GateSummary

type GateSummary struct {
	Name   string `json:"name"`
	Status string `json:"status"` // "ran" | "not_implemented" | "host-run"
	Detail string `json:"detail"`
}

GateSummary records one gate's dry-run disposition.

type IncludedFile

type IncludedFile struct {
	LogicalPath  string `json:"logical_path"`
	ResolvedPath string `json:"resolved_path"`
	GitMode      string `json:"git_mode"` // "100644" | "100755"
}

IncludedFile is a resolved payload file. Paths are repo-relative POSIX; ResolvedPath is the absolute on-disk (dereferenced) path.

type InstallSurface

type InstallSurface struct {
	PluginName  string             `json:"plugin_name"`
	Marketplace []MarketplaceEntry `json:"marketplace"`
	Entries     []SurfaceEntry     `json:"entries"`
}

InstallSurface is everything a payload declares about what installing it would register.

func ResolveInstallSurface

func ResolveInstallSurface(tree PayloadTree) (InstallSurface, error)

ResolveInstallSurface returns everything tree declares: the plugin's name, the marketplace listings with their sources resolved, and the union of the convention and manifest surface entries.

It returns an error only when a manifest cannot be read or parsed at all — a payload whose declarations cannot even be enumerated. Everything else, including a declaration pointing at nothing, is DATA: it becomes an entry, and judging it is the assertion tier's job, not resolution's.

type LockstepResult

type LockstepResult struct {
	Tree       LockstepTree `json:"tree"`
	OK         bool         `json:"ok"`
	Drifts     []string     `json:"drifts,omitempty"`
	Unreadable bool         `json:"unreadable,omitempty"`
	Detail     string       `json:"detail,omitempty"`
	ExitCode   int          `json:"exit_code"` // 0 ok, 1 drift, 2 unreadable
}

LockstepResult is the outcome of a manifest lockstep check.

func CheckLockstep

func CheckLockstep(tree LockstepTree, repoRoot, versionLocationPath string) LockstepResult

CheckLockstep proves the two manifests plus the version-location contract describe one release consistently.

PUBLIC: the primary version (manifest_path + json_pointer from version-location.json) must be a present, non-null strict-SemVer string and every pinned secondary must AGREE. DEV: those keys must all be ABSENT. present-null is distinguished from absent via an explicit sentinel. A blocked:true contract, or any unreadable pinned input, yields exit 2.

type LockstepTree

type LockstepTree string

LockstepTree is the polarity the lockstep check runs under.

const (
	// TreeDev requires the version keys ABSENT (adr-19 dev-stays-unversioned).
	TreeDev LockstepTree = "dev"
	// TreePublic requires the primary present and every secondary to agree.
	TreePublic LockstepTree = "public"
)

type MarketplaceEntry

type MarketplaceEntry struct {
	Name       string     `json:"name"`
	Source     string     `json:"source,omitempty"`
	SourceKind SourceKind `json:"source_kind"`
	// Root is the payload-relative plugin root a local source resolves to; the
	// empty string is the payload root itself (adr-28: the single repo is its
	// own marketplace, so the canonical source is "./").
	Root string `json:"root"`
}

MarketplaceEntry is one plugin listing in the marketplace manifest.

type PayloadPrecheck

type PayloadPrecheck struct {
	// Root is the symlink-resolved source tree.
	Root string
	// Dest is the symlink-resolved staging directory. Nothing is created here.
	Dest string
	// VersionLocationPath is the absolute path to the adr-19 contract.
	VersionLocationPath string
	// PrimaryPath and PrimaryPointer are the pinned primary version location the
	// contract selected, repo-relative and RFC-6901.
	PrimaryPath, PrimaryPointer string
	// Bundle is the payload resolution the render would write from.
	Bundle Bundle
	// Smoke is the light installability tier over the RESOLVED bundle — the same
	// assertions the render makes over its written output, made early enough to
	// refuse before any durable write.
	Smoke SmokeReport
}

PayloadPrecheck is everything a render refuses on WITHOUT knowing the version: the resolved locations, the payload the render would write, and the light installability verdict over it.

It exists as a named result because the ship verb writes a durable release record (the dated CHANGELOG heading) before it has a version to stamp, and a render that refuses after that write leaves a release in flight that can never be retried. Separating the version-free half lets the caller prove the render will be ACCEPTED before it writes anything.

func PrecheckPayload

func PrecheckPayload(repoRoot, dest string) (PayloadPrecheck, error)

PrecheckPayload resolves the release payload and runs every refusal a render makes that does not depend on the version.

It performs ZERO writes — not even the destination directory — so a caller may run it speculatively and a refused cut leaves the filesystem exactly as it found it. RenderPayload runs it as its own first step, so the two can never disagree about what is refusable.

It refuses when: dest overlaps repoRoot or is already populated; the version-location contract is unreadable or blocked (adr-19 — a blocked decision has no schema-valid place to write); the bundle carries a violation; either manifest is not in the payload at all; or the payload declares a surface it does not carry.

type PayloadRenderRequest

type PayloadRenderRequest struct {
	// RepoRoot is the source tree the payload is cut from. It is read only.
	RepoRoot string
	// Dest is the staging directory the payload is written to. It must live
	// OUTSIDE RepoRoot and be empty or absent.
	Dest string
	// Version is the derived release version, strict SemVer with no leading "v".
	// It is an input rather than something read back out of the tree — the tree
	// has no version to read, which is the whole point of adr-19.
	Version string
	// Entry is the marketplace changelog record for this release.
	Entry ChangelogEntry
}

PayloadRenderRequest is the input to RenderPayload.

type PayloadRenderResult

type PayloadRenderResult struct {
	// Dest is the staging directory the payload was written to.
	Dest string `json:"dest"`
	// Version is the version stamped at every pinned location.
	Version string `json:"version"`
	// Bundle is the resolution the payload was written from, so a caller can
	// render the same file classification a dry-run would.
	Bundle Bundle `json:"bundle"`
	// Files counts the payload files written.
	Files int `json:"files"`
	// Manifests names the manifests that were version-stamped, repo-relative.
	Manifests []string `json:"manifests"`
	// Lockstep is the public check over the rendered payload — the proof that
	// what was written is internally consistent.
	Lockstep LockstepResult `json:"lockstep"`
	// Smoke is the light installability check over the rendered payload — the
	// proof that what was written would actually install.
	Smoke SmokeReport `json:"smoke"`
}

PayloadRenderResult is a completed render.

func RenderPayload

func RenderPayload(req PayloadRenderRequest) (PayloadRenderResult, error)

RenderPayload writes the release payload to req.Dest with the derived version stamped into its manifests, and proves the result with CheckLockstep.

It resolves the payload through the SAME ResolveBundle/LoadIncludes machinery the dry-run and ship gates use, so there is exactly one notion of "what ships"; the render adds only the version stamp on the way out. It never touches the source tree: every write lands under Dest.

Everything refusable that does not need the version is delegated to PrecheckPayload, so a caller may run those refusals FIRST; on top of them this refuses when the version is not strict SemVer or the changelog entry is incomplete.

type PayloadTree

type PayloadTree interface {
	// Has reports whether a FILE exists at rel, a payload-relative,
	// slash-separated path. A path escaping the payload is never present.
	Has(rel string) bool
	// Read returns the bytes at rel, guarded against oversized input.
	Read(rel string) ([]byte, error)
	// List returns every file at or beneath the directory dirRel, sorted, as
	// payload-relative slash paths. An empty result means "no such directory".
	List(dirRel string) []string
}

PayloadTree is the read side of a payload: the only thing surface resolution needs from "the thing that would ship". Two implementations satisfy it — a resolved bundle (nothing materialised) and a rendered directory — so the same resolver serves the light tier and itd-66's deep tier unchanged.

func NewBundleTree

func NewBundleTree(b Bundle) PayloadTree

NewBundleTree views a resolved bundle as a payload tree, so the light tier can assert against WHAT WOULD SHIP without writing anything. A file present in the working tree but excluded from the payload is absent here — which is exactly the bug this gate catches.

func NewDirTree

func NewDirTree(root string) PayloadTree

NewDirTree views a rendered payload directory as a payload tree.

type PreflightError

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

PreflightError is a payload-preflight config fault: a missing/malformed include config, or an absolute / ".." / denied-rooted include. The caller writes NO manifest and reports the diagnostic (dry-run returns it as its only error case).

func (*PreflightError) Error

func (e *PreflightError) Error() string

type ReceiptPreflight

type ReceiptPreflight struct {
	// Unreadable, when non-empty, means the measurement could not be taken —
	// the candidate commit would not resolve, or the receipts directory could
	// not be read. A broken measurement is a distinct state from "none found",
	// because reporting the first as the second is a false statement about a
	// real requirement.
	Unreadable string
	// Commit is the candidate commit the receipts would have to name. At preview
	// time this is the working tree's HEAD; the commit release.yml actually arms
	// against is derived from the merge (`<merge>^2^`), so this is indicative,
	// not authoritative — the detail text says so.
	Commit string
	// Recorded names the detectors that have a receipt for Commit, in the order
	// found. It counts receipts present, not receipts valid: validity (PROMOTE,
	// judge model, detector binding, manifest hash) is receipt_gate's to judge,
	// and duplicating that verdict here would be the second trust root this row
	// exists to avoid.
	Recorded []string
}

ReceiptPreflight is the state of the semantic-pass receipts, measured by the caller. A nil pointer means the measurement was not taken, and the gate says so rather than reporting an absence it never looked for.

type RejectedFile

type RejectedFile struct {
	LogicalPath string            `json:"logical_path"`
	Reason      RejectedReason    `json:"reason"`
	Details     map[string]string `json:"details,omitempty"`
}

RejectedFile is a violation.

type RejectedReason

type RejectedReason string

RejectedReason is why a candidate was rejected (any entry fails a ship).

const (
	RejectedDeny            RejectedReason = "deny"
	RejectedSymlinkEscape   RejectedReason = "symlink_escape"
	RejectedSymlinkCycle    RejectedReason = "symlink_cycle"
	RejectedHardlinkDenied  RejectedReason = "hardlink_denied"
	RejectedHardlinkOffrepo RejectedReason = "hardlink_offrepo"
	RejectedDuplicate       RejectedReason = "duplicate"
	RejectedControlChar     RejectedReason = "control_char"
	RejectedPlatformBinary  RejectedReason = "platform_binary"
	RejectedMissingLiteral  RejectedReason = "missing_literal"
	RejectedFSError         RejectedReason = "fs_error"
)

type RetentionPlan

type RetentionPlan struct {
	Published     string   `json:"published"`
	Line          string   `json:"line"`
	Kept          []string `json:"kept"`
	Pruned        []string `json:"pruned"`
	Refused       bool     `json:"refused"`
	RefusalReason string   `json:"refusal_reason,omitempty"`
}

RetentionPlan is the newest-per-line prune preview for a release cut.

func ComputeRetention

func ComputeRetention(published Semver, existing []Semver) RetentionPlan

ComputeRetention decides newest-per-line retention (brief §3). It is pure and deletes nothing — it renders the prune decision only.

Rules:

  • Each MAJOR.MINOR line keeps only its newest (max-Patch) release.
  • The just-published release is NEVER pruned.
  • If ANY existing release is strictly NEWER than published, refuse and prune nothing (an out-of-order ship the operator must resolve manually).
  • Comparison is core (Major, Minor, Patch) only. Tag string = "v"+version.

type Semver

type Semver struct {
	Major, Minor, Patch int
	Prerelease, Build   string
}

Semver is a parsed strict SemVer 2.0.0 version.

func GitExistingTags

func GitExistingTags(repoRoot string) ([]Semver, error)

GitExistingTags is the default provider for the existing-release list: it runs `git tag --list v*` under repoRoot and parses the strict-SemVer core of each tag. Non-SemVer tags AND prerelease/build tags are ignored — retention decides newest-per-line over RELEASES (core versions), and Tag()/String() render the core only, so admitting a "v1.2.3-rc1" would surface a phantom "v1.2.3" in the plan and collapse it against the real "v1.2.3". It is best-effort — an error yields no tags.

func ParseSemver

func ParseSemver(value string) (Semver, error)

ParseSemver parses a strict SemVer string into its components. It returns an error for any non-conforming input (the boundary validator).

func (Semver) Line

func (s Semver) Line() string

Line is the MAJOR.MINOR retention line a version belongs to.

func (Semver) String

func (s Semver) String() string

String renders the core MAJOR.MINOR.PATCH (retention compares core only).

func (Semver) Tag

func (s Semver) Tag() string

Tag renders the v-prefixed git tag for the version core.

type ShipReport

type ShipReport struct {
	Version      string             `json:"version"`
	Bundle       Bundle             `json:"bundle"`
	Scan         scanner.ScanResult `json:"scan"`
	Lockstep     LockstepResult     `json:"lockstep"`
	Retention    RetentionPlan      `json:"retention"`
	Smoke        SmokeReport        `json:"smoke"`
	Blocked      bool               `json:"blocked"`
	BlockReasons []string           `json:"block_reasons,omitempty"`
	WouldPublish bool               `json:"would_publish"` // true iff all gates pass
}

ShipReport is the outcome of a ship run. It stops at WouldPublish before any network/publish (no GitHub Release, SLSA, tag push, or retention execution).

func Ship

func Ship(req ShipRequest) (ShipReport, error)

Ship runs the SAME gates as DryRun but HARD-FAILS: a scanner hard-fail, any bundle rejected[] entry, a lockstep drift/unreadable contract, or a retention refusal sets Blocked=true and returns ErrShipBlocked. If every gate passes it stops HERE and returns WouldPublish=true with NO network call — the real GitHub Release + SLSA + tag push + retention prune are a later phase. --allow-dirty must NOT bypass lockstep (adr-20); it is carried but never consulted by the lockstep gate.

type ShipRequest

type ShipRequest struct {
	RepoRoot string
	// Version is the release version, supplied by the caller for the reason
	// DryRunRequest.Version states: adr-19 leaves nothing in the tree to read.
	Version      string
	AllowDirty   bool
	ExistingTags []Semver
}

ShipRequest is the input to a ship run.

type SmokeFinding

type SmokeFinding struct {
	Kind   string `json:"kind"`
	Path   string `json:"path,omitempty"`
	Detail string `json:"detail"`
}

SmokeFinding is one reason the payload would not install.

type SmokeReport

type SmokeReport struct {
	Tier    SmokeTier      `json:"tier"`
	OK      bool           `json:"ok"`
	Surface InstallSurface `json:"surface"`
	// Checked counts the assertions actually made, so a pass over a payload that
	// declared nothing is visibly vacuous rather than reassuring.
	Checked  int            `json:"checked"`
	Findings []SmokeFinding `json:"findings,omitempty"`
}

SmokeReport is one installability check.

func SmokeLight

func SmokeLight(tree PayloadTree) SmokeReport

SmokeLight runs the light installability tier over a payload.

It never returns an error: an unreadable manifest is the most serious FINDING it can make, and reporting it as a finding keeps the gate's output shape the same whether the payload is perfect or unparseable — the dry-run preview depends on always having a report to render.

type SmokeTier

type SmokeTier string

SmokeTier names how deep an installability check went, so a report never implies more assurance than it earned.

const SmokeTierLight SmokeTier = "light"

SmokeTierLight is manifest-parse + source-resolve + declared-path-exists.

type SourceKind

type SourceKind string

SourceKind classifies a marketplace entry's source.

const (
	// SourceLocal — a path inside the payload; resolvable offline.
	SourceLocal SourceKind = "local"
	// SourceExternal — a remote or non-path source; resolving it needs the
	// network, so no offline gate asserts against it.
	SourceExternal SourceKind = "external"
	// SourceMissing — the entry declares no source at all.
	SourceMissing SourceKind = "missing"
)

type SurfaceEntry

type SurfaceEntry struct {
	Kind        SurfaceKind        `json:"kind"`
	Path        string             `json:"path"`
	Origin      SurfaceOrigin      `json:"origin"`
	Requirement SurfaceRequirement `json:"requirement"`
	// DeclaredAs is the raw declaration this entry was expanded from, when it
	// differs from Path (a directory declaration, a hook command string).
	DeclaredAs string `json:"declared_as,omitempty"`
	// Reason explains a requirement other than RequirePayload.
	Reason string `json:"reason,omitempty"`
}

SurfaceEntry is one declared piece of the installable surface.

type SurfaceKind

type SurfaceKind string

SurfaceKind is one register of the installable surface.

const (
	SurfaceCommand SurfaceKind = "command"
	SurfaceAgent   SurfaceKind = "agent"
	SurfaceSkill   SurfaceKind = "skill"
	SurfaceHook    SurfaceKind = "hook"
)

type SurfaceOrigin

type SurfaceOrigin string

SurfaceOrigin records HOW an entry came to be declared. It is carried on every entry so a stricter tier can weigh the registers differently without re-resolving them.

const (
	// OriginConvention — found by auto-discovery under a well-known directory.
	OriginConvention SurfaceOrigin = "convention"
	// OriginManifest — named by an explicit plugin.json key.
	OriginManifest SurfaceOrigin = "manifest"
	// OriginHookCommand — referenced by a hook's command string.
	OriginHookCommand SurfaceOrigin = "hook-command"
)

type SurfaceRequirement

type SurfaceRequirement string

SurfaceRequirement says who is expected to supply an entry's path.

const (
	// RequirePayload — the payload must carry it; absence is a failed install.
	RequirePayload SurfaceRequirement = "payload"
	// RequireInstalled — the install supplies it, so the payload never carries
	// it and its absence proves nothing.
	RequireInstalled SurfaceRequirement = "installed"
)

Directories

Path Synopsis
Package scaffold renders and writes the changelog-driven release machinery — release.yml, auto-release.yml, and the adr-37 runbook — into a managed repo that lacks it (itd-93, spc-14).
Package scaffold renders and writes the changelog-driven release machinery — release.yml, auto-release.yml, and the adr-37 runbook — into a managed repo that lacks it (itd-93, spc-14).

Jump to

Keyboard shortcuts

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