Skip to content

Commit 0cdfd06

Browse files
Unify provider progress semantics and debug traces
1 parent 17d18ac commit 0cdfd06

4 files changed

Lines changed: 707 additions & 203 deletions

File tree

contrib/ARCHITECTURE.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ Variable rules:
9696
6. Clear prior run protocol files in `.clawform/` and write runtime variables file (`.clawform/agent_variables.json`) when variables are present.
9797
7. Build runtime prompt; in `workspace` and `auto` modes include explicit verdict-gate rules for sandbox-vs-program blocking.
9898
8. Run provider in the current workspace (no temp workspace copy).
99-
9. Normalize provider-native events into shared progress categories, stream them to terminal, and during the run write session `commands/*` and `messages/*`.
99+
9. Normalize provider-native events into shared progress categories, stream them to terminal, and during the run write session `commands/*` and `messages/*`. In debug mode, also write session `events.ndjson`.
100100
10. In `auto` mode, allow at most one retry in `full-access` mode only when current-run `.clawform/agent_result.json` reports `status=partial|failure` and `reason=sandbox_blocked` (no stdout/stderr heuristic fallback).
101101
11. Read agent status from `.clawform/agent_result.json` (required) and validate strict status/reason schema.
102102
12. Collect reported changed files from `.clawform/agent_outputs.json` when that file exists and was updated in this run.
@@ -106,9 +106,10 @@ Variable rules:
106106
## 4.1 Progress Rendering Semantics
107107

108108
- In an interactive TTY, rich progress keeps a spinner plus a live `running` or `running: <activity>` status line.
109+
- The run-start line includes the session id, execution mode, and a compact `provider:model` suffix, for example `🧵 <session> | workspace | codex:gpt-5-codex`.
109110
- `running` means the provider run is still alive. It is a liveness indicator, not the same thing as reasoning text.
110111
- The live activity suffix is derived from the highest-priority active provider item, for example `search ...`, `fetch ...`, `use ...`, `edit ...`, or `update plan`.
111-
- Completed progress lines are normalized across Claude and Codex into shared categories such as reasoning (`💭`), assistant text (`💬`), search (`🔎`), fetch (`🌐`), command (``), file change (``), plan update (`🗒️`), generic tool (`🔧`), and unknown provider event (`📦`).
112+
- Completed progress lines are normalized across Claude and Codex into shared categories such as reasoning (`💭`), assistant text (`💬`), search (`🔎`), fetch (`🌐`), command (``), file change (`✏️`), plan update (`update plan | ...`), generic tool (`🔧`), and unknown provider event (`📦`).
112113
- In `plain` mode, Clawform prints stable progress lines without the interactive spinner/status renderer.
113114
- Unknown tool-like and non-tool provider items are rendered through generic fallbacks instead of being silently dropped.
114115
- Interrupting with `Ctrl+C` should surface cancellation rather than a raw provider stdout/stderr dump.
@@ -138,6 +139,7 @@ During the current run:
138139

139140
- Write `<protocol_root>/agent_variables.json` (when variables exist); the agent reads this file for resolved `${{ var.NAME }}` values.
140141
- Write `<session_root>/commands/*` and `<session_root>/messages/*` as per-session execution artifacts.
142+
- In debug mode, also write `<session_root>/events.ndjson` as a per-session event trace artifact.
141143
- Read `<protocol_root>/agent_result.json`, `<protocol_root>/agent_outputs.json`, and optional `<protocol_root>/agent_output.md` at run end to determine status, changed files, and summary.
142144

143145
On the next run of the same program:
@@ -159,6 +161,7 @@ For audit/debug visibility:
159161
| `<protocol_root>/agent_result.json` | Workspace-global scratch file for the currently running apply (overwritten on each apply) | Receive final structured run verdict (`status`, optional `reason`, `message`) where `reason` is strict enum (`sandbox_blocked` or `program_blocked`) | Read by Clawform at run end; in sandbox auto mode also used as the only retry signal source, only if file mtime is from this run |
160162
| `<protocol_root>/agent_outputs.json` | Workspace-global scratch file for the currently running apply (overwritten on each apply) | Receive changed-file list from the agent | Read by Clawform at run end for file summary/history, only if file mtime is from this run |
161163
| `<protocol_root>/agent_output.md` | Workspace-global scratch file for the currently running apply (optional; overwritten on each apply) | Receive agent-written summary text | Read by Clawform at run end; then copied into session `output.md` |
164+
| `<session_root>/events.ndjson` | Per-session (`<program_id>/<session_id>`), debug mode only | Preserve normalized provider events plus raw source lines for this session | Used for audit/debug flows and event-based validation |
162165
| `<session_root>/commands/*.txt` | Per-session (`<program_id>/<session_id>`) | Preserve command output artifacts for this session | Used for progress drilldown and debugging |
163166
| `<session_root>/messages/*.md` | Per-session (`<program_id>/<session_id>`) | Preserve assistant/message artifacts for this session | Used for progress drilldown and fallback summary source |
164167
| `<session_root>/output.md` | Per-session (`<program_id>/<session_id>`) | Store stable summary artifact for this session | Used on next run of same `program_id` for preview/prompt reference |
@@ -169,7 +172,7 @@ For audit/debug visibility:
169172

