Skip to content

Fix add_failed silent failure caused by Windows backslashes in settings.toml repo_path#1

Open
martinduncanson wants to merge 2 commits into
malphas-gh:mainfrom
martinduncanson:pr/fix-windows-toml-backslash
Open

Fix add_failed silent failure caused by Windows backslashes in settings.toml repo_path#1
martinduncanson wants to merge 2 commits into
malphas-gh:mainfrom
martinduncanson:pr/fix-windows-toml-backslash

Conversation

@martinduncanson
Copy link
Copy Markdown

Goal

Fix a silent add_failed regression on Windows where clawpm add fails despite the project being detected by other commands. Reproducible whenever .project/settings.toml was written with a Windows path containing backslashes (e.g. repo_path = \"F:\Git\my-project\").

Root cause

tomllib treats \X as an escape sequence — most Windows paths trigger TOMLDecodeError. The error was being swallowed by a bare except Exception: continue in discovery.get_project(), making the project invisible to registry lookups. clawpm tasks list --project foo worked (CWD-walk path), but clawpm tasks add --project foo failed (full TOML parse path) — same project ID, opposite results, no diagnostic output anywhere.

Approach

Three layers, smallest blast radius first:

  1. Always write paths via Path.as_posix()path_for_config() helper centralised in discovery.py. Forward slashes are valid TOML on every platform.
  2. Replace bare except Exception: continue with WARNING-level logging + narrow exceptions — silent skips over file parsing are how invisible bugs survive.
  3. Defensive CWD-walk fallback in add_task — if the registry lookup fails but a valid .project/settings.toml exists for the named project, use it. Surfaces a one-line info note about the divergence so the underlying issue stays visible without breaking the user's workflow.

Plus the test fixture (tests/test_subtasks.py) had the same backslash bug — 18 tests ERROR'd at fixture setup on Windows. Same .as_posix() fix, two call sites.

Diff summary

  • src/clawpm/discovery.pypath_for_config() helper, narrowed exception handling, find_project_dir_fallback() for CWD walk when registry lookup fails
  • src/clawpm/tasks.pyadd_task calls fallback before returning None
  • src/clawpm/cli.py — better error message when a local settings.toml exists but isn't in the registry (hints at the backslash cause)
  • tests/test_dual_lookup.py — 11 new regression tests covering: registry-only failures, CWD fallback success, scope of the WARNING log, error message phrasing
  • tests/test_subtasks.py — fixture uses .as_posix() (recovers 18 tests on Windows)

Test evidence

$ pytest tests/test_dual_lookup.py tests/test_subtasks.py -q
.............................                                            [100%]
29 passed in 1.05s

Both bug-fix commits cherry-picked onto origin/main HEAD as the PR base — no merge commits, linear history.

Concerns / things you might want to push back on

  • The CWD fallback is a workaround for a registration-time defect; the real fix is also making clawpm project init register atomically into portfolio.toml. I held off on that because it's a behaviour change, not a bug fix — happy to follow up in a separate PR if you'd prefer that approach.
  • The new WARNING log goes to stderr always (not gated by -f text). I judged this safer than silent-skip, but if you'd rather mute it under -f json, that's a one-line change.

Out of scope

This PR is bug fix only. I have additional improvements on a fork (scope: field for parallel-agent dispatch, Phase 1 reflection layer with predictions/actuals/deltas, Cowork bootstrap skill, AGENTS.md template for Codex). Those are opinionated and separate-PR material if you want them; I'd rather you merge the bug fix on its own merits first.

Provenance

Fork: https://github.com/martinduncanson/clawpm — branches feature/scope-field, feature/reflect-phase1 ready if you want follow-up PRs.

Co-authored-by: Claude (Opus 4.7, anthropic.com)

martinduncanson and others added 2 commits May 8, 2026 11:02
…king repo_path

Root cause: `project init` wrote `repo_path` using `str(Path)` on Windows, producing
backslashes (e.g. `F:\Git\polymarket-arb`). TOML treats backslashes as escape sequences,
so `ProjectSettings.load()` raised a parse error that was silently swallowed by the
`except Exception: continue` guard in `get_project()`. The project existed on disk but
was invisible to every registry lookup, causing `add_task` to return None.

Fixes:
- `path_for_config()` now always uses `Path.as_posix()` (forward slashes) so generated
  settings.toml files are valid TOML on all platforms
- `get_project()` logs a WARNING instead of silently skipping malformed settings files
- New `find_project_dir_fallback()` in discovery.py: walks up from CWD and extracts the
  `id` field via regex when TOML parse fails, enabling lookup even with malformed files
- `add_task()` calls the fallback when the registry returns None, so `clawpm add` works
  from inside an affected repo without requiring a manual settings.toml fix first
- `tasks_add` CLI error message now explains the backslash cause and suggests the fix
  when a local `.project/settings.toml` exists but registry lookup failed
- Fixed `F:/Git/polymarket-arb/.project/settings.toml`: replaced backslash path with
  forward slashes so the project is immediately visible in the portfolio registry

Pre-existing: `test_subtasks.py` fixture has the same backslash-in-TOML bug on Windows
(uses `str(portfolio_root)` directly in the TOML template); all 18 errors are pre-existing
and unrelated to this fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… backslash errors on Windows

The fixture in test_subtasks.py was embedding str(portfolio_root) directly
into TOML content. On Windows this produces backslashes which TOML treats
as escape sequences, blowing up at parse time. Applied the same as_posix()
fix already used in test_scope.py and test_dual_lookup.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant