stresstest

package
v0.32.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Package stresstest provides the on-demand correctness stress harness's core scaffolding: building the binary under test, driving scenarios, and streaming a report of what happened. It is dev-only tooling invoked via cmd/stresstest — never installed alongside cmd/aiwf.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildBinary

func BuildBinary(ctx context.Context, moduleRoot, outDir string) (string, error)

BuildBinary compiles moduleRoot's ./cmd/aiwf into outDir/aiwf and returns its absolute path. outDir must itself be an absolute path — the caller (typically a fresh os.MkdirTemp/t.TempDir) is responsible for that, so the returned path never depends on resolving the process's current working directory. Matches this repo's own worktree-binary discipline (make diag-aiwf's precedent; CLAUDE.md "Worktree binary discipline"): a stress run builds a fresh binary from source at the start of every run and uses the returned path throughout — never whatever an "aiwf" PATH lookup would resolve, which could be stale or absent.

func BuildLockHolder

func BuildLockHolder(ctx context.Context, moduleRoot, outDir string) (string, error)

BuildLockHolder compiles moduleRoot's ./internal/stresstest/lockholder into outDir/lockholder and returns its absolute path. See BuildBinary for the outDir-must-be-absolute rationale, which applies identically here. M-0242/AC-1's scenario uses the returned binary to hold internal/repolock's lock from a real, independently killable OS process.

Types

type ArchiveDuringActiveScopeScenario

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

ArchiveDuringActiveScopeScenario implements Scenario.

func NewArchiveDuringActiveScopeScenario

func NewArchiveDuringActiveScopeScenario(aiwfBin string) *ArchiveDuringActiveScopeScenario

NewArchiveDuringActiveScopeScenario builds a scenario driving one epic/milestone pair through an authorize-then-archive sequence.

func (*ArchiveDuringActiveScopeScenario) Run

Run captures the child's pre-attempt scope state, attempts to promote the parent epic straight to done, then confirms G-0393's guard refused it: the epic's own status is unaffected and the child's scope is unaffected — there is no sweep to run anymore, because the invalid state this scenario used to construct at this exact step can no longer be reached.

func (*ArchiveDuringActiveScopeScenario) Setup

Setup creates an active epic with an in_progress milestone, opens an authorize scope on the milestone from an epic-shaped branch (the rung-pair preflight requires it), then merges that branch back into the base branch so the authorize commit — which touches no file, carrying only trailers — stays reachable from HEAD for every subsequent verb in this scenario. Skipping this merge would leave the authorize commit stranded on an unmerged sibling branch, making every trailer-grep-based lookup (aiwf show/history/authorize --pause) blind to it for a reason that has nothing to do with archiving — a confound ruled out empirically before writing this scenario.

func (*ArchiveDuringActiveScopeScenario) Verify

Verify returns every violation Run collected.

type ComposeResult

type ComposeResult struct {
	Events    []json.RawMessage
	Truncated bool
}

ComposeResult is the outcome of composing a raw-report JSONL file: every successfully-parsed event, in order, plus whether the file's final line was dropped as truncated.

func Compose

func Compose(path string) (ComposeResult, error)

Compose reads path (a raw-report JSONL file written by ReportWriter) and returns every well-formed event line. A malformed trailing line — the shape a kill -9 mid-write leaves behind, since ReportWriter's O_APPEND + one-Write()-per-record discipline (AC-2) guarantees only the last record can ever be partial — is dropped silently and reported via Truncated, never treated as a whole-report failure: the same "errors are findings, not parse failures" posture aiwf check holds toward the entity tree. A malformed line anywhere else in the file is a different kind of corruption than an abort and surfaces as an error.

type ConcurrentIDAllocationScenario

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

ConcurrentIDAllocationScenario implements Scenario.

func NewConcurrentIDAllocationScenario

func NewConcurrentIDAllocationScenario(aiwfBin string, kind entity.Kind, n int, _ int64) *ConcurrentIDAllocationScenario