170173
Compatibility behavior:
171174

172-
- No read fallback is used for `agent_summary.md` or `events.ndjson`.
175+
- No read fallback is used for `agent_summary.md`.
173176
- Current apply reads only the current protocol files documented in this section.
174177
- Sandbox auto-retry does not parse provider stdout/stderr for sandbox heuristics; it only trusts current-run `agent_result.json`.
175178

@@ -186,7 +189,7 @@ Current apply does not persist:
186189
- `prompt.md`
187190
- `plan.json`
188191
- provider stdout/stderr artifact logs
189-
- canonical `events.ndjson` for new sessions
192+
- `events.ndjson` on non-debug runs
190193

191194
## 5.4 Agent Result Protocol Rules
192195

contrib/DEVELOPMENT.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,22 @@ Interactive progress UI is enabled automatically only when stdin/stdout are atta
108108
Current progress semantics:
109109

110110
- Rich mode keeps a spinner plus a live `running` or `running: <activity>` status line.
111+
- The run-start line includes the session id, execution mode, and a compact `provider:model` suffix such as `🧵 <session> | workspace | claude:sonnet`.
111112
- `running` is a liveness indicator. It does not mean the model is explicitly emitting reasoning.
112113
- Plain mode prints stable progress lines without the interactive spinner/status renderer.
113-
- Completed provider items are normalized across Claude and Codex into categories such as `💭`, `💬`, `🔎`, `🌐`, ``, ``, `🗒️`, `🔧`, and `📦`.
114+
- Completed provider items are normalized across Claude and Codex into categories such as `💭`, `💬`, `🔎`, `🌐`, ``, `✏️`, `update plan | ...`, `🔧`, and `📦`.
114115
- Unknown provider item types still surface through `🔧` / `📦` fallbacks instead of being silently dropped.
115116
- `Ctrl+C` should report cancellation rather than dumping raw provider stdout/stderr.
117+
- Per-session `events.ndjson` traces are written only in debug mode.
116118

117119
Show provider raw logs (debug mode):
118120

119121
```bash
120122
cargo run -p clawform -- apply -f examples/smoke.md --debug
121123
```
122124

125+
That debug run will also persist `.clawform/programs/<program_id>/sessions/<session_id>/events.ndjson` for postmortem event inspection.
126+
123127
Disable progress rendering entirely:
124128

125129
```bash

crates/clawform-core/src/apply.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,11 @@ fn execute_apply<R: ProviderRunner + ?Sized>(
416416
let plan_artifact = None;
417417
let provider_stdout_artifact = None;
418418
let provider_stderr_artifact = None;
419-
let events_artifact = None;
419+
let events_artifact = events_artifact_rel_path(
420+
&request.workspace_root,
421+
&context.program_key,
422+
&success_session_id,
423+
);
420424
let agent_reported_files =
421425
read_agent_reported_files(&request.workspace_root).unwrap_or_default();
422426
let agent_human_summary_explicit = read_agent_human_summary(&request.workspace_root)
@@ -2097,11 +2101,6 @@ fn print_plan_preview(plan: &SharedPlanData, debug: bool, workspace_root: &Path)
20972101
plan.program_id,
20982102
plan.program_file
20992103
);
2100-
println!(
2101-
" {} {}",
2102-
color_dim("model:", use_color),
2103-
plan.model.as_deref().unwrap_or("<provider default>")
2104-
);
21052104
if let Some(last) = &plan.last_session {
21062105
if let Some(session) = last.session_id.as_deref() {
21072106
println!(
@@ -2226,6 +2225,22 @@ fn output_artifact_rel_path(workspace_root: &Path, program_id: &str, session_id:
22262225
.unwrap_or_else(|_| to_slash_path(&abs))
22272226
}
22282227

2228+
fn events_artifact_rel_path(
2229+
workspace_root: &Path,
2230+
program_id: &str,
2231+
session_id: &str,
2232+
) -> Option<String> {
2233+
let abs = program_session_dir(workspace_root, program_id, session_id).join("events.ndjson");
2234+
if !abs.exists() {
2235+
return None;
2236+
}
2237+
Some(
2238+
abs.strip_prefix(workspace_root)
2239+
.map(to_slash_path)
2240+
.unwrap_or_else(|_| to_slash_path(&abs)),
2241+
)
2242+
}
2243+
22292244
fn format_msg_link(workspace_root: &Path, rel_path: &str, use_color: bool) -> String {
22302245
let rendered = if !supports_terminal_hyperlinks() {
22312246
"msg".to_string()

0 commit comments

Comments
 (0)