Files
boshu2__agentops/schemas/finding.json
T
Bo a4108a5503 fix: critical audit findings remediation (epic soc-ab5g) (#279)
* fix(session): sanitize init-step exec and correct BEADS_ACTOR

Two defects in `ao session spawn` runInitSteps, from the 2026-05-16
codebase audit (epic soc-ab5g):

- BEADS_ACTOR was exported as the expanded command string of the first
  init step instead of the session actor identity, so beads attribution
  for every init step was garbage. Thread tmpl.Identity.BeadsActorTemplate
  through runInitSteps and export the var only when non-empty.
- Init steps ran via raw exec.Command("bash","-c",...) (SEC-C1). Route
  init-step exec through shellutil.SanitizedBashCommand and add
  sanitizeHostname() to strip shell metacharacters from {{hostname}}-class
  template vars before substitution.

New regression tests: TestRunInitStepsSetsBeadsActor, TestSanitizeHostname.

Refs: soc-jhxr

* fix(autodev): replace vague 'validation failed' with a concrete summary

outputAutodevValidateResult returned fmt.Errorf("validation failed")
after already printing the detailed INVALID/ERROR lines -- a redundant,
content-free wrapper. Return a summary naming the file and the
validation-error count instead (COPY-C1, epic soc-ab5g).

Refs: soc-mpzu

* docs(eval): strip internal Day-N cadence jargon from user-facing text

eval_task.go exposed internal sprint labels ("Day-2 placeholder",
"Day-3 wires real launch", "Day-4 gate #4") in command Long
descriptions and flag help. Reword to describe current behavior
without the internal cadence (COPY-C2, epic soc-ab5g).

Refs: soc-iy7p

* fix(cli): reject unknown subcommands on group commands

Group-parent commands (daemon, beads, codex, constraint, factory,
goals, hooks, ratchet, rpi, session) had no Args validator, so an
unknown subcommand printed help to stdout and exited 0 -- breaking
`if ao rpi <bad>; then ...` scripting. Add Args: cobra.NoArgs to all
ten; unknown subcommands now exit 1 with the error on stderr
(CLI-C1, epic soc-ab5g).

Refs: soc-mlqe

* docs(cli): regenerate COMMANDS.md after eval-task help copy edit

* fix(daemon): contain dream output_dir against path traversal

DreamRunJobSpec/DreamStageJobSpec/DreamStageManifest Validate() only
TrimSpace-checked output_dir, leaving the operator-supplied job payload
free to redirect summary/log writes outside the intended tree.

validateOutputDir now rejects ".." traversal in all three Validate()
paths; outputDirContained rejects an absolute output_dir resolving
outside the daemon working tree, checked in DreamExecutor.RunJob before
MkdirAll. Containment checks: 1 (symlink only) → 3 (symlink + .. + abs).

Closes soc-ly33 (SEC-C2, epic soc-ab5g).

* fix(cli): wire ao --version flag and unify goals --json with -o

rootCmd had no Version field, so `ao --version` was unsupported even
though an `ao version` subcommand existed. Set rootCmd.Version = version
(the ldflags-injected build var) so the standard --version flag works.

goals registered its own local --json bool, disconnected from the
global -o/--output flag — `ao goals measure -o json` was ignored. Drop
goalsJSON; goalsJSONOutput() now reads GetOutput(), the sibling pattern
used by agentopsd.go, autodev.go, codex.go and ~40 other callsites. The
global --json persistent flag is inherited, so `ao goals --json` still
works; output paths honored by goals: 1 (local bool) → 2 (--json + -o).

Closes soc-nx1o (CLI-C2, epic soc-ab5g).

* perf(cli): collapse tmux probe storm in ao rpi status

checkTmuxSessionAlive forked `tmux has-session` up to 3 times per
non-terminal run, each with a 2s timeout — a status scan over N runs
issued 3N subprocesses and could stall ~6N seconds when tmux was slow
or absent.

probeTmuxSessions now runs one `tmux ls -F #{session_name}`, memoized
per process behind a mutex-guarded cache; tmuxSessionAlive filters the
snapshot in Go. resolveRPIToolchainDefaults collapses from per-run to
once. Subprocesses per status scan: 3N → 1.

Closes soc-d7v5 (PERF-C1, epic soc-ab5g). Mirrors the snapshot-then-
filter shape used elsewhere for batch probes.

* perf(cli): one-pass git capture + walk-once index in ao beads audit

ao beads audit re-shelled git per bead (one `git log --grep` per bead,
one `git log --since` per bead-path pair) and re-walked the worktree
per pattern (recordAuditStaleFinding probes up to 10 patterns/bead, so
up to 10N full-repo walks for N beads).

captureAuditCommits now runs a single `git log --all --name-only`,
parsed into auditCommit records; grepCommitsForID and
fileChangesSinceCommits filter that slice in Go. repoContentCache walks
the scoped roots once (lazily) and memoizes a path->content map shared
across every pattern probe. git subprocesses per audit: O(beads) → 1;
repo walks: O(10*beads) → 1. Mirrors the snapshot-then-filter shape
just applied to ao rpi status.

Closes soc-2grz (PERF-C2, epic soc-ab5g).

* fix(schemas): declare schema_version const in 15 unversioned schemas

15 of 34 schemas under schemas/ carried versioned filenames (or implied
a stable contract) without a machine-readable schema_version, so a
consumer could not detect the version from the payload alone.

Each now declares an optional schema_version integer const, mirroring
the shape in schemas/bead.v1.schema.json: const 1 for every schema
except skill-frontmatter.v2 (const 2). The field is intentionally left
out of "required" so existing documents without it still validate —
non-breaking. scenario.v1 keeps its legacy "version" field alongside.
Schemas declaring schema_version: 19/34 → 34/34.

Closes soc-wzgo (API-C2, epic soc-ab5g).

* docs(contracts): regenerate context-map after merging main

The merge of origin/main pulled a discovery SKILL.md description edit
without its companion context-map regeneration, so
validate-context-map-drift flagged 1 stale line. Regenerated via
scripts/generate-context-map.sh. Drifted lines: 1 → 0.
2026-05-16 11:05:36 -04:00

53 lines
1.9 KiB
JSON

{
"$schema": "https://json-schema.org/draft-07/schema#",
"title": "Finding Item",
"description": "Canonical finding-item schema for AgentOps validation skills. A compatible subset of the finding-artifact schema (docs/contracts/finding-artifact.schema.json). Any valid finding item is also a valid verdict.json finding entry.",
"practices": ["dora-metrics", "wiki-knowledge-surface"],
"type": "object",
"properties": {
"schema_version": {
"type": "integer",
"const": 1
},
"id": {
"type": "string",
"description": "Finding identifier for cross-skill correlation (e.g., f-2026-03-12-001). Maps to finding-artifact.id."
},
"severity": {
"type": "string",
"enum": ["critical", "significant", "minor"],
"description": "Impact level. Maps to finding-artifact.severity."
},
"category": {
"type": "string",
"description": "Finding classification (e.g., security, architecture, performance, style)."
},
"description": {
"type": "string",
"description": "What was found. Maps to finding-artifact.summary."
},
"location": {
"type": "string",
"description": "File:line reference if applicable."
},
"recommendation": {
"type": "string",
"description": "How to address the finding. Maps to finding-artifact.checklist_item."
},
"fix": {
"type": ["string", "null"],
"description": "Specific action to resolve this finding."
},
"why": {
"type": ["string", "null"],
"description": "Root cause or rationale."
},
"ref": {
"type": ["string", "null"],
"description": "File path, spec anchor, or doc reference. Maps to finding-artifact.source_artifact."
}
},
"required": ["severity", "category", "description", "location", "recommendation", "fix", "why", "ref"],
"additionalProperties": false
}