NewConcurrentIDAllocationScenario builds a scenario that races n concurrent `aiwf add <kind>` subprocesses against one disposable repo. seed matches RunRepeated's newScenario(seed int64) Scenario signature (M-0240/AC-5) but is otherwise unused — this scenario's race jitter comes from real OS goroutine/process scheduling, not seeded pseudo-randomness.

func (*ConcurrentIDAllocationScenario) Run

Run launches s.n `aiwf add` subprocesses concurrently, waits for all of them, then classifies the outcomes.

func (*ConcurrentIDAllocationScenario) Setup

Setup git-inits dir and sets a deterministic commit identity.

func (*ConcurrentIDAllocationScenario) Verify

Verify returns every violation Run collected.

type ConcurrentMilestoneRaceScenario

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

ConcurrentMilestoneRaceScenario implements Scenario.

func NewConcurrentMilestoneRaceScenario

func NewConcurrentMilestoneRaceScenario(aiwfBin string, n int, _ int64) *ConcurrentMilestoneRaceScenario

NewConcurrentMilestoneRaceScenario builds a scenario that races n concurrent actors — split roughly in half between `aiwf promote <milestone>/AC-1 met` and `aiwf cancel <milestone>` — against one shared, pre-seeded milestone carrying exactly one open AC. seed matches RunRepeated's newScenario(seed int64) Scenario signature but is otherwise unused — this scenario's race jitter comes from real OS goroutine/process scheduling, not seeded pseudo-randomness (same rationale as ConcurrentMoveScenario's own seed parameter).

func (*ConcurrentMilestoneRaceScenario) Run

Run launches s.n actors concurrently against s.milestoneID — the first s.n/2 (by launch index) running `aiwf promote <milestoneID>/AC-1 met`, the rest running `aiwf cancel <milestoneID>` — waits for all of them, decodes every actor's envelope, reads back the milestone's and its AC's post-race status, then confirms the resulting tree stays check-clean beyond baseline noise.

func (*ConcurrentMilestoneRaceScenario) Setup

Setup git-inits dir, creates one epic, one milestone under it (--tdd none, left at its default `draft` status), and exactly one AC on that milestone (left `open`) — the shared entity+AC pair every actor Run launches will later race promote/cancel against. Draft is a legal `aiwf cancel` source per the milestone FSM (internal/entity/transition.go), so the only thing standing between a cancel attempt and success is the open-AC guard this scenario exists to race.

func (*ConcurrentMilestoneRaceScenario) Verify

Verify returns every violation Run collected: AC-2's own legitimate-race-vs-violation oracle judging s.outcomes (classified in Run via classifyMilestoneRaceOutcomes), alongside AC-1's check-clean baseline — both signals stay live side by side.

type ConcurrentMoveScenario

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

ConcurrentMoveScenario implements Scenario.

func NewConcurrentMoveScenario

func NewConcurrentMoveScenario(aiwfBin string, n int, _ int64) *ConcurrentMoveScenario

NewConcurrentMoveScenario builds a scenario that races n concurrent `aiwf move` subprocesses, each relocating one of n milestones from a shared source epic to a shared target epic. seed matches RunRepeated's newScenario(seed int64) Scenario signature but is otherwise unused — this scenario's race jitter comes from real OS goroutine/process scheduling, not seeded pseudo-randomness (same rationale as ConcurrentIDAllocationScenario's own seed parameter).

func (*ConcurrentMoveScenario) Run

func (s *ConcurrentMoveScenario) Run(dir string) error

Run launches s.n `aiwf move` subprocesses concurrently — one per seeded milestone, all targeting s.targetEpic — waits for all of them, then classifies the outcomes.

func (*ConcurrentMoveScenario) Setup

func (s *ConcurrentMoveScenario) Setup(dir string) error

Setup git-inits dir, creates the source and target epics, and n milestones under the source epic — one per concurrent actor Run will later launch.

func (*ConcurrentMoveScenario) Verify

func (s *ConcurrentMoveScenario) Verify(_ string) []Violation

Verify returns every violation Run collected.

type ConcurrentWriterAtScaleScenario

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

ConcurrentWriterAtScaleScenario implements Scenario.

func NewConcurrentWriterAtScaleScenario

func NewConcurrentWriterAtScaleScenario(aiwfBin string, n int, _ int64) *ConcurrentWriterAtScaleScenario

NewConcurrentWriterAtScaleScenario builds a scenario driving n concurrent `aiwf cancel` subprocesses, each writing its diagnostic log line to one shared file. seed matches RunRepeated's newScenario(seed int64) Scenario signature (M-0240/AC-5) but is otherwise unused — this scenario's write-ordering jitter comes from real OS process scheduling, not seeded pseudo-randomness.

func (*ConcurrentWriterAtScaleScenario) Run

Run launches one `aiwf cancel` subprocess per pre-seeded gap, concurrently, all pointed at one shared diagnostic log file, then classifies the resulting file against every invocation's own reported run_id. An actor whose cancel loses the repo-lock race under contention (repolock.ErrBusy → ExitUsage) is retried until it completes (G-0424); every attempt — the lock-busy losses included — emits exactly one diagnostic line (EmitVerbOutcome's defer is registered before lock acquisition), so the run expects one clean line per attempt, whether the invocation ultimately succeeded or lost the lock and retried.

func (*ConcurrentWriterAtScaleScenario) Setup

Setup git-inits dir and pre-seeds n gap entities — one per actor Run will later cancel — capturing each allocated id from its own `aiwf add` envelope rather than assuming a fixed id-width format.

func (*ConcurrentWriterAtScaleScenario) Verify

Verify returns every violation Run collected.

type CrossWorktreeEditBodyRaceScenario

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

CrossWorktreeEditBodyRaceScenario implements Scenario.

func NewCrossWorktreeEditBodyRaceScenario

func NewCrossWorktreeEditBodyRaceScenario(aiwfBin string) *CrossWorktreeEditBodyRaceScenario

NewCrossWorktreeEditBodyRaceScenario builds a scenario that races two `aiwf edit-body` invocations against one pre-existing entity from sibling worktrees.

func (*CrossWorktreeEditBodyRaceScenario) Run

Run drives operator A's edit-body call against their own worktree (and, unless skipOperatorBEdit is set, operator B's too), then merges actor-b into actor-a's worktree and classifies however that merge resolves.

