Compare commits

..

1 Commits

Author SHA1 Message Date
YeonGyu-Kim
3b5bafc847 docs(roadmap): add #332 — doctor json missing top-level status field 2026-04-29 22:04:07 +09:00

View File

@@ -6262,8 +6262,4 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
323. **`status --output-format json` reports `session.session = "live-repl"` while simultaneously reporting `session_lifecycle.kind = "saved_only"` — contradictory session identity in a single status snapshot** — dogfooded 2026-04-29 by Jobdori on current main (`804d96b`). Running `claw status --output-format json` from an active REPL-style invocation produced `"session": "live-repl"` in the `workspace` block and `"session_lifecycle": {"kind": "saved_only", "pane_id": null, ...}` in the same object. Those two fields carry contradictory claims: `"live-repl"` asserts there is an active interactive session, while `"saved_only"` asserts there is no live tmux pane hosting the session — the session exists only as a saved artifact. A downstream claw reading this snapshot cannot tell which claim to trust: is this a running session whose pane is undetectable, or a saved-only session that the `session` field is misclassifying? Root cause: `"live-repl"` is a fallback sentinel emitted by `main.rs:6070` when `context.session_path` is `None`, while `session_lifecycle` is computed independently by `classify_session_lifecycle_for()` from tmux pane discovery; the two fields share no common source and can diverge. **Required fix shape:** (a) derive both `session.session` and `session_lifecycle.kind` from the same lifecycle classification result so they cannot diverge; (b) replace the `"live-repl"` free-form sentinel with a structured `session_kind` field (`live_repl`, `saved`, `resume`, etc.) that carries the same type vocabulary as `session_lifecycle.kind`; (c) when `session_lifecycle.kind = "saved_only"`, never emit `"session": "live-repl"` (or vice versa); (d) add a regression test proving `status --output-format json` never emits `session.kind = "live_repl"` and `session_lifecycle.kind = "saved_only"` simultaneously. **Why this matters:** `status --output-format json` is the machine-readable truth surface for session state; if two fields in the same snapshot contradict each other, every lane, monitor, and orchestrator has to pick a winner instead of reading a coherent state. Source: Jobdori live dogfood on mengmotaHost, claw-code `804d96b`, 2026-04-29.
324. **Stale local debug binaries can impersonate the current workspace because version/status/doctor do not compare embedded build provenance to repo HEAD** — dogfooded 2026-04-29 on current `origin/main` / workspace HEAD `e7074f47` after PR #2838. The working tree was at `e7074f47`, but running `./rust/target/debug/claw version --output-format json` reported embedded `git_sha` `1f901988`. `status` and `doctor` remained green and exposed no warning that the executable under test was stale relative to the workspace HEAD, nor any structured build-provenance freshness signal that downstream claws could use to decide whether the observed behavior came from the checked-out code or an older debug artifact. This is a repo-identity opacity gap: the JSON truth surfaces can look authoritative while actually describing a different binary lineage than the source tree being dogfooded. **Required fix shape:** (a) compare the embedded build `git_sha` / build date with the current workspace git HEAD and dirty state when the binary can discover a containing worktree; (b) expose redaction-safe structured fields in `version --output-format json`, `status --output-format json`, and `doctor --output-format json`, including `binary_provenance`, `workspace_head`, and `stale_binary` (with enough reason/detail to distinguish clean match, dirty workspace, unknown workspace, and definite stale SHA mismatch); (c) warn in human/text mode when executing a stale local debug binary such as `./rust/target/debug/claw` so dogfooders do not trust old behavior as current-main evidence; (d) avoid leaking secrets or absolute sensitive paths beyond the existing workspace-identification policy; (e) add regression/fixture coverage for matching HEAD, dirty workspace, no-worktree/unknown provenance, and stale embedded SHA cases. **Why this matters:** status/doctor/version are supposed to be the machine-readable basis for dogfood truth. If a stale binary can report a different `git_sha` than the checked-out repo without any freshness warning, claws can file or verify bugs against the wrong code and waste cycles chasing already-fixed or not-yet-built behavior. Source: gaebal-gajae dogfood follow-up from current main `e7074f47` after PR #2838; observed `./rust/target/debug/claw version --output-format json` reporting `git_sha` `1f901988` with no stale-binary-vs-workspace-HEAD warning.
325. **`help --output-format json` returns valid JSON but hides the actual help schema inside one prose `message` string** — dogfooded 2026-04-29 on current `origin/main` / workspace HEAD `d607ff36`. Running `./rust/target/debug/claw help --output-format json` produces parseable JSON, but the object only exposes top-level keys like `kind` and `message`; all command names, global flags, slash-command metadata, aliases, resume-safety, output-format support, auth/preflight notes, and descriptions are flattened into one human-oriented prose blob. That technically satisfies “valid JSON” while still forcing automation to scrape the same help text humans read, making `/issue`, `/help`, and resume-safety contracts opaque to claws. **Required fix shape:** (a) keep `message` as the compact human-rendered help summary, but add a documented structured schema with `schema` / `schema_version` fields; (b) expose first-class arrays/objects such as `commands[]`, `options[]`, and `slash_commands[]` with stable fields including `name`, `aliases`, `description`, `args`, `output_formats_supported`, `resume_safe`, `interactive_only`, and `creates_external_side_effects`; (c) include auth and creation preflight metadata where relevant, especially for GitHub/issue flows (`auth_preflight`, `creation_unavailable`, `gh_cli_authenticated`, `github_token_present`, or equivalent non-secret state); (d) make `/issue`, `/help`, aliases, and resume-dispatch safety machine-readable from the JSON payload instead of recoverable only by parsing prose markers; (e) add regression coverage proving `help --output-format json` is valid JSON and that `/issue`, `/help`, resume-safe vs interactive-only slash commands, aliases, descriptions, supported output formats, and side-effect/auth-preflight fields are present and internally consistent. **Why this matters:** help JSON is the discoverability surface automation uses before invoking commands. If it is just prose wrapped in JSON, claws cannot safely decide whether a command can run non-interactively, resume from a saved session, create external GitHub side effects, or requires auth/preflight without brittle text scraping. Source: gaebal-gajae dogfood follow-up from current main `d607ff36`; observed `./rust/target/debug/claw help --output-format json` returning valid JSON with only `{kind,message}` at the top level while the actionable command schema remained buried in `message`.
336. **`/session` and `/session list` have inconsistent resume-mode support: bare `/session` returns `"unsupported resumed slash command"` while `/session list` works in `--resume` — yet `/help` JSON exposes no per-subcommand resume flag** — dogfooded 2026-04-29 by Jobdori on current main (`b90875f`). Running `claw --output-format json --resume latest /session` returns `{"command":"/session","error":"unsupported resumed slash command","type":"error"}`. Running `claw --output-format json --resume latest /session list` returns a valid session list JSON. The two forms share the same slash command name but have divergent resume-mode contracts with no documentation path to learn which subcommands are resume-safe. Additionally, the error JSON uses `"type"` instead of `"kind"` — violating the vocabulary used by all other JSON outputs (`kind=status`, `kind=version`, `kind=doctor`, etc.), making error responses structurally inconsistent with success responses. **Required fix shape:** (a) document per-subcommand resume support in `/help` JSON output — each command entry should carry `"resume_subcommands": ["list"]` or similar so callers know which subcommands work in `--resume` mode; (b) align the error JSON vocabulary: replace `"type"` with `"kind"` and use `kind=error` consistently; (c) either mark `/session` bare as `[resume]`-safe (showing the list by default) or emit a typed error that names the resume-safe subcommands; (d) add regression coverage proving that all error JSON responses use `"kind"` not `"type"`, and that `/session list` resume-mode support is stable. **Why this matters:** callers using `/session` in automation cannot discover from `/help` or error text which subcommands work in resume-mode; the `type` vs `kind` vocabulary mismatch in errors also breaks generic JSON-kind dispatchers that expect a stable `kind` field. Source: Jobdori live dogfood on mengmotaHost, claw-code `b90875f`, 2026-04-29.
332. **`doctor --output-format json` has no top-level `status` field, breaking the `result["status"] == "ok"` check pattern that works for all other JSON commands** — dogfooded 2026-04-29 by Jobdori on current main (`e7074f4`). Running `claw doctor --output-format json | python3 -c "import sys,json; print(json.load(sys.stdin).get('status'))"` prints `None`. The doctor JSON uses `has_failures` (bool) + `summary: {failures, ok, total, warnings}` to express aggregate health, while every other JSON command (`status`, `sandbox`, `stats`, `cost`, etc.) uses a top-level `"status": "ok"|"warn"|"error"` field. A downstream lane checking `result.get("status") == "ok"` will silently misread a doctor output with 2 warnings as if no status were present, instead of getting `"warn"`. **Required fix shape:** (a) add a top-level `"status": "ok" | "warn" | "error"` field to doctor JSON output derived from the same `has_failures`/warning-count logic already present; (b) ensure the field is always present and uses the same vocabulary as other JSON commands; (c) keep `has_failures` and `summary` for backward compat but document `status` as the canonical machine-readable aggregate verdict; (d) add regression coverage proving `claw doctor --output-format json` always includes a non-null `"status"` field. **Why this matters:** `status` is the idiomatic machine-readable health verdict in claw's JSON surface; when `doctor` skips it, automation layers that unify health checks across commands (`doctor` + `status` + `sandbox`) must special-case doctor or silently miss warnings. Source: Jobdori live dogfood on mengmotaHost, claw-code `e7074f4`, 2026-04-29.