mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
6bb54bb347
A fresh `ao init` was immediately flagged by the CLI's own diagnostics — `ao doctor diff` reported `fm-knowledge-missing-substructure` (sessions, index missing) and the `.agents/ao/intents/sha256` store that `ao status` reads was never created. This was the last first-run wart from the [3.3 release-readiness audit](docs/audits/release-readiness-3.3-2026-07-20.md) (agents-runtime minor 3). **Fix:** `evidenceDirs` now derives the knowledge substructure from the storage package's exported contract (`DefaultBaseDir` + `SessionsDir`/`IndexDir`/`ProvenanceDir`) instead of a parallel hand-list, and adds the intents store — so init, status, and doctor agree on one layout by construction. **Verified:** RED reproduced in a sandbox (P2 finding on fresh init), GREEN after fix (finding gone, status reads both stores); new initapp tests assert both contracts on the created tree and that dry-run touches nothing; full suite 61/61 packages; `ao gate check --full` 67/67 over this range.
60 lines
2.1 KiB
Go
60 lines
2.1 KiB
Go
// Package initapp owns the filesystem effects behind the `ao init` command. It
|
|
// creates the local AgentOps evidence and verdict directories, keeping the init
|
|
// command module a thin Cobra presentation seam that performs no direct
|
|
// filesystem effect. It never initializes Git, edits ignore files, installs
|
|
// hooks, selects work, or starts a runtime.
|
|
package initapp
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/boshu2/agentops/cli/internal/storage"
|
|
)
|
|
|
|
// evidenceDirs is the fixed, ordered set of local directories `ao init` creates.
|
|
// It must cover both loop-evidence stores `ao status` reads (intents, verdicts)
|
|
// and the knowledge-store substructure `ao doctor` enforces (the storage
|
|
// package's sessions/index/provenance contract), so a fresh init is never
|
|
// flagged incomplete by the CLI's own diagnostics.
|
|
var evidenceDirs = []string{
|
|
filepath.Join(storage.DefaultBaseDir, "intents", "sha256"),
|
|
filepath.Join(storage.DefaultBaseDir, "verdicts", "sha256"),
|
|
filepath.Join(storage.DefaultBaseDir, storage.SessionsDir),
|
|
filepath.Join(storage.DefaultBaseDir, storage.IndexDir),
|
|
filepath.Join(storage.DefaultBaseDir, storage.ProvenanceDir),
|
|
filepath.Join(".agents", "handoff"),
|
|
}
|
|
|
|
// RunOptions carries the presentation choices resolved by the command module.
|
|
// The working directory is resolved inside Run so the module never performs a
|
|
// direct filesystem effect.
|
|
type RunOptions struct {
|
|
// DryRun prints what would be created without creating anything.
|
|
DryRun bool
|
|
// Stdout receives the per-directory progress lines.
|
|
Stdout io.Writer
|
|
}
|
|
|
|
// Run creates the local evidence and verdict directories, or reports what it
|
|
// would create under DryRun.
|
|
func Run(opts RunOptions) error {
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
return fmt.Errorf("get cwd: %w", err)
|
|
}
|
|
for _, relative := range evidenceDirs {
|
|
if opts.DryRun {
|
|
fmt.Fprintf(opts.Stdout, "would create %s\n", relative)
|
|
continue
|
|
}
|
|
if err := os.MkdirAll(filepath.Join(cwd, relative), 0o700); err != nil {
|
|
return fmt.Errorf("create %s: %w", relative, err)
|
|
}
|
|
fmt.Fprintf(opts.Stdout, "created %s\n", relative)
|
|
}
|
|
return nil
|
|
}
|