func (*CrossWorktreeEditBodyRaceScenario) Setup

Setup creates a main repo seeded with one gap entity, then adds two sibling worktrees (actor-a, actor-b) off that same seeded commit — dir/main, dir/wt-a, dir/wt-b.

func (*CrossWorktreeEditBodyRaceScenario) Verify

Verify returns every violation Run collected.

type CrossWorktreeIDRaceScenario

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

CrossWorktreeIDRaceScenario implements Scenario.

func NewCrossWorktreeIDRaceScenario

func NewCrossWorktreeIDRaceScenario(aiwfBin string, kind entity.Kind, _ int64) *CrossWorktreeIDRaceScenario

NewCrossWorktreeIDRaceScenario builds a scenario that races one `aiwf add <kind>` subprocess in each of two sibling worktrees. seed matches RunRepeated's newScenario(seed int64) Scenario signature (M-0240/AC-5) but is otherwise unused — this scenario's race jitter comes from real OS goroutine/process scheduling, not seeded pseudo-randomness.

func (*CrossWorktreeIDRaceScenario) Collided

func (s *CrossWorktreeIDRaceScenario) Collided() bool

Collided reports whether this scenario instance observed a real cross-worktree id collision. Exposed so a caller repeating this scenario (via RunRepeated) can assert that at least one attempt actually exercised the collision-resolution path, rather than a run where the race window was never hit passing vacuously.

func (*CrossWorktreeIDRaceScenario) Run

Run races one `aiwf add` in each sibling worktree, merges actor-b into actor-a's worktree to bring both into one view, and — only if the race actually produced a duplicate id — confirms `aiwf check` surfaces it and `aiwf reallocate` resolves it.

