Skip to content

Commit 2665ada

Browse files
committed
ROADMAP ultraworkers#142: claw init --output-format json emits unstructured message string instead of created/skipped fields
1 parent 21b377d commit 2665ada

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

ROADMAP.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,3 +5302,70 @@ Usage:
53025302
**Blocker.** None. Scoped to CLI parser + help text. ~50 lines + test.
53035303

53045304
**Source.** Jobdori dogfood 2026-04-21 16:59 KST on main HEAD `27ffd75`. Joins **CLI/REPL parity** cluster (§7.1) and **discoverability** cluster (#108 did-you-mean, #127 --json on diagnostic verbs, #139 worker concept unactionable). Session tally: ROADMAP #141.
5305+
5306+
## Pinpoint #142. `claw init --output-format json` dumps human text into `message` — no structured fields for created/skipped files
5307+
5308+
**Gap.** `claw init --output-format json` emits a valid JSON envelope, but the payload is entirely a human-formatted multi-line text block packed into `message`. There are no structured fields to tell a claw script which files were created, which were skipped, or what the project path was.
5309+
5310+
**Verified on main HEAD `21b377d` 2026-04-21 17:34 KST.**
5311+
5312+
**Actual output (fresh directory, everything created):**
5313+
```json
5314+
{
5315+
"kind": "init",
5316+
"message": "Init\n Project /private/tmp/cd-1730b\n .claw/ created\n .claw.json created\n .gitignore created\n CLAUDE.md created\n Next step Review and tailor the generated guidance"
5317+
}
5318+
```
5319+
5320+
**Idempotent second call (everything skipped):**
5321+
```json
5322+
{
5323+
"kind": "init",
5324+
"message": "Init\n Project /private/tmp/cd-1730b\n .claw/ skipped (already exists)\n .claw.json skipped (already exists)\n .gitignore skipped (already exists)\n CLAUDE.md skipped (already exists)\n Next step Review and tailor the generated guidance"
5325+
}
5326+
```
5327+
5328+
**Compare `claw status --output-format json` (the model):**
5329+
```json
5330+
{
5331+
"kind": "status",
5332+
"model": "claude-opus-4-6",
5333+
"permission_mode": "danger-full-access",
5334+
"sandbox": { "active": false, "enabled": true, "fallback_reason": "...", ... },
5335+
"usage": { "cumulative_input": 0, "messages": 0, "turns": 0, ... },
5336+
"workspace": { "changed_files": 0, ... }
5337+
}
5338+
```
5339+
5340+
**Why this is a clawability gap.**
5341+
1. **Substring matching required**: to tell whether `.claw/` was created vs skipped, a claw has to grep the `message` string for `"created"` or `"skipped (already exists)"`. Not a contract — human-language fragility.
5342+
2. **No programmatic idempotency signal**: CI/orchestration cannot easily tell "first run produced new files" from "second run was no-op". Both paths end up with `kind: init` and a free-form message.
5343+
3. **Inconsistent with `status`/`sandbox`/`doctor`**: those subcommands have first-class structured JSON. `init` does not. Product contract asymmetry.
5344+
4. **Path isn't a field**: the project path is embedded in the same string. No `project_path` key.
5345+
5. **Joins JSON-output cluster** (#90, #91, #92, #127, #130, #136): every one of those was a JSON contract shortfall where the command technically emitted JSON but did not emit *useful* JSON.
5346+
5347+
**Fix shape (~40 lines).**
5348+
Add structured fields alongside `message` (keep `message` for backward compat):
5349+
```json
5350+
{
5351+
"kind": "init",
5352+
"project_path": "/private/tmp/cd-1730b",
5353+
"created": [".claw", ".claw.json", ".gitignore", "CLAUDE.md"],
5354+
"skipped": [],
5355+
"next_step": "Review and tailor the generated guidance",
5356+
"message": "Init\n Project..."
5357+
}
5358+
```
5359+
5360+
On idempotent call: `created: []`, `skipped: [".claw", ".claw.json", ...]`.
5361+
5362+
**Acceptance.**
5363+
- `claw init --output-format json` has `created`, `skipped`, `project_path`, `next_step` top-level fields
5364+
- `created.len() + skipped.len() == 4` on standard init
5365+
- Idempotent call has empty `created`
5366+
- Existing `message` field preserved for text consumers (deprecation path only if needed)
5367+
- Regression test: JSON schema assertions for both fresh + idempotent cases
5368+
5369+
**Blocker.** None. Scoped to `init` subcommand JSON serializer. ~40 lines.
5370+
5371+
**Source.** Jobdori dogfood 2026-04-21 17:34 KST on main HEAD `21b377d`. Joins **JSON output completeness** cluster (#90/#91/#92/#127/#130/#136). Session tally: ROADMAP #142.

0 commit comments

Comments
 (0)