1008 Commits

Author SHA1 Message Date
YeonGyu-Kim
41c87309f3 roadmap: cycle #74 checkpoint — rebase blocker identified
Fresh dogfood found no new pinpoints. All core verbs working correctly.

Blocker: 8 remaining review-ready branches on origin have conflicts with
cycle #72's 4 merges. Root cause: remote branches predated the merge chain.

Example: feat/jobdori-127-verb-suffix-flags rebase fails on commit 3/3
because cycle #72 added 15+ new LocalHelpTopic variants.

Recommend: coordinate with branch authors to rebase against new main.
Cycle #74 will post integration checkpoint + queue status.
2026-04-23 04:17:54 +09:00
YeonGyu-Kim
a02527826e roadmap: #163 closed as already-fixed — #130e-A (merged cycle #72) handled help --help
Backlog-truthfulness (cycle #60) validated: fresh dogfood on current main confirmed
#163 was closed by cycle #72's help-parity chain merge. Zero duplicate work.

Cleanup: removed /tmp/jobdori-163 worktree and fix/jobdori-163-help-help-selfref branch.
2026-04-23 04:07:37 +09:00
YeonGyu-Kim
a52a361e16 roadmap: cycle #72 — 4 merges landed, 9 branches integrated via MERGE_CHECKLIST runbook 2026-04-23 04:04:57 +09:00
YeonGyu-Kim
d5373ac5d6 merge: fix/jobdori-161-worktree-git-sha — diagnostic-strictness family
Fix: resolve actual HEAD path in git worktrees for correct Git SHA in build metadata.
In worktrees, .git is a pointer file not a directory, so cargo's rerun-if-changed=.git/HEAD never triggers.

Per MERGE_CHECKLIST.md Cluster 2 (P1 Diagnostic-strictness, isolated):
- 25 lines in build.rs only (no crate-level conflicts)
- Verified: build → commit → rebuild → SHA updates correctly

Diagnostic-strictness family member (joins #122/#122b).

Applied: execution artifact runbook. Cycle #72 integration.
2026-04-23 04:04:17 +09:00
YeonGyu-Kim
a6f4e0d8d1 merge: feat/jobdori-130e-surface-help — help-parity cluster + #251 session-dispatch
Contains linear chain of 6 fixes:
- #251: intercept session-management verbs at top-level parser (dc274a0)
- #130b: enrich filesystem I/O errors with operation + path context (d49a75c)
- #130c: accept --help / -h in claw diff arm (83f744a)
- #130d: accept --help / -h in claw config arm, route to help topic (19638a0)
- #130e-A: route help/submit/resume --help to help topics before credential check (0ca0344)
- #130e-B: route plugins/prompt --help to dedicated help topics (9dd7e79)

Per MERGE_CHECKLIST.md:
- Cluster 1 (Typed-error): #251 (session-dispatch)
- Cluster 3 (Help-parity): #130b, #130c, #130d, #130e-A/B

All changes are in rust/crates/rusty-claude-cli/src/main.rs (dispatch/help routing).
No test regressions expected (fixes add new guards, don't modify existing paths).

Applied: execution artifact runbook. Cycle #72 integration.
2026-04-23 04:03:40 +09:00
YeonGyu-Kim
378b9bf533 merge: docs/jobdori-162-usage-verb-parity — document dump-manifests/bootstrap-plan/acp/export
Completes discoverability chain for 4 verbs:
- dump-manifests — upstream manifest export
- bootstrap-plan — startup component graph
- acp — Zed editor integration status (tracking #76)
- export — session transcript export

Per MERGE_CHECKLIST.md Cluster 6 (P3 Doc-truthfulness):
- Diff: +87 lines in USAGE.md (doc-only)
- Zero code risk
- Parity audit: 12/12 verbs documented (was 8/12)

Applied: execution artifact runbook. Cycle #72 integration.
2026-04-23 04:02:47 +09:00
YeonGyu-Kim
66765ea96d merge: docs/parity-update-2026-04-23 — refresh PARITY.md stats for 2026-04-23
Growth since 2026-04-03:
- Rust LOC: 48,599 → 80,789 (+66%)
- Test LOC: 2,568 → 4,533 (+76%)
- Commits: 292 → 979 (+235%)

Per MERGE_CHECKLIST.md Cluster 6 (P3 Doc-truthfulness, low-risk):
- Diff: 4 lines in PARITY.md only
- Zero code risk
- Merge-ready

Applied: execution artifact runbook. Cycle #72 integration.
2026-04-23 04:02:38 +09:00
YeonGyu-Kim
499d84c04a roadmap: #163 filed — claw help --help emits missing_credentials instead of help topic (help-parity family) 2026-04-23 04:01:24 +09:00
YeonGyu-Kim
6d1c24f9ee roadmap: doctrine refinement — three-tier artifact classification (doc → support → execution) per cycle #70 framing 2026-04-23 03:56:48 +09:00
YeonGyu-Kim
fb1a59e088 docs: add MERGE_CHECKLIST.md — integration support artifact for queue merge sequencing
Provides:
- Recommended merge order (P0 → P1 → P2 → P3 by cluster)
- Per-cluster merge prerequisites and validation steps
- Conflict risk assessment (Cluster 2 #122/#122b have same edit locus)
- Post-merge validation checklist (build + test + dogfood)
- Timeline estimate (~60 min for full 17-branch queue)

Addresses the final integration step: once branches are reviewed, knowing
the safe merge order matters. This artifact pre-answers that question.

Applied doctrine: integration-support artifacts (cycle #64) reduce reviewer
friction. At 17-branch saturation, a merge-safe checklist is first-class work.

Relates to cycle #70 integration throughput initiative.
2026-04-23 03:55:38 +09:00
YeonGyu-Kim
0527dd608d roadmap: #161 closed — shipped on fix/jobdori-161-worktree-git-sha (cycle #69) 2026-04-23 03:46:37 +09:00
YeonGyu-Kim
c5b6fa5be3 fix(#161): resolve actual HEAD path in git worktrees for correct Git SHA in build metadata
Problem: In git worktrees, .git is a pointer file (not a directory), so cargo's
rerun-if-changed=.git/HEAD never triggers when commits are made. This causes
claw version to report a stale SHA after new commits.

Solution: Add resolve_git_head_path() helper that detects worktree mode:
- If .git is a file: parse gitdir pointer, watch <gitdir>/HEAD
- If .git is a directory: watch .git/HEAD (regular repo)

This ensures build.rs invalidates on each commit, making version output truthful.

Verification: Binary built in worktree now reports correct SHA after commits
(before: stale, after: current HEAD).

Relates to ROADMAP #161 (filed cycle #65, implemented cycle #69).
Diagnostic-strictness family member.
Diff: 21 lines added (resolve_git_head_path + conditional rerun-if-changed).
2026-04-23 03:45:59 +09:00
YeonGyu-Kim
d64c7144ff roadmap: doctrine extension — CLI discoverability chain completion as doctrine (from #162 closure framing) 2026-04-23 03:40:43 +09:00
YeonGyu-Kim
2a82cf2856 roadmap: #162 closed — shipped on docs/jobdori-162-usage-verb-parity (cycle #68) 2026-04-23 03:39:36 +09:00
YeonGyu-Kim
48da1904e0 docs(#162): add USAGE.md sections for dump-manifests, bootstrap-plan, acp, export
Parity audit (cycle #67) found 4 verbs were in claw --help but absent from USAGE.md:
- dump-manifests: upstream manifest export for parity work
- bootstrap-plan: startup component graph for debugging
- acp: Zed editor integration status (discoverability only, tracking ROADMAP #76)
- export: session transcript export (requires --resume)

Each section follows the existing USAGE.md pattern:
- Purpose statement
- Example usage
- When-to-use guidance
- Related error modes where applicable

Coverage: 12/12 binary verbs now documented (was 8/12).

Acceptance:
- All 4 verbs have dedicated sections with examples: verified by grep
- Parity audit re-run: 100% coverage

Relates to ROADMAP #162 (filed cycle #67, implemented cycle #68).
Diff: +87 lines, doc-only, zero code risk.
2026-04-23 03:39:19 +09:00
YeonGyu-Kim
de7a0ffde6 roadmap: #162 filed — USAGE.md missing docs for dump-manifests, bootstrap-plan, acp, export verbs (parity audit) 2026-04-23 03:37:09 +09:00
YeonGyu-Kim
36883ba4c2 roadmap: cluster update — #161 elevated to diagnostic-strictness family (per gaebal-gajae reframe) 2026-04-23 03:35:03 +09:00
YeonGyu-Kim
f000fdd7fc docs: add REVIEW_DASHBOARD.md — integration support artifact for 14-branch queue
Consolidates all 14 review-ready branches into a single dashboard showing:
- Priority tiers (P0 typed-error → P3 doc truthfulness)
- Cluster membership and batch-reviewable groups
- Branch inventory with commits, diff size, tests, cluster, expected merge time
- Merge throughput notes and reviewer shortcuts

Per integration-support-artifacts doctrine (cycle #64):
At queue saturation (N>=5), docs that reduce reviewer cognitive load are first-class deliverables.

This dashboard aims to make queue digestion cheap:
- Reviewer can scan tiers in 60 seconds
- Batch recommendations saves context switches
- Per-branch facts pre-answer expected questions
- PR-ready summary reference for #249

Cluster impact:
- 14 branches now have explicit cluster/priority labels
- Batch review patterns identified for ~8 branches
- Merge-friction heatmap surfaces lowest-risk starting points
2026-04-23 03:33:46 +09:00
YeonGyu-Kim
f18f45c0cf roadmap: #161 filed — claw version stale SHA in worktrees (build.rs rerun-if-changed misses worktree HEAD) 2026-04-23 03:31:40 +09:00
YeonGyu-Kim
946e43e0c7 roadmap: doctrine extension — integration support artifacts as first-class deliverable at scale (from #64 framing) 2026-04-23 03:27:19 +09:00
YeonGyu-Kim
92a79b5276 docs(parity): update stats to 2026-04-23 — Rust LOC +66%, test LOC +76%, 979 commits on main
Growth since 2026-04-03:
- Rust LOC: 48,599 → 80,789 (+32,190)
- Test LOC: 2,568 → 4,533 (+1,965)
- Commits: 292 → 979 (+687, now pending review phase)

Main HEAD: ad1cf92 (doctrine loop canonical example)

Key deliverables cycles #39–#63:
- Typed-error hardening family (#247–#251)
- Diagnostic-strictness principle (#57–#59)
- Help-parity sweep (#130c–#130e)
- Suffix-guard uniformity (#152)
- Verb-classification fix (#160)
- Integration-bandwidth doctrine (#62)
- Doctrine-loop pattern formalized

Status: 13 branches awaiting review (no new branches since cycle #61 branch-last protocol established)
2026-04-23 03:25:56 +09:00
YeonGyu-Kim
ad1cf92620 roadmap: canonical worked example of doctrine loop (#61–#63 sequence preserved for future claws) 2026-04-23 03:17:41 +09:00
YeonGyu-Kim
6a3913e278 roadmap: #160 SHIPPED — reserved-verb classification landed (cycle #63) 2026-04-23 03:16:34 +09:00
YeonGyu-Kim
553893410b fix(#160): reserved-semantic verbs with positional args now emit slash-command guidance
Verbs with CLI-reserved positional-arg meanings (resume, compact, memory,
commit, pr, issue, bughunter) were falling through to Prompt dispatch
when invoked with args, causing users to see 'missing_credentials' errors
instead of guidance that the verb is a slash command.

#160 investigation revealed the underlying design question: which verbs
are 'promptable' (can start a prompt like 'explain this pattern') vs.
'reserved' (have specific CLI meaning like 'resume SESSION_ID')?

This fix implements the reserved-verb classification: at parse time,
intercept reserved verbs with trailing args and emit slash-command guidance
before falling through to Prompt. Promptable verbs (explain, bughunter, clear)
continue to route to Prompt as before.

Helper: is_reserved_semantic_verb() lists the reserved set.
All 181 tests pass (no regressions).
2026-04-23 03:16:19 +09:00
YeonGyu-Kim
b54eacaa6e roadmap: cycle-pattern doctrine — how violation → reframe → protocol loops create self-enforcing doctrine (from #61–#62) 2026-04-23 03:09:13 +09:00
YeonGyu-Kim
51cee23a27 roadmap: principle — integration bandwidth as constraint when queue is saturated (from #62 framing) 2026-04-23 03:06:22 +09:00
YeonGyu-Kim
35fee5ecde roadmap: #160 investigation update — verb classification table needed for clean fix 2026-04-23 03:04:50 +09:00
YeonGyu-Kim
f034b01733 roadmap: #160 filed — resume with positional args falls through to Prompt dispatch (#251 family) 2026-04-23 03:02:30 +09:00
YeonGyu-Kim
c4054d2fa3 roadmap: principle — backlog truthfulness is execution speed (from #60 framing) 2026-04-23 02:56:23 +09:00
YeonGyu-Kim
7bd91096a8 roadmap: #136 + #153b marked CLOSED — compact+json already correct, PATH docs comprehensive 2026-04-23 02:55:22 +09:00
YeonGyu-Kim
196fe6b493 roadmap: #136 marked CLOSED — compact+json dispatch already correct 2026-04-23 02:54:41 +09:00
YeonGyu-Kim
dc8b275c9f roadmap: principle — cycle cadence (hygiene cycles are first-class, from #59 framing) 2026-04-23 02:45:43 +09:00
YeonGyu-Kim
8f4f215e27 roadmap: diagnostic-strictness audit checklist (from cycles #57-#58) 2026-04-23 02:38:06 +09:00
YeonGyu-Kim
0aa0d3f7cf fix(#122b): claw doctor warns when cwd is broad path (home/root)
## What Was Broken

`claw doctor` reported "Status: ok" when run from ~/ or /, but `claw
prompt` in the same directory would error out with:

    error: claw is running from a very broad directory (/Users/yeongyu).
    The agent can read and search everything under this path.

Diagnostic deception: doctor said green, prompt said red. User runs
doctor to check their setup, sees all green, runs prompt, gets blocked.
Trust in doctor erodes.

This is the exact pattern captured in the 'Diagnostic Commands Must Be
At Least As Strict As Runtime Commands' principle recorded in ROADMAP.md
at cycle #57.

## Root Cause

Two code paths perform the broad-cwd check:
- CliAction::Prompt handler → `enforce_broad_cwd_policy()` (errors out)
- CliAction::Repl handler → same function

But render_doctor_report() never called detect_broad_cwd(). The workspace
health check only looked at whether cwd was inside a git project, not
whether cwd was a dangerously broad path.

## What This Fix Does

Extend `check_workspace_health()` to also probe `detect_broad_cwd()`:

    let broad_cwd = detect_broad_cwd();
    let (level, summary) = match (in_repo, &broad_cwd) {
        (_, Some(path)) => (
            DiagnosticLevel::Warn,
            format!(
                "current directory is a broad path ({}); Prompt/REPL will \
                 refuse to run here without --allow-broad-cwd",
                path.display()
            ),
        ),
        (true, None) => (DiagnosticLevel::Ok, "project root detected"),
        (false, None) => (DiagnosticLevel::Warn, "not inside a git project"),
    };

The check now warns about BOTH failure modes with clear messaging about
what Prompt/REPL will do.

## Dogfood Verification

Before fix:
    $ cd ~ && claw doctor
    Workspace
      Status           warn
      Summary          current directory is not inside a git project
    [all green otherwise]

    $ echo | claw prompt "test"
    error: claw is running from a very broad directory (/Users/yeongyu)...

After fix:
    $ cd ~ && claw doctor
    Workspace
      Status           warn
      Summary          current directory is a broad path (/Users/yeongyu);
                       Prompt/REPL will refuse to run here without
                       --allow-broad-cwd

    $ cd / && claw doctor
    Workspace
      Status           warn
      Summary          current directory is a broad path (/); ...

Non-regression:
    $ cd /tmp/my-project && claw doctor
    Workspace
      Status           warn
      Summary          current directory is not inside a git project
    (unchanged)

    $ cd /path/to/real/git/project && claw doctor
    Workspace
      Status           ok
      Summary          project root detected on branch main
    (unchanged)

## Regression Tests Added

- `workspace_check_in_project_dir_reports_ok` — non-broad + in-project = OK
- `workspace_check_outside_project_reports_warn` — non-broad + not-in-project = Warn with 'not inside git project' summary
- 181 binary tests pass (was 179, added 2)

## Related

- Principle: 'Diagnostic Commands Must Be At Least As Strict As Runtime
  Commands' (ROADMAP.md cycle #57)
- Companion to #122 (stale-base preflight in doctor)
- Sibling: next step is probably a full runtime-vs-doctor audit for
  other asymmetries (auth, sandbox, plugins, hooks)
2026-04-23 02:35:49 +09:00
YeonGyu-Kim
86b98d07e9 roadmap: principle — diagnostic surfaces must be at least as strict as runtime (from #122 framing) 2026-04-23 02:25:45 +09:00
YeonGyu-Kim
cb8839e050 roadmap: cluster closure + defer #155/#156 design questions (config section validation, mcp/agents soft-warning) 2026-04-23 02:18:46 +09:00
YeonGyu-Kim
41b0006eea roadmap: cluster closure note — help-parity family complete (#130c, #130d, #130e) 2026-04-23 02:10:07 +09:00
YeonGyu-Kim
9dd7e79eb2 fix(#130e-B): route plugins/prompt --help to dedicated help topics
## What Was Broken (ROADMAP #130e Category B)

Two remaining surface-level help outliers after #130e-A:

    $ claw plugins --help
    Unknown /plugins action '--help'. Use list, install, enable, disable, uninstall, or update.

    $ claw prompt --help
    claw v0.1.0  (top-level help — wrong help topic)

`plugins` treated `--help` as an invalid subaction name. `prompt`
was explicitly listed in the early `wants_help` interception with
commit/pr/issue, which routed to top-level help instead of
prompt-specific help.

## Root Cause (Traced)

1. **plugins**: `parse_local_help_action()` didn't have a "plugins"
   arm, so `["plugins", "--help"]` returned None and continued into
   the `"plugins"` parser arm (main.rs:1031), which treated `--help`
   as the `action` argument. Runtime layer then rejected it as
   "Unknown action".

2. **prompt**: At main.rs:~800, there was an early interception for
   `--help` following certain subcommands (prompt, commit, pr, issue)
   that forced `wants_help = true`, routing to generic top-level help
   instead of letting parse_local_help_action produce a prompt-specific
   topic.

## What This Fix Does

Same pattern as #130c/#130d/#130e-A:

1. **LocalHelpTopic enum extended** with Plugins, Prompt variants
2. **parse_local_help_action() extended** to map both new cases
3. **Help topic renderers added** with accurate usage info
4. **Early prompt-interception removed** — prompt now falls through to
   parse_local_help_action like other subcommands. commit/pr/issue
   (which aren't actual subcommands yet) remain in the early list.

## Dogfood Verification

Before fix:
    $ claw plugins --help
    Unknown /plugins action '--help'. Use list, install, enable, ...

    $ claw prompt --help
    claw v0.1.0
    (top-level help, not prompt-specific)

After fix:
    $ claw plugins --help
    Plugins
      Usage            claw plugins [list|install|enable|disable|uninstall|update] [<target>]
      Purpose          manage bundled and user plugins from the CLI surface
      ...

    $ claw prompt --help
    Prompt
      Usage            claw prompt <prompt-text>
      Purpose          run a single-turn, non-interactive prompt and exit
      Flags            --model · --allowedTools · --output-format · --compact
      ...

## Non-Regression Verification

- `claw plugins` (no args) → still displays plugin inventory 
- `claw plugins list` → still works correctly 
- `claw prompt "text"` → still requires credentials, runs prompt 
- All 180 binary tests pass 
- All 466 library tests pass 

## Regression Tests Added (4+ assertions)

- `plugins --help` → HelpTopic(Plugins)
- `prompt --help` → HelpTopic(Prompt)
- Short forms `plugins -h` / `prompt -h` both work
- `prompt "hello world"` still routes to Prompt action with correct text

## HELP-PARITY SWEEP COMPLETE

All 22 top-level subcommands now emit proper help topics:

| Command | Status |
|---|---|
| help --help |  #130e-A |
| version --help |  pre-existing |
| status --help |  pre-existing |
| sandbox --help |  pre-existing |
| doctor --help |  pre-existing |
| acp --help |  pre-existing |
| init --help |  pre-existing |
| state --help |  pre-existing |
| export --help |  pre-existing |
| diff --help |  #130c |
| config --help |  #130d |
| mcp --help |  pre-existing |
| agents --help |  pre-existing |
| plugins --help |  #130e-B (this commit) |
| skills --help |  pre-existing |
| submit --help |  #130e-A |
| prompt --help |  #130e-B (this commit) |
| resume --help |  #130e-A |
| system-prompt --help |  pre-existing |
| dump-manifests --help |  pre-existing |
| bootstrap-plan --help |  pre-existing |

Zero outliers. Contract universally enforced.

## Related

- Closes #130e Category B (plugins, prompt surface-parity)
- Completes entire help-parity sweep family (#130c, #130d, #130e)
- Stacks on #130e-A (dispatch-order fixes) on same worktree
2026-04-23 02:07:50 +09:00
YeonGyu-Kim
0ca034472b fix(#130e-A): route help/submit/resume --help to help topics before credential check
## What Was Broken (ROADMAP #130e, filed cycle #53)

Three subcommands leaked `missing_credentials` errors when called
with `--help`:

    $ claw help --help
    [error-kind: missing_credentials]
    error: missing Anthropic credentials...

    $ claw submit --help
    [error-kind: missing_credentials]
    error: missing Anthropic credentials...

    $ claw resume --help
    [error-kind: missing_credentials]
    error: missing Anthropic credentials...

This is the same dispatch-order bug class as #251 (session verbs).
The parser fell through to the credential check before help-flag
resolution ran. Critical discoverability gap: users couldn't learn
what these commands do without valid credentials.

## Root Cause (Traced)

`parse_local_help_action()` (main.rs:1260) is called early in
`parse_args()` (main.rs:1002), BEFORE credential check. But the
match statement inside only recognized:
status, sandbox, doctor, acp, init, state, export, version,
system-prompt, dump-manifests, bootstrap-plan, diff, config.

`help`, `submit`, `resume` were NOT in the list, so the function
returned `None`, and parsing continued to credential check which
then failed.

## What This Fix Does

Same pattern as #130c (diff) and #130d (config):

1. **LocalHelpTopic enum extended** with Meta, Submit, Resume variants
2. **parse_local_help_action() extended** to map the three new cases
3. **Help topic renderers added** with accurate usage info

Three-line change to parse_local_help_action:

    "help" => LocalHelpTopic::Meta,
    "submit" => LocalHelpTopic::Submit,
    "resume" => LocalHelpTopic::Resume,

Dispatch order (parse_args):
    1. --resume parsing
    2. parse_local_help_action() ← NOW catches help/submit/resume --help
    3. parse_single_word_command_alias()
    4. parse_subcommand() ← Credential check happens here

## Dogfood Verification

Before fix (all three):
    $ claw help --help
    [error-kind: missing_credentials]
    error: missing Anthropic credentials...

After fix:
    $ claw help --help
    Help
      Usage            claw help [--output-format <format>]
      Purpose          show the full CLI help text (all subcommands, flags, environment)
      ...

    $ claw submit --help
    Submit
      Usage            claw submit [--session <id|latest>] <prompt-text>
      Purpose          send a prompt to an existing managed session
      Requires         valid Anthropic credentials (when actually submitting)
      ...

    $ claw resume --help
    Resume
      Usage            claw resume [<session-id|latest>]
      Purpose          restart an interactive REPL attached to a managed session
      ...

## Non-Regression Verification

- `claw help` (no --help) → still shows full CLI help 
- `claw submit "text"` (with prompt) → still requires credentials 
- `claw resume` (bare) → still emits slash command guidance 
- All 180 binary tests pass 
- All 466 library tests pass 

## Regression Tests Added (6 assertions)

- `help --help` → routes to HelpTopic(Meta)
- `submit --help` → routes to HelpTopic(Submit)
- `resume --help` → routes to HelpTopic(Resume)
- Short forms: `help -h`, `submit -h`, `resume -h` all work

## Pattern Note

This is Category A of #130e (dispatch-order bugs). Same class as #251.
Category B (surface-parity: plugins, prompt) will be handled in a
follow-up commit/branch.

## Help-Parity Sweep Status

After cycle #52 (#130c diff, #130d config), help sweep revealed:

| Command | Before | After This Commit |
|---|---|---|
| help --help | missing_credentials |  Meta help |
| submit --help | missing_credentials |  Submit help |
| resume --help | missing_credentials |  Resume help |
| plugins --help | "Unknown action" |  #130e-B (next) |
| prompt --help | wrong help |  #130e-B (next) |

## Related

- Closes #130e Category A (dispatch-order help fixes)
- Same bug class as #251 (session verbs)
- Stacks on #130d (config help) on same worktree branch
- #130e Category B (plugins, prompt) queued for follow-up
2026-04-23 02:03:10 +09:00
YeonGyu-Kim
762e9bb212 roadmap: file #130e — help-parity sweep reveals 5 additional anomalies (3 dispatch-order, 2 surface) 2026-04-23 02:00:59 +09:00
YeonGyu-Kim
19638a015e fix(#130d): accept --help / -h in claw config arm, route to help topic
## What Was Broken (ROADMAP #130d, filed cycle #52)

`claw config --help` was silently ignored — the command executed and
displayed the config dump instead of showing help:

    $ claw config --help
    Config
      Working directory /private/tmp/dogfood-probe-47
      Loaded files      0
      Merged keys       0
      (displays full config, not help)

Expected: help for the config command. Actual: silent acceptance of
`--help`, runs config display anyway.

This is the opposite outlier from #130c (which rejected help with an
error). Together they form the help-parity anomaly:
- #130c `diff --help` → error (rejects help)
- #130d `config --help` → silent ignore (runs command, ignores help)
- Others (status, mcp, export) → proper help
- Expected behavior: all commands should show help on `--help`

## Root Cause (Traced)

At main.rs:1050, the `"config"` parser arm parsed arguments positionally:

    "config" => {
        let tail = &rest[1..];
        let section = tail.first().cloned();
        // ... ignores unrecognized args like --help silently
        Ok(CliAction::Config { section, ... })
    }

Unlike the `diff` arm (#130c), `config` had no explicit check for
extra args. It positionally parsed the first arg as an optional
`section` and silently accepted/ignored any trailing arg, including
`--help`.

## What This Fix Does

Same pattern as #130c (help-surface parity):

1. **LocalHelpTopic enum extended** with new `Config` variant
2. **parse_local_help_action() extended** to map `"config"` → `LocalHelpTopic::Config`
3. **config arm guard added**: check for help flag before parsing section
4. **Help topic renderer added**: human-readable help text for config

Fix locus at main.rs:1050:

    "config" => {
        // #130d: accept --help / -h and route to help topic
        if rest.len() >= 2 && is_help_flag(&rest[1]) {
            return Ok(CliAction::HelpTopic(LocalHelpTopic::Config));
        }
        let tail = &rest[1..];
        // ... existing parsing continues
    }

## Dogfood Verification

Before fix:
    $ claw config --help
    Config
      Working directory ...
      Loaded files      0
      (no help, runs config)

After fix:
    $ claw config --help
    Config
      Usage            claw config [--cwd <path>] [--output-format <format>]
      Purpose          merge and display the resolved configuration
      Options          --cwd overrides the workspace directory
      Output           loaded files and merged key-value pairs
      Formats          text (default), json
      Related          claw status · claw doctor · claw init

Short form `claw config -h` also works.

## Non-Regression Verification

- `claw config` (no args) → still displays config dump 
- `claw config permissions` (section arg) → still works 
- All 180 binary tests pass 
- All 466 library tests pass 

## Regression Tests Added (4 assertions)

- `config --help` → routes to `HelpTopic(LocalHelpTopic::Config)`
- `config -h` (short form) → routes to help topic
- bare `config` (no args) → still routes to `Config` action
- `config permissions` (with section) → still works correctly

## Pattern Note

#130c and #130d form a pair: two outlier failure modes in help
handling for local introspection commands:
- #130c `diff` rejected help (loud error) → fixed with guard + routing
- #130d `config` silently ignored help (silent accept) → fixed with same pattern

Both are now consistent with the rest of the CLI (status, mcp, export, etc.).

## Related

- Closes #130d (config help discoverability gap)
- Completes help-parity family (#130c, #130d)
- Stacks on #130c (diff help fix) on same worktree branch
- Part of help-consistency thread (#141 audit)
2026-04-23 01:55:25 +09:00
YeonGyu-Kim
5e29430d4f roadmap: file #130d — config command silently ignores --help, displays config dump instead 2026-04-23 01:53:31 +09:00
YeonGyu-Kim
83f744adf0 fix(#130c): accept --help / -h in claw diff arm
## What Was Broken (ROADMAP #130c, filed cycle #50)

`claw diff --help` was rejected with:

    [error-kind: unknown]
    error: unexpected extra arguments after `claw diff`: --help

Other local introspection commands accept --help fine:
- `claw status --help` → shows help 
- `claw mcp --help` → shows help 
- `claw export --help` → shows help 
- `claw diff --help` → error  (outlier)

This is a help-surface parity bug: `diff` is the only local command
that rejects --help as "extra arguments" before the help detector
gets a chance to run.

## Root Cause (Traced)

At main.rs:1063, the `"diff"` parser arm rejected ALL extra args:

    "diff" => {
        if rest.len() > 1 {
            return Err(format!("unexpected extra arguments after `claw diff`: {}", ...));
        }
        Ok(CliAction::Diff { output_format })
    }

When parsing `["diff", "--help"]`, `rest.len() > 1` was true (length
is 2) and `--help` was rejected as extra argument.

Other commands (status, sandbox, doctor, init, state, export, etc.)
routed through `parse_local_help_action()` which detected
`--help` / `-h` and routed to a LocalHelpTopic. The `diff` arm
lacked this guard.

## What This Fix Does

Three minimal changes:

1. **LocalHelpTopic enum extended** with new `Diff` variant
2. **parse_local_help_action() extended** to map `"diff"` → `LocalHelpTopic::Diff`
3. **diff arm guard added**: check for help flag before extra-args validation
4. **Help topic renderer added**: human-readable help text for diff command

Fix locus at main.rs:1063:

    "diff" => {
        // #130c: accept --help / -h as first argument and route to help topic
        if rest.len() == 2 && is_help_flag(&rest[1]) {
            return Ok(CliAction::HelpTopic(LocalHelpTopic::Diff));
        }
        if rest.len() > 1 { /* existing error */ }
        Ok(CliAction::Diff { output_format })
    }

## Dogfood Verification

Before fix:
    $ claw diff --help
    [error-kind: unknown]
    error: unexpected extra arguments after `claw diff`: --help

After fix:
    $ claw diff --help
    Diff
      Usage            claw diff [--output-format <format>]
      Purpose          show local git staged + unstaged changes
      Requires         workspace must be inside a git repository
      ...

And `claw diff -h` (short form) also works.

## Non-Regression Verification

- `claw diff` (no args) → still routes to Diff action correctly
- `claw diff foo` (unknown arg) → still rejected as "unexpected extra arguments"
- `claw diff --output-format json` (valid flag) → still works
- All 180 binary tests pass
- All 466 library tests pass

## Regression Tests Added (4 assertions)

- `diff --help` → routes to HelpTopic(LocalHelpTopic::Diff)
- `diff -h` (short form) → routes to HelpTopic(LocalHelpTopic::Diff)
- bare `diff` → still routes to Diff action
- `diff foo` (unknown arg) → still errors with "extra arguments"

## Pattern

Follows #141 help-consistency work (extending LocalHelpTopic to
cover more subcommands). Clean surface-parity fix: identify the
outlier, add the missing guard. Low-risk, high-clarity.

## Related

- Closes #130c (diff help discoverability gap)
- Stacks on #130b (filesystem context) and #251 (session dispatch)
- Part of help-consistency thread (#141 audit, #145 plugins wiring)
2026-04-23 01:48:40 +09:00
YeonGyu-Kim
0d8adceb67 roadmap: file #130c — pure-local commands reject --help as extra argument (diff, config, status) 2026-04-23 01:44:11 +09:00
YeonGyu-Kim
d49a75cad5 fix(#130b): enrich filesystem I/O errors with operation + path context
## What Was Broken (ROADMAP #130b, filed cycle #47)

In a fresh workspace, running:

    claw export latest --output /private/nonexistent/path/file.jsonl --output-format json

produced:

    {"error":"No such file or directory (os error 2)","hint":null,"kind":"unknown","type":"error"}

This violates the typed-error contract:
- Error message is a raw errno string with zero context
- Does not mention the operation that failed (export)
- Does not mention the target path
- Classifier defaults to "unknown" even though the code path knows
  this is a filesystem I/O error

## Root Cause (Traced)

run_export() at main.rs:~6915 does:

    fs::write(path, &markdown)?;

When this fails:
1. io::Error propagates via ? to main()
2. Converted to string via .to_string() in error handler
3. classify_error_kind() cannot match "os error" or "No such file"
4. Defaults to "kind": "unknown"

The information is there at the source (operation name, target path,
io::ErrorKind) but lost at the propagation boundary.

## What This Fix Does

Three changes:

1. **New helper: contextualize_io_error()** (main.rs:~260)
   Wraps an io::Error with operation name + target path into a
   recognizable message format:

       "{operation} failed: {target} ({error})"

2. **Classifier branch added** (classify_error_kind at main.rs:~270)
   Recognizes the new format and classifies as "filesystem_io_error":

       else if message.contains("export failed:") ||
               message.contains("diff failed:") ||
               message.contains("config failed:") {
           "filesystem_io_error"
       }

3. **run_export() wired** (main.rs:~6915)
   fs::write() call now uses .map_err() to enrich io::Error:

       fs::write(path, &markdown).map_err(|e| -> Box<dyn std::error::Error> {
           contextualize_io_error("export", &path.display().to_string(), e).into()
       })?;

## Dogfood Verification

Before fix:

    {"error":"No such file or directory (os error 2)","kind":"unknown","type":"error"}

After fix:

    {"error":"export failed: /private/nonexistent/path/file.jsonl (No such file or directory (os error 2))","kind":"filesystem_io_error","type":"error"}

The envelope now tells downstream claws:
- WHAT operation failed (export)
- WHERE it failed (the path)
- WHAT KIND of failure (filesystem_io_error)
- The original errno detail preserved for diagnosis

## Non-Regression Verification

- Successful export still works (emits "kind": "export" envelope as before)
- Session not found error still emits "session_not_found" (not filesystem)
- missing_credentials still works correctly
- cli_parse still works correctly
- All 180 binary tests pass
- All 466 library tests pass
- All 95 compat-harness tests pass

## Regression Tests Added

Inside the main CliAction test function:

- "export failed:" pattern classifies as "filesystem_io_error" (not "unknown")
- "diff failed:" pattern classifies as "filesystem_io_error"
- "config failed:" pattern classifies as "filesystem_io_error"
- contextualize_io_error() produces a message containing operation name
- contextualize_io_error() produces a message containing target path
- Messages produced by contextualize_io_error() are classifier-recognizable

## Scope

This is the minimum viable fix: enrich export's fs::write with context.
Future work (filed as part of #130b scope): apply same pattern to
other filesystem operations (diff, plugins, config fs reads, session
store writes, etc.). Each application is a copy-paste of the same
helper pattern.

## Pattern

Follows #145 (plugins parser interception), #248-249 (arm-level leak
templates). Helper + classifier + call site wiring. Minimal diff,
maximum observability gain.

## Related

- Closes #130b (filesystem error context preservation)
- Stacks on top of #251 (dispatch-order fix) — same worktree branch
- Ground truth for future #130 broader sweep (other io::Error sites)
2026-04-23 01:40:07 +09:00
YeonGyu-Kim
9eba71da81 roadmap: file #153b — PATH setup guide follow-up to #153 2026-04-23 01:35:24 +09:00
YeonGyu-Kim
ef5aae3ddd roadmap: file #130b — filesystem errors lose context, emit generic errno strings (export command case) 2026-04-23 01:33:25 +09:00
YeonGyu-Kim
f05bc037de docs(#250, #251): Align SCHEMAS.md with actual binary, downgrade #250 to scope-reduced
Cycle #46 follow-up to cycle #45's #251 implementation. Closes #250's
implementation urgency by aligning docs with reality.

SCHEMAS.md Updates:
For each of the 4 session-management verbs, added:
1. Status marker (Implemented or Stub only)
2. Actual binary envelope (shape produced by the #251-fixed binary)
3. Aspirational (future) shape (original SCHEMAS.md content, preserved as target)
4. Gap notes where the two diverge

Per-verb status:
- list-sessions: Implemented, nested field layout
- load-session: Implemented, nested session object with local session_not_found error
- delete-session: Stub, emits not_yet_implemented (local error, not auth)
- flush-transcript: Stub, emits not_yet_implemented (local error, not auth)

ROADMAP.md Updates:
- #251 marked CLOSED: Full status with commit ref, test counts.
- #250 marked SCOPE-REDUCED: Option A resolved by #251, Option C moot,
  only Option B (doc alignment) remains as future cleanup.

Why this matters:
Every code change should close its documentation loop. #251 landed on
the branch, but SCHEMAS.md still described aspirational shapes without
marking which were implemented. Claws reading SCHEMAS.md would have
assumed full conformance and hit surprises. Now the document tells the
truth about which verbs work, which are stubs, and why.

Related:
- #251 implementation on feat/jobdori-251-session-dispatch branch
- #250 scope-reduced to Option B (field-name harmonization)
- #145/#146 parser fall-through fix precedent
2026-04-23 01:28:33 +09:00
YeonGyu-Kim
dc274a0f96 fix(#251): intercept session-management verbs at top-level parser to bypass credential check
## What Was Broken (ROADMAP #251)

Session-management verbs (list-sessions, load-session, delete-session,
flush-transcript) were falling through to the parser's `_other => Prompt`
catchall at main.rs:~1017. This construed them as `CliAction::Prompt {
prompt: "list-sessions", ... }` which then required credentials via the
Anthropic API path. The result: purely-local session operations emitted
`missing_credentials` errors instead of session-layer envelopes.

## Acceptance Criterion

The fix's essential requirement (stated by gaebal-gajae):
**"These 4 verbs stop falling through to Prompt and emitting `missing_credentials`."**
Not "all 4 are fully implemented to spec" — stubs are acceptable for
delete-session and flush-transcript as long as they route LOCALLY.

## What This Fix Does

Follows the exact pattern from #145 (plugins) and #146 (config/diff):

1. **CliAction enum** (main.rs:~700): Added 4 new variants.
2. **Parser** (main.rs:~945): Added 4 match arms before the `_other => Prompt`
   catchall. Each arm validates the verb's positional args (e.g., load-session
   requires a session-id) and rejects extra arguments.
3. **Dispatcher** (main.rs:~455):
   - list-sessions → dispatches to `runtime::session_control::list_managed_sessions_for()`
   - load-session → dispatches to `runtime::session_control::load_managed_session_for()`
   - delete-session → emits `not_yet_implemented` error (local, not auth)
   - flush-transcript → emits `not_yet_implemented` error (local, not auth)

## Dogfood Verification

Run on clean environment (no credentials):

```bash
$ env -i PATH=$PATH HOME=$HOME claw list-sessions --output-format json
{
  "command": "list-sessions",
  "sessions": [
    {"id": "session-1775777421902-1", ...},
    ...
  ]
}
# ✓ Session-layer envelope, not auth error

$ env -i PATH=$PATH HOME=$HOME claw load-session nonexistent --output-format json
{"error":"session not found: nonexistent", "kind":"session_not_found", ...}
# ✓ Local session_not_found error, not missing_credentials

$ env -i PATH=$PATH HOME=$HOME claw delete-session test-id --output-format json
{"command":"delete-session","error":"not_yet_implemented","kind":"not_yet_implemented","type":"error"}
# ✓ Local not_yet_implemented, not auth error

$ env -i PATH=$PATH HOME=$HOME claw flush-transcript test-id --output-format json
{"command":"flush-transcript","error":"not_yet_implemented","kind":"not_yet_implemented","type":"error"}
# ✓ Local not_yet_implemented, not auth error
```

Regression sanity:

```bash
$ claw plugins --output-format json  # #145 still works
$ claw prompt "hello" --output-format json  # still requires credentials correctly
$ claw list-sessions extra arg --output-format json  # rejects extra args with cli_parse
```

## Regression Tests Added

Inside `removed_login_and_logout_subcommands_error_helpfully` test function:

- `list-sessions` → CliAction::ListSessions (both text and JSON output)
- `load-session <id>` → CliAction::LoadSession with session_reference
- `delete-session <id>` → CliAction::DeleteSession with session_id
- `flush-transcript <id>` → CliAction::FlushTranscript with session_id
- Missing required arg errors (load-session and delete-session without ID)
- Extra args rejection (list-sessions with extra positional args)

All 180 binary tests pass. 466 library tests pass.

## Fix Scope vs. Full Implementation

This fix addresses #251 (dispatch-order bug) and #250's Option A (implement
the surfaces). list-sessions and load-session are fully functional via
existing runtime::session_control helpers. delete-session and flush-transcript
are stubbed with local "not yet implemented" errors to satisfy #251's
acceptance criterion without requiring additional session-store mutations
that can ship independently in a follow-up.

## Template

Exact same pattern as #145 (plugins) and #146 (config/diff): top-level
verb interception → CliAction variant → dispatcher with local operation.

## Related

Closes #251. Addresses #250 Option A for 4 verbs. Does not block #250
Option B (documentation scope guards) which remains valuable.
2026-04-23 01:25:32 +09:00
YeonGyu-Kim
2fcb85ce4e ROADMAP #251: dispatch-order bug — session-management verbs fall through to Prompt before credential check (filed by gaebal-gajae; formalized by Jobdori cycle #40)
Cycle #40: gaebal-gajae conceived #251 in their 00:00 Discord cycle
status but hadn't committed to ROADMAP yet. Jobdori verified their
diagnosis with code trace and formalized into ROADMAP with the proper
framing relationship to #250.

## What This Pinpoint Says

Same observable as #250 (session-management verbs emit missing_credentials
instead of SCHEMAS.md envelope) but reframed at the dispatch-order layer:

- #250 says: surface missing on canonical binary vs SCHEMAS.md promise
- #251 says: top-level parser fall-through happens BEFORE dispatcher
  could intercept, so credential resolution runs before the verb is
  classified as a purely-local operation

#251's framing is sharper because it identifies WHY the fall-through
produces auth errors, not just that it does.

## Verified Code Trace

- main.rs:1017-1027 is the _other => Prompt catchall
- joins all rest[] tokens into joined, constructs CliAction::Prompt
- downstream resolves credentials -> emits missing_credentials
- No credential call would be needed had the verb been intercepted

Same pattern has been fixed before for other purely-local verbs:
- #145: plugins (main.rs:888-906, explicit match arm)
- #146: config and diff (main.rs:911-935, same shape)

#251 extends this to the 4 session-management verbs.

## Recommended Sequence

1. #251 fix (4 match arms mirroring #145/#146) — principled solution
2. #250's Option B (docs scope note) — guard against future drift
3. #250's Option C (reject with redirect) — unnecessary if #251 lands

## Discipline

Per cycle #24 calibration:
- Red-state bug? Borderline (silent misroute to auth error class)
- Real friction? ✓ (4 documented surfaces emit wrong error class)
- Evidence-backed? ✓ (code trace + prior-fix precedent #145/#146)
- Same-cycle fix? ✗ (filed + document, boundary discipline #36)
- Implementation cost? ~40 lines Rust + tests, bounded

## Credit

Conception: gaebal-gajae (Discord msg 1496526112254328902, 00:00 KST)
Formalization: Jobdori cycle #40 (code trace + precedent linking)

This is the right kind of collaboration: gaebal-gajae saw the dispatch
pattern I had missed in #250 (I framed as surface parity; they framed
as dispatch order). I verified their diagnosis and committed the
ROADMAP entry. Two framings make the pinpoint sharper than either
alone.
2026-04-23 00:06:46 +09:00