func (*CrossWorktreeIDRaceScenario) Setup

Setup creates a main repo with a seed commit, then adds two sibling worktrees (actor-a, actor-b) off it — dir/main, dir/wt-a, dir/wt-b.

func (*CrossWorktreeIDRaceScenario) Verify

Verify returns every violation Run collected.

type DiskFaultScenario

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

DiskFaultScenario implements Scenario.

func NewDiskFaultScenario

func NewDiskFaultScenario(aiwfBin string) *DiskFaultScenario

NewDiskFaultScenario builds a scenario driving aiwfBin (the real compiled aiwf binary) against a permission-denied fixture directory.

func (*DiskFaultScenario) Run

func (s *DiskFaultScenario) Run(dir string) error

Run revokes write permission on the seeded gap's parent directory, attempts a promote against it, restores permissions so cleanup can proceed regardless of outcome, and classifies the result.

func (*DiskFaultScenario) Setup

func (s *DiskFaultScenario) Setup(dir string) error

Setup git-inits dir and seeds one gap entity via a real `aiwf add`.

func (*DiskFaultScenario) Verify

func (s *DiskFaultScenario) Verify(_ string) []Violation

Verify returns the violations Run collected.

type ForceOverrideDurabilityScenario

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

ForceOverrideDurabilityScenario implements Scenario.

func NewForceOverrideDurabilityScenario

func NewForceOverrideDurabilityScenario(aiwfBin string) *ForceOverrideDurabilityScenario

NewForceOverrideDurabilityScenario builds a scenario driving both the ack-revocation-by-rebase and cherry-picked-force-carryover sequences against one disposable repo.

func (*ForceOverrideDurabilityScenario) Run

Run drives item 5 (ack-revocation-by-rebase) then item 6 (cherry-picked-force-carryover) against dir, and classifies the combined outcome.

func (*ForceOverrideDurabilityScenario) Setup

Setup creates two independent epics: one promoted to done (the item-5 target for a manual illegal-transition edit), and one carrying a draft milestone (the item-6 target for a force-promote), with two sibling branches cut off the point where that milestone is still draft.

func (*ForceOverrideDurabilityScenario) Verify

Verify returns every violation Run collected.

type HeadDriftScenario

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

HeadDriftScenario implements Scenario.

func NewHeadDriftScenario

func NewHeadDriftScenario(aiwfBin string) *HeadDriftScenario

NewHeadDriftScenario builds a scenario driving one epic activation through a simulated preflight-then-interloper-checkout sequence.

func (*HeadDriftScenario) Run

func (s *HeadDriftScenario) Run(dir string) error

Run simulates the incident: a preflight reads the current branch, a parallel session's checkout switches to a different one, and the activation promote then runs — landing wherever HEAD now points, not the branch the preflight observed.

func (*HeadDriftScenario) Setup

func (s *HeadDriftScenario) Setup(dir string) error

Setup creates one epic at its default (proposed) status — the entity a subsequent activation promote will target, mirroring the actual G-0269 incident's own `aiwf promote <epic> active` call.

func (*HeadDriftScenario) Verify

func (s *HeadDriftScenario) Verify(_ string) []Violation

Verify returns every violation Run collected.

type LockKillScenario

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

LockKillScenario implements Scenario.

func NewLockKillScenario

func NewLockKillScenario(lockHolderBin string) *LockKillScenario

NewLockKillScenario builds a scenario driving lockHolderBin (the built internal/stresstest/lockholder binary) as the lock-holding process to kill.

func (*LockKillScenario) Run

func (s *LockKillScenario) Run(dir string) error

Run launches the lockholder against dir, waits for its readiness signal, probes the lock state before and after killing it, and records classifyLockKillOutcome's verdict.

func (*LockKillScenario) Setup

func (s *LockKillScenario) Setup(dir string) error

Setup git-inits dir so the lockfile resolves to the real <dir>/.git/aiwf.lock path repolock documents, matching what a real aiwf invocation would use.

