Files
MOPAC/internal/writeback/report_test.go
T
mrcharles aefa73aa90 harness: LiteLLM client, Redmine intake, REPORT writeback, gated bash tool
OpenAI-compatible chat client for the LiteLLM proxy (base_url normalization,
Bearer auth, retry/backoff on 429/5xx/transport, usage accounting) - stdlib
http only. Intake lists issues in scope from /issues.json with the task
class read from a configurable custom field. Writeback lands each turn as
REPORT-<vertical>-<task>-<ts>.md plus REPORT-latest.md (atomic rename) with
model/tier/token telemetry. The bash tool ports maki's permission semantics
without tree-sitter: segment-by-segment compound-command checks, deny beats
allow, word-boundary "cmd *" matching, $()/backtick/subshell denied, output
truncation, per-command timeout with process-group cleanup.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-08-28 19:20:57 -05:00

79 lines
2.1 KiB
Go

package writeback
import (
"os"
"path/filepath"
"strings"
"testing"
"time"
"git.knownelement.com/reachableceo/MOPAC/harness/internal/task"
)
func TestWriteProducesReportAndLatest(t *testing.T) {
dir := t.TempDir()
r := Report{
Time: time.Date(2026, 8, 28, 19, 41, 2, 0, time.UTC),
Vertical: "demo-stack",
Task: task.Task{ID: "demo-1", Subject: "MVP demo", Prompt: "tell me about yourself", Class: "primary", Source: "demo"},
Class: "primary",
Tier: "mopac-primary",
Model: "glm-5.3",
PromptTokens: 12,
CompletionTokens: 340,
TotalTokens: 352,
Rounds: 1,
StopReason: "complete",
Duration: 2 * time.Second,
Content: "I am GLM, a large language model.",
}
path, err := Write(dir, r)
if err != nil {
t.Fatalf("Write: %v", err)
}
want := filepath.Join(dir, "REPORT-demo-stack-demo-1-20260828-194102.md")
if path != want {
t.Errorf("path = %s, want %s", path, want)
}
body, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
s := string(body)
for _, want := range []string{
"model: glm-5.3 (tier mopac-primary, class primary)",
"usage: prompt=12 completion=340 total=352 tokens",
"rounds=1",
"## Result",
"I am GLM, a large language model.",
} {
if !strings.Contains(s, want) {
t.Errorf("REPORT missing %q", want)
}
}
latest, err := os.ReadFile(filepath.Join(dir, "REPORT-latest.md"))
if err != nil || len(latest) != len(body) {
t.Errorf("REPORT-latest.md missing or stale (err=%v)", err)
}
// No .tmp litter.
entries, _ := os.ReadDir(dir)
for _, e := range entries {
if strings.HasSuffix(e.Name(), ".tmp") {
t.Errorf("tmp file left behind: %s", e.Name())
}
}
}
func TestSanitize(t *testing.T) {
if got := sanitize("a/b c"); got != "a-b-c" {
t.Errorf("sanitize = %q", got)
}
}
func TestEmptyContentPlaceholder(t *testing.T) {
r := Report{Time: time.Now(), Vertical: "v", Task: task.Task{ID: "x"}, Content: ""}
if !strings.Contains(r.Render(), "(no content produced)") {
t.Errorf("empty content should render a placeholder")
}
}