Files
multica/server/internal/daemon/execenv/observability.go
Eve 4600e725e3 feat(daemon): log runtime brief mode + path on every task start (MUL-3560)
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>
2026-06-24 14:29:04 +08:00

34 lines
1.4 KiB
Go

package execenv
// RuntimeConfigPath returns the absolute path to the runtime-brief file
// that InjectRuntimeConfig writes for the given provider, or "" when the
// provider has no file-based config target.
//
// Daemon code uses this to log "where did the brief land" alongside the
// rendered char count, so an operator can `cat` the exact file to confirm
// which template a given task was given. The private runtimeConfigPath is
// the implementation; this is a stable export so the daemon does not have
// to thread the provider→filename table in a second place.
func RuntimeConfigPath(workDir, provider string) string {
return runtimeConfigPath(workDir, provider)
}
// BriefMode returns the human-readable label of the brief path that
// InjectRuntimeConfig would render right now: "slim" when the
// `runtime_brief_slim` feature flag evaluates to on, "legacy" otherwise.
//
// This is intended for daemon observability only — the brief mode is
// always derivable from the flag service, but a structured label keeps log
// queries cheap and lets dashboards filter by mode without re-implementing
// the toggle logic.
//
// Nil-safe by way of useSlimBrief (which falls through Service.IsEnabled's
// nil-safe path), so a daemon that forgot to wire SetFeatureFlags still
// produces a meaningful label ("legacy") rather than panicking.
func BriefMode() string {
if useSlimBrief() {
return "slim"
}
return "legacy"
}