func (*LockKillScenario) Verify

func (s *LockKillScenario) Verify(_ string) []Violation

Verify returns the violations Run collected.

type MidWriteKillScenario

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

MidWriteKillScenario implements Scenario.

func NewMidWriteKillScenario

func NewMidWriteKillScenario(aiwfBin string) *MidWriteKillScenario

NewMidWriteKillScenario builds a scenario driving aiwfBin (the real compiled aiwf binary) against a large-bodied gap entity.

func (*MidWriteKillScenario) Run

func (s *MidWriteKillScenario) Run(dir string) error

Run promotes the control repo's gap to completion to learn the fully-written bytes, then kills the target repo's equivalent promote mid-write and classifies the result.

func (*MidWriteKillScenario) Setup

func (s *MidWriteKillScenario) Setup(dir string) error

Setup creates dir/control and dir/target as two independent git repos, each seeded with one identically-bodied gap entity.

func (*MidWriteKillScenario) Verify

func (s *MidWriteKillScenario) Verify(_ string) []Violation

Verify returns the violations Run collected.

type ParallelBranchReallocateScenario

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

ParallelBranchReallocateScenario implements Scenario.

func NewParallelBranchReallocateScenario

func NewParallelBranchReallocateScenario(aiwfBin string, kind entity.Kind) *ParallelBranchReallocateScenario

NewParallelBranchReallocateScenario builds a scenario driving one `aiwf add <kind>` per operator clone, then the merge/push/reallocate sequence between them.

func (*ParallelBranchReallocateScenario) Run

Run drives both operators' adds, the merge/push sequence to the point of collision, and the reallocate-based resolution.

func (*ParallelBranchReallocateScenario) Setup

Setup creates a bare origin repo and clones it into dir/operator-a and dir/operator-b.

func (*ParallelBranchReallocateScenario) Verify

Verify returns every violation Run collected.

type PromoteOnWrongBranchDetectionScenario

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

PromoteOnWrongBranchDetectionScenario implements Scenario.

func NewPromoteOnWrongBranchDetectionScenario

func NewPromoteOnWrongBranchDetectionScenario(aiwfBin string) *PromoteOnWrongBranchDetectionScenario

NewPromoteOnWrongBranchDetectionScenario builds a scenario driving one epic activation through the same interloping-checkout shape HeadDriftScenario uses, then checking whether `aiwf check` detects the misplacement once back on the original branch.

func (*PromoteOnWrongBranchDetectionScenario) Run

Run reproduces the incident (an interloping checkout onto an arbitrarily-named, non-ritual-shaped branch, then the activation promote lands there — same shape as the real G-0270 incident), then checks back out to the preflight branch and runs `aiwf check`, simulating the operator later inspecting from where they started, unaware of what happened on the interloper branch in between.

func (*PromoteOnWrongBranchDetectionScenario) Setup

Setup creates one epic at its default (proposed) status — the entity a subsequent activation promote will target.

func (*PromoteOnWrongBranchDetectionScenario) Verify

Verify returns every violation Run collected.

type ReachabilityIsolationScenario

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

ReachabilityIsolationScenario implements Scenario.

func NewReachabilityIsolationScenario

func NewReachabilityIsolationScenario(aiwfBin string, kind entity.Kind, _ int64) *ReachabilityIsolationScenario

NewReachabilityIsolationScenario builds a scenario confirming cross-worktree reachability isolation for one entity kind. seed matches RunRepeated's newScenario(seed int64) Scenario signature (M-0240/AC-5) but is unused — this scenario is deterministic, not a race (contrast AC-2/AC-3): a sequential commit in one worktree, observed from another, always reproduces the same way.

func (*ReachabilityIsolationScenario) Run

Run captures a baseline `aiwf check` in worktree A, commits a new entity in worktree B, re-runs check in worktree A (still unmerged) and confirms it is unchanged, probes `show`/`history` for the sibling's entity from worktree A — `show` is expected to already find it live (M-0260), `history` is expected to still show nothing (git-log-scoped, unaffected by M-0260) — then merges and confirms `history` flips to "found" — closing the loop on "unreachable via history today, reachable once merged," never "unreachable forever."

