Clear the operations-layer alignment residuals (#1054)

Closes out the six residual items #1051 disclosed: terminology residue
on non-authority surfaces, the eval command-surface fixture that failed
when executed (#{3,4} -> #{3,5}), the vacuous retrieval-quality canary
and the nightly job that ran it, the consumer-free dream config block
and its exclusive helpers, the remaining knowledge-shaped writers moved
to the scratch tier, and the MEMORY.md consumer audit.

bin/ralph still resumes legacy .agents/ralph/ checkpoints so the
documented backwards-compat contract holds without a migration; both
paths and the outside-both refusal are now tested.

Fresh author-distinct validation returned PASS with empty not_checked,
after an earlier revision failed on a dangling nightly invoker and a
back-compat test regression that were fixed and independently
re-verified.

Test-Removal-Reason: the dream config subsystem was deleted with its tests (operations-layer residuals)
This commit is contained in:
Bo
2026-08-08 14:34:14 -04:00
committed by GitHub
parent 4f6c47bb0d
commit 62cc3b6ee0
23 changed files with 159 additions and 720 deletions
+3 -21
View File
@@ -54,22 +54,6 @@ jobs:
chmod +x tests/docs/validate-doc-release.sh
./tests/docs/validate-doc-release.sh
retrieval-bench:
name: Retrieval Quality Bench
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.5'
cache-dependency-path: cli/go.sum
- name: Run retrieval quality smoke
run: bash evals/agentops-core/fixtures/retrieval-quality-smoke.sh
# The release path is otherwise exercised only by a real `v*` tag push, which
# is how a retired .goreleaser.yml before-hook stayed broken for 20 days
# (docs/audits/release-readiness-v3.3.0.md, "Process lesson"). The nightly run
@@ -145,7 +129,7 @@ jobs:
summary:
name: Summary
needs: [cli-tests, static-validation, retrieval-bench, release-path-smoke, security-toolchain]
needs: [cli-tests, static-validation, release-path-smoke, security-toolchain]
if: always()
runs-on: ubuntu-latest
steps:
@@ -160,7 +144,6 @@ jobs:
echo "|-----|--------|"
echo "| CLI tests | ${{ needs.cli-tests.result }} |"
echo "| Static validation | ${{ needs.static-validation.result }} |"
echo "| Retrieval bench | ${{ needs.retrieval-bench.result }} |"
echo "| Release path smoke | ${{ needs.release-path-smoke.result }} |"
echo "| Security toolchain | ${{ needs.security-toolchain.result }} |"
echo ""
@@ -168,7 +151,7 @@ jobs:
} >> "$GITHUB_STEP_SUMMARY"
- name: Create issue on failure
if: needs.cli-tests.result == 'failure' || needs.static-validation.result == 'failure' || needs.retrieval-bench.result == 'failure' || needs.release-path-smoke.result == 'failure' || needs.security-toolchain.result == 'failure'
if: needs.cli-tests.result == 'failure' || needs.static-validation.result == 'failure' || needs.release-path-smoke.result == 'failure' || needs.security-toolchain.result == 'failure'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
@@ -179,7 +162,6 @@ jobs:
|-----|--------|
| CLI tests | ${{ needs.cli-tests.result }} |
| Static validation | ${{ needs.static-validation.result }} |
| Retrieval bench | ${{ needs.retrieval-bench.result }} |
| Release path smoke | ${{ needs.release-path-smoke.result }} |
| Security toolchain | ${{ needs.security-toolchain.result }} |
@@ -201,5 +183,5 @@ jobs:
fi
- name: Check for failures
if: needs.cli-tests.result == 'failure' || needs.static-validation.result == 'failure' || needs.retrieval-bench.result == 'failure' || needs.release-path-smoke.result == 'failure' || needs.security-toolchain.result == 'failure'
if: needs.cli-tests.result == 'failure' || needs.static-validation.result == 'failure' || needs.release-path-smoke.result == 'failure' || needs.security-toolchain.result == 'failure'
run: exit 1
+9
View File
@@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
- The consumer-free `dream:` config block (the retired overnight subsystem's
settings; existing config files still parse and the key is ignored), the
vacuous retrieval-quality canary and its smoke (every Go test it named was
already deleted; the retrieval-comparison contract is now explicitly
dormant and the blocking manifest-paths gate remains the live retrieval
guard), and the dormant `check-pillar-coverage.sh` GOALS.yaml script.
Remaining scratch-tier writers (`mine-all-sessions.sh`, `team-runner.sh`,
`bin/ralph`) now write under `.agents/scratch/`.
- The `ao flywheel` command family (`status`, `compare`) and the whole live
knowledge-flywheel product surface: `cli/internal/flywheelapp`, the
flywheel-only metric helpers and types, the `flywheel` build-profile bit,
+8 -4
View File
@@ -8,7 +8,7 @@
# ralph --branch feat/dark-mode "Add dark mode"
# ralph --spec spec.md "Add dark mode"
# ralph --dry-run "Add dark mode"
# ralph --resume .agents/ralph/<slug>.checkpoint
# ralph --resume .agents/scratch/ralph/<slug>.checkpoint
# ralph --phase-timeout 900 "Big feature"
set -euo pipefail
@@ -62,10 +62,14 @@ if [[ -n "$RESUME_FILE" ]]; then
echo "Checkpoint file not found: $RESUME_FILE" >&2
exit 1
fi
# Validate checkpoint is under .agents/ralph/ and has expected header
# Validate the checkpoint lives in a ralph checkpoint dir and has the
# expected header. New checkpoints are written under .agents/scratch/ralph/;
# the legacy .agents/ralph/ path stays resumable so checkpoints written
# before the scratch-tier move still work (no migration required).
case "$RESUME_FILE" in
.agents/scratch/ralph/*.checkpoint|*/.agents/scratch/ralph/*.checkpoint) ;;
.agents/ralph/*.checkpoint|*/.agents/ralph/*.checkpoint) ;;
*) echo "Refusing to source checkpoint outside .agents/ralph/: $RESUME_FILE" >&2; exit 1 ;;
*) echo "Refusing to source checkpoint outside .agents/scratch/ralph/ (or the legacy .agents/ralph/): $RESUME_FILE" >&2; exit 1 ;;
esac
if ! head -1 "$RESUME_FILE" | grep -q '^# Ralph checkpoint'; then
echo "Invalid checkpoint file (missing header): $RESUME_FILE" >&2
@@ -97,7 +101,7 @@ BRANCH="${BRANCH:-feat/ralph-$(date +%s)}"
BASE_BRANCH="${BASE_BRANCH:-$(git branch --show-current)}"
WORKDIR="${WORKDIR:-$(pwd)}"
SLUG="${SLUG:-$(echo "$GOAL" | tr ' ' '-' | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]//g' | head -c 40)}"
RALPH_DIR=".agents/ralph"
RALPH_DIR=".agents/scratch/ralph"
RALPH_LOG="${RALPH_LOG:-$RALPH_DIR/$(date +%Y-%m-%d)-$SLUG.log}"
CHECKPOINT_FILE="$RALPH_DIR/$SLUG.checkpoint"
+25 -304
View File
@@ -44,9 +44,6 @@ type Config struct {
// Models settings
Models ModelsConfig `yaml:"models" json:"models"`
// Dream settings for private overnight runs.
Dream DreamConfig `yaml:"dream" json:"dream"`
// Compile settings for ao compile headless runtime preference.
Compile CompileConfig `yaml:"compile" json:"compile"`
}
@@ -90,7 +87,6 @@ type RPIConfig struct {
TmuxCommand string `yaml:"tmux_command" json:"tmux_command"`
}
// PathsConfig holds configurable paths for artifact locations.
// Fixes G5: paths are now configurable, not hardcoded.
type PathsConfig struct {
@@ -149,71 +145,6 @@ type ModelsConfig struct {
SkillOverrides map[string]string `yaml:"skill_overrides" json:"skill_overrides"`
}
// DreamConfig holds settings for the private overnight Dream operator mode.
type DreamConfig struct {
// ReportDir is where overnight summaries and step artifacts are written.
ReportDir string `yaml:"report_dir" json:"report_dir"`
// RunTimeout is the maximum duration for a single overnight run.
RunTimeout string `yaml:"run_timeout" json:"run_timeout"`
// KeepAwake controls whether local runs should attempt keep-awake assistance.
// Nil means "not explicitly configured".
KeepAwake *bool `yaml:"keep_awake,omitempty" json:"keep_awake,omitempty"`
// Runners is the ordered list of Dream runtimes to use for multimodel work.
Runners []string `yaml:"runners,omitempty" json:"runners,omitempty"`
// SchedulerMode is the chosen host scheduler mode (manual, launchd, cron, systemd).
SchedulerMode string `yaml:"scheduler_mode,omitempty" json:"scheduler_mode,omitempty"`
// ScheduleAt is the preferred local time (HH:MM) for host-scheduled Dream runs.
ScheduleAt string `yaml:"schedule_at,omitempty" json:"schedule_at,omitempty"`
// ConsensusPolicy controls how Dream Council synthesizes multiple runner outputs.
ConsensusPolicy string `yaml:"consensus_policy,omitempty" json:"consensus_policy,omitempty"`
// CouncilRunnerTimeout caps how long each Dream Council runner lane may
// run before its context is cancelled. Accepts Go duration strings
// (e.g. "90s", "3m"). Empty means "use the built-in default".
CouncilRunnerTimeout string `yaml:"council_runner_timeout,omitempty" json:"council_runner_timeout,omitempty"`
// CreativeLane controls whether Dream Council should request wildcard ideas.
// Nil means "not explicitly configured".
CreativeLane *bool `yaml:"creative_lane,omitempty" json:"creative_lane,omitempty"`
// LocalCurator configures a local Tier 1 curator such as Ollama/Gemma.
LocalCurator DreamLocalCuratorConfig `yaml:"local_curator,omitempty" json:"local_curator,omitempty"`
}
// DreamLocalCuratorConfig holds settings for a local Tier 1 Dream curator.
type DreamLocalCuratorConfig struct {
// Enabled controls whether the local curator should be treated as active.
// Nil means "not explicitly configured".
Enabled *bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
// Engine identifies the local engine. V1 supports "ollama".
Engine string `yaml:"engine,omitempty" json:"engine,omitempty"`
// OllamaURL is the Ollama API root used when Engine is "ollama".
OllamaURL string `yaml:"ollama_url,omitempty" json:"ollama_url,omitempty"`
// Model is the Tier 1 model name.
Model string `yaml:"model,omitempty" json:"model,omitempty"`
// WorkerDir is the local Dream worker directory.
WorkerDir string `yaml:"worker_dir,omitempty" json:"worker_dir,omitempty"`
// VaultDir is the local knowledge vault written by the worker.
VaultDir string `yaml:"vault_dir,omitempty" json:"vault_dir,omitempty"`
// HourlyCap is the worker's bounded autonomy limit.
HourlyCap int `yaml:"hourly_cap,omitempty" json:"hourly_cap,omitempty"`
// AllowedJobKinds is the local curator queue allowlist.
AllowedJobKinds []string `yaml:"allowed_job_kinds,omitempty" json:"allowed_job_kinds,omitempty"`
}
// TierConfig holds model names for a tier.
type TierConfig struct {
// Claude is the Claude model name (opus, sonnet, haiku).
@@ -288,7 +219,6 @@ const (
// Default returns the default configuration.
func Default() *Config {
homeDir, _ := os.UserHomeDir()
defaultKeepAwake := true
return &Config{
Output: defaultOutput,
BaseDir: defaultBaseDir,
@@ -318,13 +248,6 @@ func Default() *Config {
},
SkillOverrides: map[string]string{},
},
Dream: DreamConfig{
ReportDir: ".agents/overnight/latest",
RunTimeout: "8h",
KeepAwake: &defaultKeepAwake,
SchedulerMode: "manual",
ConsensusPolicy: "majority",
},
Paths: PathsConfig{
LearningsDir: ".agents/learnings",
PatternsDir: ".agents/patterns",
@@ -581,19 +504,6 @@ func applyEnv(cfg *Config) *Config {
applyEnvStr(&cfg.RPI.BDCommand, "AGENTOPS_RPI_BD_COMMAND")
applyEnvStr(&cfg.RPI.TmuxCommand, "AGENTOPS_RPI_TMUX_COMMAND")
applyEnvStr(&cfg.Models.DefaultTier, "AGENTOPS_MODEL_TIER")
applyEnvStr(&cfg.Dream.ReportDir, "AGENTOPS_DREAM_REPORT_DIR")
applyEnvStr(&cfg.Dream.RunTimeout, "AGENTOPS_DREAM_RUN_TIMEOUT")
if v, ok := getEnvBoolValue("AGENTOPS_DREAM_KEEP_AWAKE"); ok {
cfg.Dream.KeepAwake = boolPtr(v)
}
if v, ok := getEnvBoolValue("AGENTOPS_DREAM_CURATOR_ENABLED"); ok {
cfg.Dream.LocalCurator.Enabled = boolPtr(v)
}
applyEnvStr(&cfg.Dream.LocalCurator.Engine, "AGENTOPS_DREAM_CURATOR_ENGINE")
applyEnvStr(&cfg.Dream.LocalCurator.OllamaURL, "AGENTOPS_DREAM_CURATOR_OLLAMA_URL")
applyEnvStr(&cfg.Dream.LocalCurator.Model, "AGENTOPS_DREAM_CURATOR_MODEL")
applyEnvStr(&cfg.Dream.LocalCurator.WorkerDir, "AGENTOPS_DREAM_CURATOR_WORKER_DIR")
applyEnvStr(&cfg.Dream.LocalCurator.VaultDir, "AGENTOPS_DREAM_CURATOR_VAULT_DIR")
if v := os.Getenv("AGENTOPS_COUNCIL_MODEL_TIER"); v != "" {
if cfg.Models.SkillOverrides == nil {
cfg.Models.SkillOverrides = make(map[string]string)
@@ -630,7 +540,6 @@ func merge(dst, src *Config) *Config {
mergeSearch(&dst.Search, &src.Search)
mergeRPI(&dst.RPI, &src.RPI)
mergeModels(&dst.Models, &src.Models)
mergeDream(&dst.Dream, &src.Dream)
mergePaths(&dst.Paths, &src.Paths)
return dst
@@ -683,41 +592,6 @@ func mergeModels(dst, src *ModelsConfig) {
}
}
// mergeDream merges Dream config fields.
func mergeDream(dst, src *DreamConfig) {
mergeStr(&dst.ReportDir, src.ReportDir)
mergeStr(&dst.RunTimeout, src.RunTimeout)
if src.KeepAwake != nil {
dst.KeepAwake = boolPtr(*src.KeepAwake)
}
if len(src.Runners) > 0 {
dst.Runners = append([]string{}, src.Runners...)
}
mergeStr(&dst.SchedulerMode, src.SchedulerMode)
mergeStr(&dst.ScheduleAt, src.ScheduleAt)
mergeStr(&dst.ConsensusPolicy, src.ConsensusPolicy)
mergeStr(&dst.CouncilRunnerTimeout, src.CouncilRunnerTimeout)
if src.CreativeLane != nil {
dst.CreativeLane = boolPtr(*src.CreativeLane)
}
mergeDreamLocalCurator(&dst.LocalCurator, &src.LocalCurator)
}
func mergeDreamLocalCurator(dst, src *DreamLocalCuratorConfig) {
if src.Enabled != nil {
dst.Enabled = boolPtr(*src.Enabled)
}
mergeStr(&dst.Engine, src.Engine)
mergeStr(&dst.OllamaURL, src.OllamaURL)
mergeStr(&dst.Model, src.Model)
mergeStr(&dst.WorkerDir, src.WorkerDir)
mergeStr(&dst.VaultDir, src.VaultDir)
mergeInt(&dst.HourlyCap, src.HourlyCap)
if len(src.AllowedJobKinds) > 0 {
dst.AllowedJobKinds = append([]string{}, src.AllowedJobKinds...)
}
}
// mergePaths merges path config fields (G5: configurable paths, not hardcoded).
func mergePaths(dst, src *PathsConfig) {
mergeStr(&dst.LearningsDir, src.LearningsDir)
@@ -855,23 +729,6 @@ func getEnvBool(key string) (bool, bool) {
return false, false
}
// getEnvBoolValue returns the boolean value and whether the env var was set to
// a recognized boolean literal.
func getEnvBoolValue(key string) (bool, bool) {
switch strings.ToLower(strings.TrimSpace(os.Getenv(key))) {
case "true", "1", "yes", "on":
return true, true
case "false", "0", "no", "off":
return false, true
default:
return false, false
}
}
func boolPtr(v bool) *bool {
return &v
}
// resolveStringField resolves a string through the precedence chain.
// Returns the resolved value and its source.
func resolveStringField(home, project, env, flag, def string) resolved {
@@ -901,51 +758,24 @@ func resolveStringField(home, project, env, flag, def string) resolved {
return result
}
func resolveStringSliceField(home, project []string, def []string) resolved {
result := resolved{Value: append([]string{}, def...), Source: SourceDefault}
if len(home) > 0 {
result = resolved{Value: append([]string{}, home...), Source: SourceHome}
}
if len(project) > 0 {
result = resolved{Value: append([]string{}, project...), Source: SourceProject}
}
return result
}
// ResolvedConfig shows config values with their sources.
//
// The RPI* and Dream* fields are excluded from serialization (`json:"-"`):
// no `ao rpi` or `ao dream` command exists, so `ao config --show` must not
// render resolved values for subsystems a user cannot invoke. The fields
// themselves are retained for now because callers outside this package
// (e.g. cmd/ao tests) still reference them; deleting the underlying Config
// struct sections is a separate pass.
// The RPI* fields are excluded from serialization (`json:"-"`): no `ao rpi`
// command exists, so `ao config --show` must not render resolved values for a
// subsystem a user cannot invoke. The Dream block was removed with the
// overnight subsystem; unknown `dream:` keys in existing config files still
// parse and are ignored.
type ResolvedConfig struct {
Output resolved `json:"output"`
BaseDir resolved `json:"base_dir"`
Verbose resolved `json:"verbose"`
RPIWorktreeMode resolved `json:"-"`
RPIRuntimeMode resolved `json:"-"`
RPIRuntimeCommand resolved `json:"-"`
RPIAOCommand resolved `json:"-"`
RPIBDCommand resolved `json:"-"`
RPITmuxCommand resolved `json:"-"`
ModelsDefaultTier resolved `json:"models_default_tier"`
DreamReportDir resolved `json:"-"`
DreamRunTimeout resolved `json:"-"`
DreamKeepAwake resolved `json:"-"`
DreamRunners resolved `json:"-"`
DreamScheduler resolved `json:"-"`
DreamScheduleAt resolved `json:"-"`
DreamConsensus resolved `json:"-"`
DreamCreativeLane resolved `json:"-"`
DreamCuratorEnabled resolved `json:"-"`
DreamCuratorEngine resolved `json:"-"`
DreamCuratorOllamaURL resolved `json:"-"`
DreamCuratorModel resolved `json:"-"`
DreamCuratorWorkerDir resolved `json:"-"`
DreamCuratorVaultDir resolved `json:"-"`
DreamCuratorJobKinds resolved `json:"-"`
Output resolved `json:"output"`
BaseDir resolved `json:"base_dir"`
Verbose resolved `json:"verbose"`
RPIWorktreeMode resolved `json:"-"`
RPIRuntimeMode resolved `json:"-"`
RPIRuntimeCommand resolved `json:"-"`
RPIAOCommand resolved `json:"-"`
RPIBDCommand resolved `json:"-"`
RPITmuxCommand resolved `json:"-"`
ModelsDefaultTier resolved `json:"models_default_tier"`
}
type resolved struct {
@@ -961,23 +791,6 @@ type configFields struct {
rpiRuntimeCommand, rpiAOCommand string
rpiBDCommand, rpiTmuxCommand string
modelsDefaultTier string
dreamReportDir, dreamRunTimeout string
dreamKeepAwake bool
dreamKeepAwakeSet bool
dreamRunners []string
dreamSchedulerMode string
dreamScheduleAt string
dreamConsensusPolicy string
dreamCreativeLane bool
dreamCreativeLaneSet bool
dreamCuratorEnabled bool
dreamCuratorEnabledSet bool
dreamCuratorEngine string
dreamCuratorOllamaURL string
dreamCuratorModel string
dreamCuratorWorkerDir string
dreamCuratorVaultDir string
dreamCuratorJobKinds []string
}
// extractFields pulls resolution-relevant fields from a Config.
@@ -987,34 +800,16 @@ func extractFields(cfg *Config) configFields {
return configFields{}
}
return configFields{
output: cfg.Output,
baseDir: cfg.BaseDir,
verbose: cfg.Verbose,
rpiWorktreeMode: cfg.RPI.WorktreeMode,
rpiRuntimeMode: cfg.RPI.RuntimeMode,
rpiRuntimeCommand: cfg.RPI.RuntimeCommand,
rpiAOCommand: cfg.RPI.AOCommand,
rpiBDCommand: cfg.RPI.BDCommand,
rpiTmuxCommand: cfg.RPI.TmuxCommand,
modelsDefaultTier: cfg.Models.DefaultTier,
dreamReportDir: cfg.Dream.ReportDir,
dreamRunTimeout: cfg.Dream.RunTimeout,
dreamKeepAwake: cfg.Dream.KeepAwake != nil && *cfg.Dream.KeepAwake,
dreamKeepAwakeSet: cfg.Dream.KeepAwake != nil,
dreamRunners: append([]string{}, cfg.Dream.Runners...),
dreamSchedulerMode: cfg.Dream.SchedulerMode,
dreamScheduleAt: cfg.Dream.ScheduleAt,
dreamConsensusPolicy: cfg.Dream.ConsensusPolicy,
dreamCreativeLane: cfg.Dream.CreativeLane != nil && *cfg.Dream.CreativeLane,
dreamCreativeLaneSet: cfg.Dream.CreativeLane != nil,
dreamCuratorEnabled: cfg.Dream.LocalCurator.Enabled != nil && *cfg.Dream.LocalCurator.Enabled,
dreamCuratorEnabledSet: cfg.Dream.LocalCurator.Enabled != nil,
dreamCuratorEngine: cfg.Dream.LocalCurator.Engine,
dreamCuratorOllamaURL: cfg.Dream.LocalCurator.OllamaURL,
dreamCuratorModel: cfg.Dream.LocalCurator.Model,
dreamCuratorWorkerDir: cfg.Dream.LocalCurator.WorkerDir,
dreamCuratorVaultDir: cfg.Dream.LocalCurator.VaultDir,
dreamCuratorJobKinds: append([]string{}, cfg.Dream.LocalCurator.AllowedJobKinds...),
output: cfg.Output,
baseDir: cfg.BaseDir,
verbose: cfg.Verbose,
rpiWorktreeMode: cfg.RPI.WorktreeMode,
rpiRuntimeMode: cfg.RPI.RuntimeMode,
rpiRuntimeCommand: cfg.RPI.RuntimeCommand,
rpiAOCommand: cfg.RPI.AOCommand,
rpiBDCommand: cfg.RPI.BDCommand,
rpiTmuxCommand: cfg.RPI.TmuxCommand,
modelsDefaultTier: cfg.Models.DefaultTier,
}
}
@@ -1027,16 +822,6 @@ type envFields struct {
rpiRuntimeCommand, rpiAOCommand string
rpiBDCommand, rpiTmuxCommand string
modelsDefaultTier string
dreamReportDir, dreamRunTimeout string
dreamKeepAwake bool
dreamKeepAwakeSet bool
dreamCuratorEnabled bool
dreamCuratorEnabledSet bool
dreamCuratorEngine string
dreamCuratorOllamaURL string
dreamCuratorModel string
dreamCuratorWorkerDir string
dreamCuratorVaultDir string
}
// loadEnvFields reads all resolution-relevant environment variables.
@@ -1055,15 +840,6 @@ func loadEnvFields() envFields {
ef.rpiBDCommand, _ = getEnvString("AGENTOPS_RPI_BD_COMMAND")
ef.rpiTmuxCommand, _ = getEnvString("AGENTOPS_RPI_TMUX_COMMAND")
ef.modelsDefaultTier, _ = getEnvString("AGENTOPS_MODEL_TIER")
ef.dreamReportDir, _ = getEnvString("AGENTOPS_DREAM_REPORT_DIR")
ef.dreamRunTimeout, _ = getEnvString("AGENTOPS_DREAM_RUN_TIMEOUT")
ef.dreamKeepAwake, ef.dreamKeepAwakeSet = getEnvBoolValue("AGENTOPS_DREAM_KEEP_AWAKE")
ef.dreamCuratorEnabled, ef.dreamCuratorEnabledSet = getEnvBoolValue("AGENTOPS_DREAM_CURATOR_ENABLED")
ef.dreamCuratorEngine, _ = getEnvString("AGENTOPS_DREAM_CURATOR_ENGINE")
ef.dreamCuratorOllamaURL, _ = getEnvString("AGENTOPS_DREAM_CURATOR_OLLAMA_URL")
ef.dreamCuratorModel, _ = getEnvString("AGENTOPS_DREAM_CURATOR_MODEL")
ef.dreamCuratorWorkerDir, _ = getEnvString("AGENTOPS_DREAM_CURATOR_WORKER_DIR")
ef.dreamCuratorVaultDir, _ = getEnvString("AGENTOPS_DREAM_CURATOR_VAULT_DIR")
return ef
}
@@ -1085,25 +861,6 @@ func resolveVerbose(home, project configFields, env envFields, flagVerbose bool)
return r
}
func resolveBoolField(
homeVal bool, homeSet bool,
projectVal bool, projectSet bool,
envVal bool, envSet bool,
def bool,
) resolved {
r := resolved{Value: def, Source: SourceDefault}
if homeSet {
r = resolved{Value: homeVal, Source: SourceHome}
}
if projectSet {
r = resolved{Value: projectVal, Source: SourceProject}
}
if envSet {
r = resolved{Value: envVal, Source: SourceEnv}
}
return r
}
// Resolve returns configuration with source tracking.
// Uses precedence chain: flags > env > project > home > defaults.
func Resolve(flagOutput, flagBaseDir string, flagVerbose bool) *ResolvedConfig {
@@ -1139,36 +896,6 @@ func Resolve(flagOutput, flagBaseDir string, flagVerbose bool) *ResolvedConfig {
RPIBDCommand: resolveStringField(home.rpiBDCommand, project.rpiBDCommand, env.rpiBDCommand, "", "bd"),
RPITmuxCommand: resolveStringField(home.rpiTmuxCommand, project.rpiTmuxCommand, env.rpiTmuxCommand, "", "tmux"),
ModelsDefaultTier: resolveStringField(home.modelsDefaultTier, project.modelsDefaultTier, env.modelsDefaultTier, "", "balanced"),
DreamReportDir: resolveStringField(home.dreamReportDir, project.dreamReportDir, env.dreamReportDir, "", ".agents/overnight/latest"),
DreamRunTimeout: resolveStringField(home.dreamRunTimeout, project.dreamRunTimeout, env.dreamRunTimeout, "", "8h"),
DreamKeepAwake: resolveBoolField(
home.dreamKeepAwake, home.dreamKeepAwakeSet,
project.dreamKeepAwake, project.dreamKeepAwakeSet,
env.dreamKeepAwake, env.dreamKeepAwakeSet,
true,
),
DreamRunners: resolveStringSliceField(home.dreamRunners, project.dreamRunners, []string{}),
DreamScheduler: resolveStringField(home.dreamSchedulerMode, project.dreamSchedulerMode, "", "", "manual"),
DreamScheduleAt: resolveStringField(home.dreamScheduleAt, project.dreamScheduleAt, "", "", ""),
DreamConsensus: resolveStringField(home.dreamConsensusPolicy, project.dreamConsensusPolicy, "", "", "majority"),
DreamCreativeLane: resolveBoolField(
home.dreamCreativeLane, home.dreamCreativeLaneSet,
project.dreamCreativeLane, project.dreamCreativeLaneSet,
false, false,
false,
),
DreamCuratorEnabled: resolveBoolField(
home.dreamCuratorEnabled, home.dreamCuratorEnabledSet,
project.dreamCuratorEnabled, project.dreamCuratorEnabledSet,
env.dreamCuratorEnabled, env.dreamCuratorEnabledSet,
false,
),
DreamCuratorEngine: resolveStringField(home.dreamCuratorEngine, project.dreamCuratorEngine, env.dreamCuratorEngine, "", ""),
DreamCuratorOllamaURL: resolveStringField(home.dreamCuratorOllamaURL, project.dreamCuratorOllamaURL, env.dreamCuratorOllamaURL, "", ""),
DreamCuratorModel: resolveStringField(home.dreamCuratorModel, project.dreamCuratorModel, env.dreamCuratorModel, "", ""),
DreamCuratorWorkerDir: resolveStringField(home.dreamCuratorWorkerDir, project.dreamCuratorWorkerDir, env.dreamCuratorWorkerDir, "", ""),
DreamCuratorVaultDir: resolveStringField(home.dreamCuratorVaultDir, project.dreamCuratorVaultDir, env.dreamCuratorVaultDir, "", ""),
DreamCuratorJobKinds: resolveStringSliceField(home.dreamCuratorJobKinds, project.dreamCuratorJobKinds, []string{}),
}
// When a layer was read through the deprecated fallback path, attribute
// its values to the path actually read so --show agrees with the
@@ -1191,12 +918,6 @@ func (rc *ResolvedConfig) relabelSource(from, to Source) {
&rc.RPIWorktreeMode, &rc.RPIRuntimeMode, &rc.RPIRuntimeCommand,
&rc.RPIAOCommand, &rc.RPIBDCommand, &rc.RPITmuxCommand,
&rc.ModelsDefaultTier,
&rc.DreamReportDir, &rc.DreamRunTimeout, &rc.DreamKeepAwake,
&rc.DreamRunners, &rc.DreamScheduler, &rc.DreamScheduleAt,
&rc.DreamConsensus, &rc.DreamCreativeLane,
&rc.DreamCuratorEnabled, &rc.DreamCuratorEngine, &rc.DreamCuratorOllamaURL,
&rc.DreamCuratorModel, &rc.DreamCuratorWorkerDir, &rc.DreamCuratorVaultDir,
&rc.DreamCuratorJobKinds,
}
for _, field := range fields {
if field.Source == from {
+20 -158
View File
@@ -2032,167 +2032,29 @@ func TestResolve_ModelsDefaultTier_EnvOverride(t *testing.T) {
}
}
func TestResolve_DreamDefaults(t *testing.T) {
t.Setenv("AGENTOPS_CONFIG", "")
for _, key := range []string{
"AGENTOPS_OUTPUT", "AGENTOPS_BASE_DIR", "AGENTOPS_VERBOSE",
"AGENTOPS_NO_SC",
"AGENTOPS_RPI_WORKTREE_MODE", "AGENTOPS_RPI_RUNTIME",
"AGENTOPS_RPI_RUNTIME_MODE", "AGENTOPS_RPI_RUNTIME_COMMAND",
"AGENTOPS_RPI_AO_COMMAND", "AGENTOPS_RPI_BD_COMMAND",
"AGENTOPS_RPI_TMUX_COMMAND",
"AGENTOPS_FLYWHEEL_AUTO_PROMOTE_THRESHOLD",
"AGENTOPS_MODEL_TIER", "AGENTOPS_COUNCIL_MODEL_TIER",
"AGENTOPS_DREAM_REPORT_DIR", "AGENTOPS_DREAM_RUN_TIMEOUT", "AGENTOPS_DREAM_KEEP_AWAKE",
} {
t.Setenv(key, "")
func TestLoadFromPath_ToleratesRetiredDreamKey(t *testing.T) {
tmpDir := t.TempDir()
configPath := filepath.Join(tmpDir, "config.yaml")
// The dream config block was retired with the overnight subsystem.
// Existing user configs that still carry the key must load.
content := `
verbose: true
dream:
report_dir: .agents/overnight/latest
local_curator:
enabled: true
`
if err := os.WriteFile(configPath, []byte(content), 0644); err != nil {
t.Fatal(err)
}
rc := Resolve("", "", false)
if rc.DreamReportDir.Value != ".agents/overnight/latest" || rc.DreamReportDir.Source != SourceDefault {
t.Fatalf("DreamReportDir = (%v, %v), want (.agents/overnight/latest, %v)", rc.DreamReportDir.Value, rc.DreamReportDir.Source, SourceDefault)
cfg, err := loadFromPath(configPath)
if err != nil {
t.Fatalf("loadFromPath() with retired dream key errored: %v", err)
}
if rc.DreamRunTimeout.Value != "8h" || rc.DreamRunTimeout.Source != SourceDefault {
t.Fatalf("DreamRunTimeout = (%v, %v), want (8h, %v)", rc.DreamRunTimeout.Value, rc.DreamRunTimeout.Source, SourceDefault)
}
if rc.DreamKeepAwake.Value != true || rc.DreamKeepAwake.Source != SourceDefault {
t.Fatalf("DreamKeepAwake = (%v, %v), want (true, %v)", rc.DreamKeepAwake.Value, rc.DreamKeepAwake.Source, SourceDefault)
}
if rc.DreamScheduler.Value != "manual" || rc.DreamScheduler.Source != SourceDefault {
t.Fatalf("DreamScheduler = (%v, %v), want (manual, %v)", rc.DreamScheduler.Value, rc.DreamScheduler.Source, SourceDefault)
}
if rc.DreamConsensus.Value != "majority" || rc.DreamConsensus.Source != SourceDefault {
t.Fatalf("DreamConsensus = (%v, %v), want (majority, %v)", rc.DreamConsensus.Value, rc.DreamConsensus.Source, SourceDefault)
}
if rc.DreamCreativeLane.Value != false || rc.DreamCreativeLane.Source != SourceDefault {
t.Fatalf("DreamCreativeLane = (%v, %v), want (false, %v)", rc.DreamCreativeLane.Value, rc.DreamCreativeLane.Source, SourceDefault)
}
if got, ok := rc.DreamRunners.Value.([]string); !ok || len(got) != 0 || rc.DreamRunners.Source != SourceDefault {
t.Fatalf("DreamRunners = (%#v, %v), want (empty, %v)", rc.DreamRunners.Value, rc.DreamRunners.Source, SourceDefault)
}
}
func TestApplyEnv_DreamOverrides(t *testing.T) {
cfg := Default()
t.Setenv("AGENTOPS_DREAM_REPORT_DIR", "/tmp/dream")
t.Setenv("AGENTOPS_DREAM_RUN_TIMEOUT", "10h")
t.Setenv("AGENTOPS_DREAM_KEEP_AWAKE", "false")
t.Setenv("AGENTOPS_DREAM_CURATOR_ENABLED", "true")
t.Setenv("AGENTOPS_DREAM_CURATOR_ENGINE", "ollama")
t.Setenv("AGENTOPS_DREAM_CURATOR_OLLAMA_URL", "http://127.0.0.1:11435")
t.Setenv("AGENTOPS_DREAM_CURATOR_MODEL", "gemma4:e4b")
t.Setenv("AGENTOPS_DREAM_CURATOR_WORKER_DIR", "D:\\dream")
t.Setenv("AGENTOPS_DREAM_CURATOR_VAULT_DIR", "D:\\vault")
got := applyEnv(cfg)
if got.Dream.ReportDir != "/tmp/dream" {
t.Fatalf("Dream.ReportDir = %q, want /tmp/dream", got.Dream.ReportDir)
}
if got.Dream.RunTimeout != "10h" {
t.Fatalf("Dream.RunTimeout = %q, want 10h", got.Dream.RunTimeout)
}
if got.Dream.KeepAwake == nil || *got.Dream.KeepAwake != false {
t.Fatalf("Dream.KeepAwake = %#v, want false", got.Dream.KeepAwake)
}
if got.Dream.LocalCurator.Enabled == nil || *got.Dream.LocalCurator.Enabled != true {
t.Fatalf("Dream.LocalCurator.Enabled = %#v, want true", got.Dream.LocalCurator.Enabled)
}
if got.Dream.LocalCurator.Engine != "ollama" {
t.Fatalf("Dream.LocalCurator.Engine = %q, want ollama", got.Dream.LocalCurator.Engine)
}
if got.Dream.LocalCurator.OllamaURL != "http://127.0.0.1:11435" {
t.Fatalf("Dream.LocalCurator.OllamaURL = %q, want http://127.0.0.1:11435", got.Dream.LocalCurator.OllamaURL)
}
if got.Dream.LocalCurator.Model != "gemma4:e4b" {
t.Fatalf("Dream.LocalCurator.Model = %q, want gemma4:e4b", got.Dream.LocalCurator.Model)
}
if got.Dream.LocalCurator.WorkerDir != "D:\\dream" {
t.Fatalf("Dream.LocalCurator.WorkerDir = %q, want D:\\dream", got.Dream.LocalCurator.WorkerDir)
}
if got.Dream.LocalCurator.VaultDir != "D:\\vault" {
t.Fatalf("Dream.LocalCurator.VaultDir = %q, want D:\\vault", got.Dream.LocalCurator.VaultDir)
}
}
func TestResolve_DreamLocalCuratorEnv(t *testing.T) {
t.Setenv("AGENTOPS_CONFIG", "")
t.Setenv("AGENTOPS_DREAM_CURATOR_ENABLED", "true")
t.Setenv("AGENTOPS_DREAM_CURATOR_ENGINE", "ollama")
t.Setenv("AGENTOPS_DREAM_CURATOR_OLLAMA_URL", "http://127.0.0.1:11435")
t.Setenv("AGENTOPS_DREAM_CURATOR_MODEL", "gemma4:e4b")
t.Setenv("AGENTOPS_DREAM_CURATOR_WORKER_DIR", "D:\\dream")
t.Setenv("AGENTOPS_DREAM_CURATOR_VAULT_DIR", "D:\\vault")
rc := Resolve("", "", false)
if rc.DreamCuratorEnabled.Value != true || rc.DreamCuratorEnabled.Source != SourceEnv {
t.Fatalf("DreamCuratorEnabled = (%v, %v), want (true, %v)", rc.DreamCuratorEnabled.Value, rc.DreamCuratorEnabled.Source, SourceEnv)
}
if rc.DreamCuratorEngine.Value != "ollama" || rc.DreamCuratorEngine.Source != SourceEnv {
t.Fatalf("DreamCuratorEngine = (%v, %v), want (ollama, %v)", rc.DreamCuratorEngine.Value, rc.DreamCuratorEngine.Source, SourceEnv)
}
if rc.DreamCuratorOllamaURL.Value != "http://127.0.0.1:11435" || rc.DreamCuratorOllamaURL.Source != SourceEnv {
t.Fatalf("DreamCuratorOllamaURL = (%v, %v), want env URL", rc.DreamCuratorOllamaURL.Value, rc.DreamCuratorOllamaURL.Source)
}
if rc.DreamCuratorModel.Value != "gemma4:e4b" || rc.DreamCuratorModel.Source != SourceEnv {
t.Fatalf("DreamCuratorModel = (%v, %v), want env model", rc.DreamCuratorModel.Value, rc.DreamCuratorModel.Source)
}
if rc.DreamCuratorWorkerDir.Value != "D:\\dream" || rc.DreamCuratorWorkerDir.Source != SourceEnv {
t.Fatalf("DreamCuratorWorkerDir = (%v, %v), want env worker", rc.DreamCuratorWorkerDir.Value, rc.DreamCuratorWorkerDir.Source)
}
if rc.DreamCuratorVaultDir.Value != "D:\\vault" || rc.DreamCuratorVaultDir.Source != SourceEnv {
t.Fatalf("DreamCuratorVaultDir = (%v, %v), want env vault", rc.DreamCuratorVaultDir.Value, rc.DreamCuratorVaultDir.Source)
}
}
func TestMergeDream_ExtendedFields(t *testing.T) {
dst := Default()
src := &Config{
Dream: DreamConfig{
Runners: []string{"codex", "claude"},
SchedulerMode: "launchd",
ScheduleAt: "01:30",
ConsensusPolicy: "majority",
CreativeLane: boolPtr(true),
LocalCurator: DreamLocalCuratorConfig{
Enabled: boolPtr(true),
Engine: "ollama",
OllamaURL: "http://127.0.0.1:11435",
Model: "gemma4:e4b",
WorkerDir: "D:\\dream",
VaultDir: "D:\\vault",
HourlyCap: 20,
AllowedJobKinds: []string{"ingest-claude-session", "lint-wiki", "dream-seed"},
},
},
}
got := merge(dst, src)
if want := []string{"codex", "claude"}; len(got.Dream.Runners) != len(want) {
t.Fatalf("Dream.Runners = %#v, want %#v", got.Dream.Runners, want)
}
if got.Dream.SchedulerMode != "launchd" {
t.Fatalf("Dream.SchedulerMode = %q, want launchd", got.Dream.SchedulerMode)
}
if got.Dream.ScheduleAt != "01:30" {
t.Fatalf("Dream.ScheduleAt = %q, want 01:30", got.Dream.ScheduleAt)
}
if got.Dream.ConsensusPolicy != "majority" {
t.Fatalf("Dream.ConsensusPolicy = %q, want majority", got.Dream.ConsensusPolicy)
}
if got.Dream.CreativeLane == nil || !*got.Dream.CreativeLane {
t.Fatalf("Dream.CreativeLane = %#v, want true", got.Dream.CreativeLane)
}
if got.Dream.LocalCurator.Enabled == nil || !*got.Dream.LocalCurator.Enabled {
t.Fatalf("Dream.LocalCurator.Enabled = %#v, want true", got.Dream.LocalCurator.Enabled)
}
if got.Dream.LocalCurator.Model != "gemma4:e4b" {
t.Fatalf("Dream.LocalCurator.Model = %q, want gemma4:e4b", got.Dream.LocalCurator.Model)
}
if got.Dream.LocalCurator.HourlyCap != 20 {
t.Fatalf("Dream.LocalCurator.HourlyCap = %d, want 20", got.Dream.LocalCurator.HourlyCap)
}
if got := strings.Join(got.Dream.LocalCurator.AllowedJobKinds, ","); got != "ingest-claude-session,lint-wiki,dream-seed" {
t.Fatalf("Dream.LocalCurator.AllowedJobKinds = %q", got)
if !cfg.Verbose {
t.Fatal("loadFromPath Verbose = false, want true (sibling keys must still parse)")
}
}
+2 -2
View File
@@ -512,8 +512,8 @@ func TestTrackChild_ConcurrentAccess(t *testing.T) {
func TestMeasureOne_Skip_ExitCode77(t *testing.T) {
// When a gate exits 77 (autotools skip convention), the goals runner
// must classify the measurement as `skip`, not `fail`. This is the
// quarantine-by-precondition path used by check-flywheel-compounding.sh
// when the corpus is dormant — failing under "no signal" is a
// quarantine-by-precondition path skip-aware gate scripts use when a
// precondition is absent — failing under "no signal" is a
// misclassification that artificially drags fitness scores.
g := Goal{ID: "skip77", Check: "exit 77", Weight: 3}
m := MeasureOne(g, time.Second)
+9
View File
@@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
- The consumer-free `dream:` config block (the retired overnight subsystem's
settings; existing config files still parse and the key is ignored), the
vacuous retrieval-quality canary and its smoke (every Go test it named was
already deleted; the retrieval-comparison contract is now explicitly
dormant and the blocking manifest-paths gate remains the live retrieval
guard), and the dormant `check-pillar-coverage.sh` GOALS.yaml script.
Remaining scratch-tier writers (`mine-all-sessions.sh`, `team-runner.sh`,
`bin/ralph`) now write under `.agents/scratch/`.
- The `ao flywheel` command family (`status`, `compare`) and the whole live
knowledge-flywheel product surface: `cli/internal/flywheelapp`, the
flywheel-only metric helpers and types, the `flywheel` build-profile bit,
+6
View File
@@ -1,6 +1,12 @@
# AgentOps Eval Architecture — v1
> **Status:** PROPOSED (Bo to ratify) · **Date:** 2026-08-04
> **Terminology note (2026-08-07):** this dated proposal predates the
> operations-layer alignment and keeps its original wording ("the operating
> loop", "~150 skills"). The current product category and vocabulary live in
> [`../contracts/ubiquitous-language.md`](../contracts/ubiquitous-language.md);
> the catalog is 51 canonical skills. Read the decisions here against that
> current frame.
> **Inputs:** [skill-eval SOTA research](../research/skill-eval-sota-standards-2026-08.md) ·
> [effectiveness evidence audit](../evals/agentops-effectiveness-evidence.md) · the in-tree eval
> substrate (`cli/internal/eval/`, `cli/internal/evalsubstrate/`, `evals/`)
@@ -85,7 +85,13 @@ documents:
# MEMORY.md is a temporary machine-consumed projection, not an AgentOps
# authority: its claims belong to their cited sources (docs, ADRs, session
# records). Retire it only after its current consumers are audited.
# records). Consumer audit (2026-08-07): two live consumers exist — the
# corpus-delta eval harness (scripts/corpus-delta-harness.sh reads it as a
# context surface in both A/B arms) and the coding-agent convention of
# loading a root memory file. The former ao session memory writer is
# removed, so the file is read-only surface. Retained; retire when the
# harness stops reading it and the convention is served by a caller-owned
# memory system.
- path: MEMORY.md
tracked: true
class: machine-consumed-memory-projection
+1 -1
View File
@@ -1,6 +1,6 @@
# Optional Lesson Format
Learn may analyze collections of durable verdicts after the operating loop has
Learn may analyze collections of durable verdicts after an RPI traversal has
finished. When a caller chooses to preserve a recurring pattern as a lesson, use
one Markdown file under a caller-selected directory such as
`.agents/learnings/`. Lessons are advisory evidence; they never change RPI
+11 -26
View File
@@ -1,30 +1,15 @@
# Retrieval Comparison Contract
# Retrieval Comparison Contract (dormant)
The former retrieval-bench CLI was retired from the production command spine.
The deterministic decision gate for changing retrieval behavior is the
repository-owned smoke below. It exercises the retained Go implementation
directly, including named backend comparison over the same manifest, search
root, and `k`.
## Command Surface
The canonical comparison smoke is:
```bash
bash evals/agentops-core/fixtures/retrieval-quality-smoke.sh
```
The smoke runs focused Go tests covering:
- train/holdout Precision@K and MRR
- representative live-corpus coverage and stable top results
- multi-backend comparison report shape
- offline `agentic-rg`, `wiki-link-expand`, and `rerank-llamacpp` fallback behavior
- retrieval quality thresholds
The smoke must run offline. The `rerank-llamacpp` case leaves
`AGENTOPS_RETRIEVAL_RERANK_ENDPOINT` unset, proving the file-backed fallback
rather than contacting a live model.
> **Status (2026-08-07): dormant.** The retrieval-bench surface is fully
> retired: the `ao eval bench` seat is deliberately unwired, the Go tests the
> former comparison smoke named were deleted with their implementation, and
> the smoke itself was removed once it could no longer execute anything
> (a canary that runs zero tests is theater, not proof). The one live
> retrieval guard is the blocking `always.retrieval-manifest-paths` gate,
> which keeps the checked-in eval manifest's ground-truth paths resolvable.
> The sections below are retained as the binding policy for any future
> retrieval-backend revival; they govern nothing until such an
> implementation exists and brings its own executable comparison smoke.
## Report Shape
+1 -1
View File
@@ -45,7 +45,7 @@ Dated plans, audits, releases, and archive material are historical evidence, not
- [Producer-Defect Recurrence Contract](contracts/producer-defect-register.md)
- [Generated skill projections](contracts/registry-as-derived.md)
- [Release Notes Contract](contracts/release-notes.md)
- [Retrieval Comparison Contract](contracts/retrieval-comparison.md)
- [Retrieval Comparison Contract (dormant)](contracts/retrieval-comparison.md)
- [Runtime Neutrality Contract](contracts/runtime-neutrality.md)
- [Scenario → Test Linkage Contract](contracts/scenario-test-linkage.md)
- [Scope Escape Report Template](contracts/scope-escape-report.md)
@@ -15,7 +15,7 @@ trap cleanup EXIT
top_count="$(rg -c '^### `ao ' "$DOCS_PATH")"
sub_count="$(rg -c '^#### `ao ' "$DOCS_PATH")"
all_count="$(rg -c '^#{3,4} `ao ' "$DOCS_PATH")"
all_count="$(rg -c '^#{3,5} `ao ' "$DOCS_PATH")"
if [[ "$top_count" != "20" || "$sub_count" != "56" || "$all_count" != "89" ]]; then
printf 'unexpected command heading counts: top=%s sub=%s all=%s\n' "$top_count" "$sub_count" "$all_count" >&2
@@ -23,7 +23,7 @@ if [[ "$top_count" != "20" || "$sub_count" != "56" || "$all_count" != "89" ]]; t
fi
# shellcheck disable=SC2016 # literal backticks delimit generated Markdown command headings.
mapfile -t commands < <(rg '^#{3,4} `ao ' "$DOCS_PATH" | sed -E 's/^.*`([^`]+)`.*/\1/')
mapfile -t commands < <(rg '^#{3,5} `ao ' "$DOCS_PATH" | sed -E 's/^.*`([^`]+)`.*/\1/')
if [[ "${#commands[@]}" -ne 89 ]]; then
printf 'unexpected command matrix size: %s\n' "${#commands[@]}" >&2
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
(
cd "$ROOT/cli"
env -u AGENTOPS_RPI_RUNTIME go test -count=1 -timeout=120s ./cmd/ao -run '^(TestRetrievalBench_BuildReportTrainHoldoutAndSections|TestRetrievalBench_RealCorpusManifestHasTrainHoldoutCoverage|TestRetrievalBench_PrecisionAtK|TestBuildLiveReport_FixtureCoverage|TestBuildSearchEvalComparisonReport_JSONIncludesBackendMetrics|TestSearchEvalBackendAgenticRGPathTokenSearch|TestSearchEvalBackendWikiLinkExpand|TestSearchEvalBackendRerankLlamaCPPSkipsWhenEndpointUnset)$'
)
echo "retrieval quality smoke passed"
@@ -1,143 +0,0 @@
{
"schema_version": 1,
"id": "agentops-core.retrieval-quality-gates",
"name": "AgentOps Retrieval Quality Gates Canary",
"description": "Offline public canary for real-corpus retrieval quality, search-backend comparison, and deterministic fixture coverage.",
"practices": [
"llm-eval-harness",
"wiki-knowledge-surface"
],
"domain": "retrieval",
"visibility": "public_canary",
"tier": "deterministic",
"owners": [
"agentops"
],
"tags": [
"canary",
"offline",
"retrieval",
"knowledge",
"dream"
],
"allowed_runtimes": [
"shell",
"static"
],
"environment": {
"offline_required": true,
"network": "forbidden",
"scrub_env_prefixes": [
"AGENTOPS_RPI_RUNTIME",
"ANTHROPIC_",
"OPENAI_"
],
"timeout_seconds": 120
},
"fixtures": [
{
"path": "fixtures/retrieval-quality-smoke.sh",
"purpose": "Behavioral retrieval smoke covering quality thresholds, live-corpus ranking, and offline backend comparison.",
"required": true
}
],
"scoring": {
"aggregate_threshold": 1,
"dimensions": [
{
"name": "correctness",
"weight": 2,
"threshold": 1,
"critical": true
},
{
"name": "learning_closure",
"weight": 2,
"threshold": 1,
"critical": true
},
{
"name": "process_adherence",
"weight": 1,
"threshold": 1
},
{
"name": "artifact_quality",
"weight": 1,
"threshold": 1
},
{
"name": "runtime_compatibility",
"weight": 1,
"threshold": 1
}
]
},
"baseline_policy": {
"mode": "compare",
"baseline_path": ".agents/evals/baselines/agentops-core.retrieval-quality-gates.baseline.json",
"blocking_gate": "none"
},
"cases": [
{
"id": "retrieval-quality-smoke",
"title": "real-corpus retrieval smoke passes",
"kind": "command",
"objective": "Keep train/holdout retrieval quality, live-corpus ranking, and offline backend comparison passing.",
"runtime": "shell",
"timeout_seconds": 120,
"inputs": {
"cwd": "../..",
"shell": "bash evals/agentops-core/fixtures/retrieval-quality-smoke.sh"
},
"expectations": [
{
"type": "exit_code",
"value": 0
},
{
"type": "stdout_contains",
"value": "retrieval quality smoke passed"
}
],
"dimensions": [
"correctness",
"learning_closure",
"runtime_compatibility"
],
"critical": true
},
{
"id": "retrieval-real-corpus-fixtures",
"title": "real-corpus retrieval fixtures preserve holdout labels",
"kind": "artifact_check",
"objective": "Keep the live retrieval fixture corpus large enough and explicitly labeled for holdout quality checks.",
"expectations": [
{
"type": "artifact_contains",
"target": "../../cli/cmd/ao/testdata/retrieval-bench-live/benchmark.json",
"value": "\"split\": \"holdout\""
},
{
"type": "artifact_contains",
"target": "../../cli/cmd/ao/testdata/retrieval-bench-live/benchmark.json",
"value": "\"best_id\""
},
{
"type": "artifact_contains",
"target": "../../cli/cmd/ao/testdata/retrieval-bench-live/security-toolchain-gate.md",
"value": "Security Toolchain Gate"
},
{
"type": "artifact_contains",
"target": "../../cli/cmd/ao/testdata/retrieval-bench-live/architecture-surface-contract.md",
"value": "Architecture Surface Contract"
}
],
"dimensions": [
"artifact_quality",
"learning_closure"
]
}
]
}
+1 -1
View File
@@ -122,7 +122,7 @@ parse_spec() {
AGENT_COUNT=$MAX_AGENTS
fi
TEAM_DIR=".agents/teams/${TEAM_ID}"
TEAM_DIR=".agents/scratch/teams/${TEAM_ID}"
mkdir -p "$TEAM_DIR"
}
-1
View File
@@ -83,7 +83,6 @@ scripts/check-orchestration-contracts.sh
scripts/check-outcomes-holdout-leak.sh
scripts/check-paths-resolver-coverage.sh
scripts/check-pawl-pre-push.sh
scripts/check-pillar-coverage.sh
scripts/check-product-freshness.sh
scripts/check-proof-coherence.sh
scripts/check-provenance-chain.sh
-28
View File
@@ -1,28 +0,0 @@
#!/usr/bin/env bash
# check-pillar-coverage.sh — Verify GOALS.yaml has goals for all 4 pillars.
#
# Post-GOALS.md migration (see CLAUDE.md §Agent Goals): GOALS.yaml is the
# legacy YAML format. When it is absent but GOALS.md is present, skip with
# exit 0 because the markdown narrative does not carry machine-readable
# per-goal `pillar` fields; no downstream gate depends on this script today.
set -uo pipefail
GOALS_FILE="${1:-GOALS.yaml}"
if [ ! -f "$GOALS_FILE" ]; then
if [ -f "GOALS.md" ]; then
echo "SKIP: GOALS.yaml not found; repo uses GOALS.md (post-migration). Pillar coverage is documented in the narrative, not machine-checkable here." >&2
exit 0
fi
echo "ERROR: GOALS.yaml not found at $GOALS_FILE" >&2
exit 1
fi
pillars=$(yq '.goals[].pillar' "$GOALS_FILE" | sort -u)
for p in knowledge-compounding validated-acceleration goal-driven-automation zero-friction-workflow; do
if ! echo "$pillars" | grep -q "$p"; then
echo "MISSING pillar: $p" >&2
exit 1
fi
done
+1 -1
View File
@@ -27,7 +27,7 @@ set -uo pipefail
AO="${AGENTOPS_AO_BIN:-ao}"
SESSIONS_DIR="${1:-$HOME/.claude/projects/-Users-bo-dev-agentops}"
STORE_DIR=".agents/provenance"
STORE_DIR=".agents/scratch/provenance-mine"
STORE="$STORE_DIR/mine-events.jsonl"
STATE_DIR="$STORE_DIR/state"
SUMMARY="$STORE_DIR/mine-summary.json"
@@ -12,5 +12,4 @@ evals/agentops-core/distribution-install-update.json
evals/agentops-core/eval-runner-engine-control-plane.json
evals/agentops-core/rpi-behavior.json
evals/agentops-core/release-security-gates.json
evals/agentops-core/retrieval-quality-gates.json
evals/agentops-core/runtime-smoke-matrix.json
+8 -8
View File
@@ -48,9 +48,9 @@ JSONL
run env AGENTOPS_AO_BIN="$AO_BIN" bash "$SCRIPT" "$SESS"
[ "$status" -eq 0 ]
[[ "$output" == *"mine-all"* ]]
# The store exists, is gitignored-by-convention (.agents/provenance/), and holds
# The store exists, is gitignored-by-convention (.agents/scratch/provenance-mine/), and holds
# the mined per-inference events.
store="$WORK/.agents/provenance/mine-events.jsonl"
store="$WORK/.agents/scratch/provenance-mine/mine-events.jsonl"
[ -f "$store" ]
# Two tool_use blocks -> two tool_call events; the tool_result is filtered out.
n="$(grep -c '"kind":"tool_call"' "$store")"
@@ -62,7 +62,7 @@ JSONL
@test "mine-all: re-run is incremental (idempotent) — already-mined events are not re-appended" {
cd "$WORK"
env AGENTOPS_AO_BIN="$AO_BIN" bash "$SCRIPT" "$SESS" >/dev/null
store="$WORK/.agents/provenance/mine-events.jsonl"
store="$WORK/.agents/scratch/provenance-mine/mine-events.jsonl"
before="$(grep -c '"schema_version"' "$store")"
# Second run over the SAME unchanged session: --state has advanced, so 0 new.
run env AGENTOPS_AO_BIN="$AO_BIN" bash "$SCRIPT" "$SESS"
@@ -75,7 +75,7 @@ JSONL
@test "mine-all: writes a valid summary artifact with reconciled counts" {
cd "$WORK"
env AGENTOPS_AO_BIN="$AO_BIN" bash "$SCRIPT" "$SESS" >/dev/null
summary="$WORK/.agents/provenance/mine-summary.json"
summary="$WORK/.agents/scratch/provenance-mine/mine-summary.json"
[ -f "$summary" ]
run jq -e '.sessions_mined==1 and .new_events==2 and .store_total==2 and .failed==0' "$summary"
[ "$status" -eq 0 ]
@@ -83,8 +83,8 @@ JSONL
@test "mine-all: a held lock makes a concurrent miner exit 2 (single writer)" {
cd "$WORK"
mkdir -p .agents/provenance
mkdir .agents/provenance/.mine.lock # simulate another miner holding the lock
mkdir -p .agents/scratch/provenance-mine
mkdir .agents/scratch/provenance-mine/.mine.lock # simulate another miner holding the lock
run env AGENTOPS_AO_BIN="$AO_BIN" bash "$SCRIPT" "$SESS"
[ "$status" -eq 2 ]
[[ "$output" == *"another miner holds the lock"* ]]
@@ -116,7 +116,7 @@ STUB
[ "$status" -eq 1 ] # exit reflects the failure (defect 1)
[[ "$output" == *"(1 failed)"* ]]
# The advanced state was rolled back (removed) — not left to skip never-stored events.
[ ! -f "$WORK/.agents/provenance/state/sess-a.json" ]
[ ! -f "$WORK/.agents/scratch/provenance-mine/state/sess-a.json" ]
# Nothing was appended to the store.
[ ! -s "$WORK/.agents/provenance/mine-events.jsonl" ] || ! grep -q . "$WORK/.agents/provenance/mine-events.jsonl"
[ ! -s "$WORK/.agents/scratch/provenance-mine/mine-events.jsonl" ] || ! grep -q . "$WORK/.agents/scratch/provenance-mine/mine-events.jsonl"
}
+39
View File
@@ -68,3 +68,42 @@ CKPT
[[ "$output" != *"Budget:"* ]]
[ ! -e "$TMP/does-not-exist" ]
}
@test "checkpoints under the canonical scratch dir resume" {
mkdir -p "$TMP/.agents/scratch/ralph"
cat > "$TMP/.agents/scratch/ralph/resume.checkpoint" <<CKPT
# Ralph checkpoint — source this to resume
GOAL=Scratch\ tier\ resume
BRANCH=feat/scratch-resume
BASE_BRANCH=main
WORKDIR=$TMP
SLUG=resume
SKIP_PRE_MORTEM=false
SPEC_FILE=''
RALPH_LOG=.agents/scratch/ralph/resume.log
LAST_PHASE=pr
CKPT
cd "$TMP"
run env CODEX_BIN="$TMP/does-not-exist" "$RALPH" \
--resume .agents/scratch/ralph/resume.checkpoint --dry-run
[ "$status" -eq 0 ]
[[ "$output" == *"Resuming after phase: pr"* ]]
[ ! -e "$TMP/does-not-exist" ]
}
@test "a checkpoint outside both ralph dirs is still refused" {
mkdir -p "$TMP/elsewhere"
cat > "$TMP/elsewhere/evil.checkpoint" <<'CKPT'
# Ralph checkpoint — source this to resume
GOAL=pwned
CKPT
cd "$TMP"
run env CODEX_BIN="$TMP/does-not-exist" "$RALPH" \
--resume elsewhere/evil.checkpoint --dry-run
[ "$status" -eq 1 ]
[[ "$output" == *"Refusing to source checkpoint outside"* ]]
}
+6 -6
View File
@@ -11,9 +11,9 @@ TMPDIR=$(mktemp -d)
cleanup() {
rm -rf "$TMPDIR" \
"$REPO_ROOT/.agents/teams/test-run-001" \
"$REPO_ROOT/.agents/teams/test-run-claude-001" \
"$REPO_ROOT/.agents/teams/test-run-claude-crash"
"$REPO_ROOT/.agents/scratch/teams/test-run-001" \
"$REPO_ROOT/.agents/scratch/teams/test-run-claude-001" \
"$REPO_ROOT/.agents/scratch/teams/test-run-claude-crash"
}
trap cleanup EXIT
@@ -54,8 +54,8 @@ assert_not_contains() {
}
echo "=== Test: team-runner.sh dry-run ==="
rm -rf "$REPO_ROOT/.agents/teams/test-run-001" \
"$REPO_ROOT/.agents/teams/test-run-claude-001"
rm -rf "$REPO_ROOT/.agents/scratch/teams/test-run-001" \
"$REPO_ROOT/.agents/scratch/teams/test-run-claude-001"
# Test 1: Syntax check
echo "Test 1: Syntax check"
@@ -75,7 +75,7 @@ assert_contains "shows codex runtime" "Runtime: codex" "$OUTPUT"
# Test 3: Dry run produces report
echo "Test 3: Report generation"
assert_eq "report exists" "true" "$(test -f "$REPO_ROOT/.agents/teams/test-run-001/team-report.md" && echo true || echo false)"
assert_eq "report exists" "true" "$(test -f "$REPO_ROOT/.agents/scratch/teams/test-run-001/team-report.md" && echo true || echo false)"
# Test 4: Sandbox level mapping
echo "Test 4: Sandbox level mapping"