bootstrap

package
v0.4.0 Latest Latest
Warning

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

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

Documentation

Overview

Package bootstrap runs the bootstrap loop: the fixed-point pass that runs inside one batch job and turns any repository into an archive an earlier csf binary runs. It is the "ask C" slice of the laser_bootstrap program.

The loop owns the fixed point and the keep/refuse decision. Its stages are function values registered in data (CS-6): the NewLoop constructor builds a pipeline of Entry values, and a sibling slice plugs a stage in by appending one Entry — mine, induce, lean, shell and the jev batch land that way without the loop changing. Each iteration measures the repository, runs the stages, measures again, and keeps the change only when it grew the seed without a refusal; otherwise the tree is rolled back and the refusal logged. It repeats until the reading stops changing, the cap is reached, or every chief row holds, then emits the archive.

The loop has no network, no database and no subprocess: it reads and writes one directory tree, so it runs locally (no AWS) against a fixture repository, which is how its acceptance is proven.

Index

Constants

View Source
const (
	// FormatVersion is the manifest's version. A reader that does not know a
	// version refuses the archive rather than guess.
	FormatVersion = 1
	// ManifestName is the manifest's member name. It is the archive's first
	// member, so a reader learns the format before it reads any repository
	// byte.
	ManifestName = "manifest.json"
	// EntrypointName is the executable a runner runs, relative to the
	// extracted archive root. It is a manifest field, so a later format may
	// move it without a reader change.
	EntrypointName = "bin/csf"
)

The archive format is frozen at version 1. A later bootstrapper release may add members to an archive, but it never changes what a version 1 manifest field means, so a csf binary from any earlier release runs a newer archive. The brief calls this the boot sector: frozen forever.

View Source
const ArchiveName = "bootstrap.tar.gz"

ArchiveName is the archive the loop emits beside the repository.

View Source
const DefaultCap = 32

DefaultCap bounds the loop's iterations when none is set.

Variables

View Source
var Platforms = []string{"linux_amd64"}

Platforms are the platforms a version 1 archive may run on, as <goos>_<goarch>. A reader refuses an archive it cannot run.

Functions

func Measure

func Measure(ctx context.Context, repo string) (prod.Reading, error)

Measure reads a repository into a prod.Reading by the marker convention the merge quality gate and this loop share: a top-level directory's count for a chief row is the marker file named after the row's id inside it, and the files are every regular file under the repository, by slash path. The per-directory checker that computes the counts from the tree is not landed, so a directory with no markers reads clean — the loop and the gate agree because they read the convention through this one function.

func NoFix

func NoFix(_ context.Context, _ *Run) error

NoFix is a Fixer that proposes no change. The mine and induce slices supply the repairing one; until they land, a loop built with NoFix measures a repository and emits its archive without altering the tree.

func PayloadDigest

func PayloadDigest(entries []DigestEntry) string

PayloadDigest is the frozen framing of the payload digest: each entry contributes its name, its kind and its content length, then its content, in the slice's order. The emitter sorts members by name, so the digest is a function of the tree alone and a rewrite of the manifest cannot be forged against altered content.

func TarGz

func TarGz(ctx context.Context, request EmitRequest) (string, error)

TarGz writes the repository at request.Repo as a deterministic tar.gz archive at the destination beside its parent directory, and returns that path. The archive's first member is the version 1 manifest; the rest is the repository's tree, one member per regular file and directory, sorted by name, with fixed ownership, timestamps and gzip header. So two runs over the same tree, revision and timestamp are byte-identical, and the manifest's sha256 refuses an archive altered after it was written. The archive is built in memory and written whole through pkg/atomicfile, so it never leaves a half-written archive.

Types

type DigestEntry

type DigestEntry struct {
	Name      string
	Directory bool
	Content   []byte
}

DigestEntry is one archive member as the payload digest sees it: its slash name, whether it is a directory, and its content (a directory's is empty). The emitter and the runner both build these, so the digest each computes is one function of the same bytes.

type EmitRequest

type EmitRequest struct {
	Repo           string
	Destination    string
	SourceRevision string
	Created        string
}

EmitRequest is the emitter's input: the repository to archive, the destination beside its parent directory (the loop's archive name), and the two manifest facts the tree does not carry — the source revision and the created timestamp. Same tree and same two facts is the same bytes.

type Emitter

type Emitter func(ctx context.Context, request EmitRequest) (string, error)

Emitter writes a repository into a deterministic archive and returns its path.