func (*ReachabilityIsolationScenario) Setup

Setup creates a main repo with a seed commit, then adds two sibling worktrees (actor-a, actor-b) off it — dir/main, dir/wt-a, dir/wt-b. Only actor-b ever commits in this scenario; actor-a is the observing side.

func (*ReachabilityIsolationScenario) Verify

Verify returns every violation Run collected.

type RepeatEvent

type RepeatEvent struct {
	Attempt        int      `json:"attempt"`
	Seed           int64    `json:"seed"`
	Passed         bool     `json:"passed"`
	Dir            string   `json:"dir,omitempty"`
	CorrelationIDs []string `json:"correlation_ids,omitempty"`
}

RepeatEvent is the raw-report event one --repeat attempt logs. The seed is what makes a violation found on a given attempt replayable: rerunning newScenario with that exact seed reproduces the same actor-start jitter and randomized delays the attempt used. Dir names the preserved scenario dir on a failing attempt (mirrors RunResult.Dir; empty on a pass). CorrelationIDs holds every diagnostic-log run_id observed during this attempt's window (empty when diagnosticLogPath was never supplied, or nothing logged) — the same value each contributing subprocess's own --format=json output reports as metadata.correlation_id (internal/cli/root.go: "reused as the diagnostic logger's run_id"), so a failing attempt's Dir plus these ids is enough to find every diagnostic-log entry that subprocess wrote without re-running the campaign.

type ReportWriter

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

ReportWriter appends JSONL events to an underlying writer, one Write call per event. Reuses internal/logger's O_APPEND + one-Write()-per-record discipline (ADR-0017 Decision #5) for the harness's own raw-report stream rather than inventing a second streaming primitive: POSIX guarantees a single write(2) under O_APPEND is atomic with respect to the file offset, so concurrent writers' events are never interleaved or torn.

func OpenReportWriter

func OpenReportWriter(path string) (*ReportWriter, error)

OpenReportWriter opens path for append, creating it if absent, and returns a ReportWriter backed by that file.

func (*ReportWriter) Close

func (rw *ReportWriter) Close() error

Close closes the underlying writer if it implements io.Closer.

func (*ReportWriter) WriteEvent

func (rw *ReportWriter) WriteEvent(event any) error

WriteEvent marshals event to JSON, appends a trailing newline, and writes the result as exactly one Write call.

type RunResult

type RunResult struct {
	Dir        string
	Passed     bool
	Violations []Violation
}

RunResult is the outcome of RunScenario. Dir names the scenario's temp directory when it survives on disk (any failure); Dir is empty when the scenario passed and its directory was already cleaned up.

func RunRepeated

func RunRepeated(newScenario func(seed int64) Scenario, baseDir string, n int, seedFn func() int64, rw *ReportWriter, diagnosticLogPath string, logOffset *int64) ([]RunResult, error)

RunRepeated runs a scenario n times against baseDir. newScenario builds one Scenario per attempt from that attempt's seed (so scenario code can thread the seed into whatever randomness it uses); seedFn supplies each attempt's seed — production callers inject a real random source, tests inject a deterministic sequence. Every attempt's outcome is logged via rw as a RepeatEvent before the next attempt starts, so a run that's killed mid-repeat still leaves every completed attempt's seed on disk. diagnosticLogPath, when non-empty, names aiwf's own diagnostic-log file (AIWF_LOG_FILE) the scenario's subprocesses write to; each attempt's RepeatEvent.CorrelationIDs is the set of run_ids that landed in the file during that attempt's own window, via a resumable byte-offset cursor so consecutive attempts never attribute the same log lines twice. logOffset is the cursor's current position — callers running multiple scenarios against one shared diagnostic-log file (e.g. cmd/stresstest run --scenario all) pass the SAME *int64 across every RunRepeated call so the cursor carries forward instead of re-scanning from byte 0 (and re- attributing every earlier scenario's ids) each time; a caller driving one scenario alone can pass a fresh var each time, or nil when diagnosticLogPath is "" (never dereferenced in that case). An empty diagnosticLogPath (no diagnostic logging enabled for this run) skips attribution entirely — every event's CorrelationIDs stays empty.

A scenario attempt that fails verification (RunScenario returns Passed: false) does not stop the repeat loop — a single pass of a concurrency-shaped scenario proves nothing about a rare race, so --repeat's whole point is running the full count regardless, buying statistical coverage across all n attempts. A mechanical failure in RunScenario itself, a failure to log an event, or an I/O-level failure reading the diagnostic log (correlationIDsSince can't open/seek/read the file) aborts the loop immediately: each is the harness's own machinery failing, so continuing would only produce more failures of the same kind. A single malformed diagnostic-log *line*, in contrast, never aborts — see correlationIDsSince's own doc comment for why that content-level case is tolerated rather than fatal.

