mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-14 13:49:18 +02:00
Yushen asked how to confirm which prompt template a task is given —
slim or legacy — once staging starts opting into `runtime_brief_slim`.
Two verification paths now exist:
1. File inspection (works today): the rendered brief lives in
{workDir}/CLAUDE.md (claude/codebuddy), AGENTS.md (codex /
copilot / opencode / openclaw / hermes / pi / cursor / kimi /
kiro / qoder / antigravity), or GEMINI.md (gemini). Operators
can `cat` the file to see the exact bytes the agent will load.
2. Structured daemon log (this PR): the daemon now logs one
`execenv: runtime brief written` line per task start, carrying
provider, brief_path (so you don't have to guess the filename),
brief_chars (rendered rune count), and brief_mode (`slim` or
`legacy`). Dashboards / log queries can filter by brief_mode to
confirm the staging rollout is actually hitting the slim path
without grepping every workdir.
What's in this PR:
- `internal/daemon/execenv/observability.go` (new): public
`RuntimeConfigPath(workDir, provider) string` (thin wrapper
around the private mapping) and `BriefMode() string` ("slim" or
"legacy", nil-safe via the feature flag service).
- `internal/daemon/daemon.go`: one `taskLog.Info(...)` after
`InjectRuntimeConfig` returns successfully. Failure path
unchanged (still warns).
- `internal/daemon/execenv/observability_test.go` (new):
TestRuntimeConfigPath pins the full 15-provider mapping;
TestBriefMode verifies the label flips with the flag and that
a nil service returns "legacy" rather than panicking.
Sample log line (staging, flag on, codex provider):
INFO execenv: runtime brief written task=abc12345
provider=codex
brief_path=/var/multica/workspaces/.../task-abc/workdir/AGENTS.md
brief_chars=11868
brief_mode=slim
Same line on prod (flag off):
INFO execenv: runtime brief written task=abc12345
provider=codex
brief_path=/var/multica/workspaces/.../task-abc/workdir/AGENTS.md
brief_chars=19567
brief_mode=legacy
Verification:
- go vet ./internal/daemon/... ok
- go test ./internal/daemon/... ok
- TestRuntimeConfigPath pins all 15 providers (including the
fall-through to "" for unknown).
- TestBriefMode verifies both flag states + nil-safety.
Risk: very low. Adds one INFO log per task start (already a low-
frequency event by daemon standards), no behaviour change anywhere
in the brief generation or task execution path.
Co-authored-by: multica-agent <github@multica.ai>
71 lines
2.2 KiB
Go
71 lines
2.2 KiB
Go
package execenv
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/multica-ai/multica/server/pkg/featureflag"
|
|
)
|
|
|
|
// TestRuntimeConfigPath pins the provider→filename mapping the daemon
|
|
// log line relies on. If the mapping ever changes, the test catches it
|
|
// — operators expect to know exactly which file to `cat`.
|
|
func TestRuntimeConfigPath(t *testing.T) {
|
|
t.Parallel()
|
|
cases := []struct {
|
|
provider string
|
|
want string
|
|
}{
|
|
{"claude", "/work/CLAUDE.md"},
|
|
{"codebuddy", "/work/CLAUDE.md"},
|
|
{"codex", "/work/AGENTS.md"},
|
|
{"copilot", "/work/AGENTS.md"},
|
|
{"opencode", "/work/AGENTS.md"},
|
|
{"openclaw", "/work/AGENTS.md"},
|
|
{"hermes", "/work/AGENTS.md"},
|
|
{"pi", "/work/AGENTS.md"},
|
|
{"cursor", "/work/AGENTS.md"},
|
|
{"kimi", "/work/AGENTS.md"},
|
|
{"kiro", "/work/AGENTS.md"},
|
|
{"qoder", "/work/AGENTS.md"},
|
|
{"antigravity", "/work/AGENTS.md"},
|
|
{"gemini", "/work/GEMINI.md"},
|
|
{"totally-unknown", ""},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := RuntimeConfigPath("/work", tc.provider); got != tc.want {
|
|
t.Errorf("RuntimeConfigPath(/work, %q) = %q, want %q", tc.provider, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestBriefMode verifies the label flips with the feature flag. Nil-safe
|
|
// path returns "legacy" so a daemon that forgot to wire SetFeatureFlags
|
|
// emits a meaningful label, not panics.
|
|
func TestBriefMode(t *testing.T) {
|
|
// Not t.Parallel-safe because we mutate the package-level flag pointer.
|
|
saved := runtimeFlags.Load()
|
|
t.Cleanup(func() { runtimeFlags.Store(saved) })
|
|
|
|
// Nil service → legacy.
|
|
runtimeFlags.Store(nil)
|
|
if got := BriefMode(); got != "legacy" {
|
|
t.Errorf("BriefMode with nil service = %q, want %q", got, "legacy")
|
|
}
|
|
|
|
// Flag off → legacy.
|
|
off := featureflag.NewStaticProvider()
|
|
off.Set(runtimeBriefSlimFlag, featureflag.Rule{Default: false})
|
|
runtimeFlags.Store(featureflag.NewService(off))
|
|
if got := BriefMode(); got != "legacy" {
|
|
t.Errorf("BriefMode with flag off = %q, want %q", got, "legacy")
|
|
}
|
|
|
|
// Flag on → slim.
|
|
on := featureflag.NewStaticProvider()
|
|
on.Set(runtimeBriefSlimFlag, featureflag.Rule{Default: true})
|
|
runtimeFlags.Store(featureflag.NewService(on))
|
|
if got := BriefMode(); got != "slim" {
|
|
t.Errorf("BriefMode with flag on = %q, want %q", got, "slim")
|
|
}
|
|
}
|