type Entry

type Entry struct {
	ID    StageID
	Stage Stage
}

Entry is one pipeline row: a stage under its id, in run order.

type Fixer

type Fixer func(ctx context.Context, run *Run) error

Fixer applies one candidate change to the working tree. It returns an error only when it cannot apply the change at all; a change the gates later refuse is a nil error and a rollback, not an error.

type Loop

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

Loop runs the bootstrap stages to a fixed point.

func NewLoop

func NewLoop(measurer Measurer, fixer Fixer) *Loop

NewLoop builds a loop from a measurer and a fixer, with its default pipeline, archive name and cap; the With* methods replace them.

func (*Loop) Run

func (l *Loop) Run(ctx context.Context, repo string) (Result, error)

Run drives the loop to a fixed point and returns the emitted archive's path.

func (*Loop) WithArchive

func (l *Loop) WithArchive(archive string) *Loop

WithArchive replaces the archive destination, relative to the repository's parent directory.

func (*Loop) WithCap

func (l *Loop) WithCap(cap int) *Loop

WithCap replaces the iteration cap.

func (*Loop) WithCreated

func (l *Loop) WithCreated(created string) *Loop

WithCreated sets the timestamp the emitted archive's manifest records, as RFC 3339, or empty for none. It is part of the archive's bytes, so a caller that wants a reproducible archive fixes it.

func (*Loop) WithEmitter

func (l *Loop) WithEmitter(emitter Emitter) *Loop

WithEmitter replaces the archive emitter.

func (*Loop) WithFixer

func (l *Loop) WithFixer(fixer Fixer) *Loop

WithFixer replaces the fixer stage's function.

func (*Loop) WithLogger

func (l *Loop) WithLogger(logger *slog.Logger) *Loop

WithLogger replaces the refusal logger.

func (*Loop) WithMeasurer

func (l *Loop) WithMeasurer(measurer Measurer) *Loop

WithMeasurer replaces the measurer.

func (*Loop) WithPipeline

func (l *Loop) WithPipeline(pipeline []Entry) *Loop

WithPipeline replaces the loop's pipeline of stages.

func (*Loop) WithSourceRevision

func (l *Loop) WithSourceRevision(revision string) *Loop

WithSourceRevision sets the revision the emitted archive's manifest records.

type Manifest

type Manifest struct {
	FormatVersion  int      `json:"format_version"`
	SourceRevision string   `json:"source_revision"`
	Created        string   `json:"created"`
	SHA256         string   `json:"sha256"`
	Entrypoint     string   `json:"entrypoint"`
	Platform       []string `json:"platform"`
}

Manifest is the frozen version 1 archive manifest. Every field is fixed by the format; a later version adds fields, never reinterprets these. SHA256 is the digest of the archive's payload — every member but the manifest — so a reader refuses a tampered archive before it extracts a byte.

type Measurer

type Measurer func(ctx context.Context, repo string) (prod.Reading, error)

Measurer measures a repository into a prod.Reading. A real caller wires the checker commands; a fixture injects a scripted measurer.

type Result

type Result struct {
	Done       bool
	Iterations int
	Archive    string
	Initial    prod.Reading
	Final      prod.Reading
	Kept       []prod.Reading
	Refusals   []prod.Refusal
}

Result reports how the loop finished. Kept holds the readings of the kept changes in order — every consecutive pair grew the seed — and Refusals holds every refusal, so every_kept_change_raised_seed and refusals_logged are both read off one run.

type Run

type Run struct {
	Repo      string
	Before    prod.Reading
	After     prod.Reading
	Refusals  []prod.Refusal
	Kept      bool
	Iteration int
}

Run is one iteration's state, handed to every stage.

type Stage

type Stage func(ctx context.Context, run *Run) error

Stage is one function value of the pipeline, mutating the working tree or the run's state. The loop measures before and after the stages and owns the keep/refuse decision, so a stage never decides whether to keep.

type StageID

type StageID string

StageID names one stage of the loop, spelled as the brief names it.

const (
	// StageWork turns csfc refusals into work items.
	StageWork StageID = "csfc_refusals_to_work"
	// StageFix applies mechanical, jev-picked and coder-session fixes.
	StageFix StageID = "fix"
	// StageScore measures the score after the fixes.
	StageScore StageID = "build_test_score"
	// StageKeep decides keep_if(seed_grows, nothing_breaks).
	StageKeep StageID = "keep_if"
)

Jump to

Keyboard shortcuts

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