func RunScenario

func RunScenario(s Scenario, baseDir string) (RunResult, error)

RunScenario creates a fresh temp directory under baseDir, runs Setup/Run/Verify against it, and applies the harness's cleanup discipline: a passing scenario (no error, no violations) removes its own temp dir; a failing one — a Setup or Run error, or a non-empty Verify result — preserves it, since the on-disk state at failure time is RCA material a human might want to open directly.

type Scenario

type Scenario interface {
	Setup(dir string) error
	Run(dir string) error
	Verify(dir string) []Violation
}

Scenario is one unit of the stress harness's catalog. It sets up its own disposable repo, drives its behavior, and verifies an invariant afterward. Real scenarios (the tiered catalog in docs/initiatives/robustness-correctness-stress-testing.md) land in later milestones; this milestone only builds the interface and the driver that runs one.

type VerbSequenceScenario

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

VerbSequenceScenario implements Scenario. steps is the number of walk operations run per entity kind (M-0250/AC-2: promote is one of several selectable operations now, not the only one).

func NewVerbSequenceScenario

func NewVerbSequenceScenario(aiwfBin string, seed int64, steps int) *VerbSequenceScenario

NewVerbSequenceScenario builds a scenario that walks `steps` promote attempts per kind, seeded for reproducibility.

func (*VerbSequenceScenario) Run

func (s *VerbSequenceScenario) Run(dir string) error

Run creates one entity of every kind, plus one extra scratch epic dedicated to being the milestone's alternate move target (M-0250/AC-2), and walks each through s.steps random operations. The epic and milestone are special-cased: the milestone is created immediately after the epic — while the epic is still freshly "proposed", guaranteed non-terminal — and only then are both walked, rather than "walk the epic to completion, then create the milestone" the way entity.AllKinds() order would otherwise suggest. That ordering used to let the epic's own random walk (stepPromote draws its target uniformly from the kind's full closed status set, terminal statuses included) drive it to done/cancelled before the milestone ever existed, starving `move`'s walk coverage — see G-0401. The remaining four kinds (ADR, gap, decision, contract) have no creation-time dependency on another kind's walked state, so they keep the original create-then-walk-in-place shape, in entity.AllKinds() order.

func (*VerbSequenceScenario) Setup

func (s *VerbSequenceScenario) Setup(dir string) error

Setup git-inits dir and sets a deterministic commit identity.

func (*VerbSequenceScenario) Verify

func (s *VerbSequenceScenario) Verify(_ string) []Violation

Verify returns every violation walk collected across every kind.

type Violation

type Violation struct {
	Message string
}

Violation is one invariant breach a scenario's Verify step found.

Directories

Path Synopsis
Command lockholder acquires internal/repolock's exclusive lock on the repo root passed as its only argument, prints "ACQUIRED" to signal readiness, then blocks until killed.
Command lockholder acquires internal/repolock's exclusive lock on the repo root passed as its only argument, prints "ACQUIRED" to signal readiness, then blocks until killed.

Jump to

Keyboard shortcuts

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