Skip to content

fix: improve error handling for config loading, task parsing and file transport#10

Merged
tjb-tech merged 1 commit intoHKUDS:mainfrom
xzq-xu:fix/medium-bugs
Mar 18, 2026
Merged

fix: improve error handling for config loading, task parsing and file transport#10
tjb-tech merged 1 commit intoHKUDS:mainfrom
xzq-xu:fix/medium-bugs

Conversation

@xzq-xu
Copy link
Copy Markdown
Contributor

@xzq-xu xzq-xu commented Mar 18, 2026

Summary

  • Fix _load_config() crashing on corrupted JSON: When config.json contains invalid JSON or fails Pydantic validation, all callers expect None to be returned. Previously this raised an unhandled exception, potentially crashing discover, status, and other team commands.
  • Fix empty strings in --blocks / --blocked-by flags: Input like --blocked-by ",,task1" produced ["", "", "task1"], causing tasks to be permanently blocked since no task has an empty-string ID. Empty entries are now filtered out during parsing in both task create and task update.
  • Fix FileTransport.deliver() leaving orphan tmp files on failure: If rename failed (e.g. cross-filesystem), the .tmp-*.json file was left behind with no cleanup. Now uses Path.replace() for atomic move and cleans up the tmp file in an except block.

Test plan

  • All 124 existing tests pass
  • Ruff lint clean
  • Manually corrupt a team's config.json and verify team discover doesn't crash
  • Test task create --blocked-by ",,task1" and verify only task1 is in blockedBy
  • Verify no .tmp-*.json files accumulate in inbox directories

Made with Cursor

… transport

- Fix _load_config() crashing on corrupted JSON files instead of
  returning None as all callers expect.
- Fix task create/update accepting empty strings in --blocks and
  --blocked-by flags (e.g. ",,task1" produced ["", "", "task1"]),
  which caused tasks to be permanently blocked.
- Fix FileTransport.deliver() leaving orphan tmp files on failure.
  Use Path.replace() for atomic move and clean up tmp in except block.

Made-with: Cursor
@tjb-tech tjb-tech merged commit 7372063 into HKUDS:main Mar 18, 2026
@xzq-xu xzq-xu deleted the fix/medium-bugs branch March 19, 2026 10:08
a24ibrah pushed a commit to a24ibrah/ClawTeam that referenced this pull request Mar 30, 2026
fix: improve error handling for config loading, task parsing and file transport
juntaochi added a commit to novix-science/ClawTeam-gstack that referenced this pull request Apr 20, 2026
…st_command + deploy_url

- 13 failing tests cover presence, frontmatter schema, stub detection (sections + blacklist), test-report rerun + cache-hit + exit-1 + timeout, and ship-notes deploy_url 2xx/non-2xx/URLError paths
- Test-local schema fixtures (DesignDoc/TestReport/ShipNotes) inherit from ArtifactFrontmatterBase; Phase 3 GstackSprintPlugin ships the real subclasses
- Pitfall HKUDS#4 proof: subprocess_runner injection seam asserted with shell-free list cmd + cwd pin + 300s timeout
- Pitfall HKUDS#6 proof: unregistered artifact_type surfaces 'Phase 3 plugin must register' message
- Pitfall HKUDS#10 proof: deploy_url_checker injection seam covers URLError offline-safety path
- RED: all tests fail with ModuleNotFoundError on clawteam.harness.evidence_gate
juntaochi added a commit to novix-science/ClawTeam-gstack that referenced this pull request Apr 20, 2026
…oy_url HEAD probe

- New clawteam/harness/evidence_gate.py subclasses ArtifactRequiredGate with:
  - Layer 1 presence check (inherited)
  - Layer 2 frontmatter parse + EvidenceSchemaRegistry dispatch; unregistered artifact_type surfaces 'Phase 3 plugin must register'
  - Layer 3 stub detection (detect_stub): blacklist regex (TBD / TODO / xxx+ / placeholder / Lorem ipsum) with line numbers, then required ## section floor of 100 bytes
  - Layer 4 dispatch: test-report → _run_test_command (shell=False, cwd=workspace_branch, 300s timeout) with SHA256 content-hash cache persisted via file_locked + atomic_write_text; ship-notes → _check_deploy_url HEAD probe with 10s timeout
  - Layer 4b per-phase artifact-cap (phase_artifact_cap_bytes) with artifact_compaction suggestion
- Injection seams: subprocess_runner (T-02-03 mitigation verification) and deploy_url_checker (Pitfall HKUDS#10 / T-02-01 Phase 5 allowlist contract)
- Fix test file: rename TestReportFixture to ReportTestFixture (avoid pytest Test* collection warning); quote created_at YAML values so they stay str (YAML 1.1 auto-parses bare ISO-8601 as datetime)
- 13 evidence-gate tests pass; template regression matrix (SC#10), harness, artifact_caps, evidence_schemas, turn_envelope all green (87/87)
juntaochi added a commit to novix-science/ClawTeam-gstack that referenced this pull request Apr 27, 2026
- ToolCallCompleted (D-09, cost tracker input)
- ClaudeApiResponse (D-12, cache-hit tracking)
- BudgetAlarmReached (D-10, budget threshold crossing)
- RateLimitSaturated (D-13, 429 backpressure)
- ZombieWorktreeGced (SC HKUDS#10, worktree GC)
- DormancyTransition (QUALITY-04, agent dormancy)
- register_event_type calls appended at module bottom after Phase 6 block
juntaochi added a commit to novix-science/ClawTeam-gstack that referenced this pull request Apr 27, 2026
…2 GREEN)

- clawteam/cli/commands.py doctor() gains optional `gc: bool = typer.Option(...)`
  flag. When `--gc` absent, behavior is byte-identical to prior doctor()
  (existing _DOCTOR_TOOLS iteration + _human() render + _output(checks, _human)).

- With `--gc`: after the tool checklist, walks get_data_dir()/teams/<name>/
  for each team dir. For each, collects active_branches from every
  SprintState.load(team, sprint_id) under sprints/ (unreadable state.json
  fallbacks to sprint_dir.name — preserve-on-doubt safety posture).
  Calls find_zombie_worktrees(worktrees_root, max_age_days=30,
  active_branches=active_branches) then gc_zombies(zombies, team_name=...,
  bus=get_event_bus()) emitting one ZombieWorktreeGced per deletion.
  Appends per-team zombies_removed + active_branches_preserved + disk_usage
  report to gc_summary["teams"]; combined dict {**checks, "gc": gc_summary}
  dispatched via _output for both --json and human branches.

- Human renderer extension: after the existing tool-checklist render,
  prints "GC complete: N zombie worktree(s) removed across M team(s)"
  then per-team line with disk_usage gb + over_soft/over_hard color tag
  (green ok / yellow over-soft / red over-hard).

- Safety invariant (07-RESEARCH §Pitfall 6): active SprintState
  workspace_branches preserved regardless of worktree age. Test
  test_doctor_gc_respects_active_sprints locks this contract.

Tests: tests/test_doctor_gc.py 4 passed + tests/test_doctor.py 6 passed
+ tests/test_doctor_new_entries.py 22 passed + tests/workspace/ 13 passed
= 45 passed total (BC + new, no regressions).

Closes Plan 07-08 Task 2; ROADMAP §Phase 7 SC HKUDS#10 (zombie worktree GC)
closed for the doctor-entry half. Wave 5 Plan 07-08 complete.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
juntaochi added a commit to novix-science/ClawTeam-gstack that referenced this pull request Apr 27, 2026
- .planning/phases/07-parallel-sprints-attentionqueue-ux-cost-controls/07-08-SUMMARY.md (new)
  Documents both tasks, 2 deviations (Rule 3 cross-executor stash on
  Task 1 GREEN + Rule 1 fixture mtime bump), interface surface for
  Plan 07-09, 17 tests green, self-check passed.
- .planning/STATE.md status/stopped_at/Current Position/session/decisions/metrics
  advanced for 07-08; completed_plans 73 -> 74 (96%).
- .planning/ROADMAP.md Phase 7 plans table marks 07-08 complete; progress
  row flipped from 6/9 (Wave 4) to 8/9 (Wave 5 — only 07-09 load test remains).

ROADMAP §Phase 7 SC HKUDS#10 (zombie-worktree auto-GC + 5 GB/10 GB disk budget)
CLOSED for the doctor-entry half. Sprint-spawn-time auto-GC deferred to
v1.x per scope boundary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
juntaochi added a commit to novix-science/ClawTeam-gstack that referenced this pull request Apr 27, 2026
The Phase 7 GC pass previously scanned teams/<team>/worktrees/ — a
directory WorkspaceManager never writes to. Real worktrees live at
<data_dir>/workspaces/<team>/<agent>/ (workspace/manager._workspaces_root).
Net effect: every production invocation of clawteam doctor --gc
reported total_zombies=0 even with real zombies on disk; Phase 7 SC HKUDS#10
was silently unmet. Exposed workspaces_root() as a public accessor,
switched the CLI scan root to workspaces/<team>/, and rewrote
tests/test_doctor_gc.py to build worktrees under the production layout
so the test now exercises the shipped path rather than a parallel one.
Team discovery now unions teams/ and workspaces/ directories so stale
workspaces without a matching teams/ entry are still GC'd.

Active-branch safety filter refinement to active_agents (IN-07) is
deferred; this commit fixes the scan path only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
juntaochi added a commit to novix-science/ClawTeam-gstack that referenced this pull request Apr 27, 2026
User request: "用tmux hook 把prompt注入进每一轮对话 包括身份和需要用的
skill 或者用tmux hook去做一些别的事情 总之tmux hook会是一个很好的技术".

Concept: agents drift over long sessions. CEO forgets to delegate (user
just hit this bug), engineer forgets which `clawteam` subcommands are
available, shipper forgets that `/ship` lives in the framework. A
periodic re-injection of "you are X; here's what you should use"
keeps them anchored.

Implementation:

1. `clawteam nudge <pane_id>` CLI command (new clawteam/nudge.py):
   - Looks up pane_id → session → team → agent via the persisted
     tmux_pane_map.json
   - Debounces (60s cooldown per pane) so repeated silence-hook firings
     don't spam the claude TUI
   - Reads the latest sprint state (current_phase + goal) for context
   - Builds a role-specific reminder text from _ROLE_NUDGES table
     (each role gets 2-3 lines: what you ARE + what commands you CAN
     run now). Appends "Goal: X · Phase: Y" when available.
   - Injects via `tmux send-keys -l <text>` + `send-keys Enter` so
     claude processes it as a user turn.
   - Silent-fail on any error (a noisy hook drowns the user's tmux).

2. tmux hook wiring (tmux_backend.py::_configure_nudge_hook):
   - `monitor-silence = 45s` on each window
   - `alert-silence` hook fires `clawteam nudge #{pane_id}` in the
     background (`run-shell -b`)
   - Opt-out via `CLAWTEAM_NUDGE_SECONDS=0` env var
   - Called from both `TmuxBackend.tile_panes()` (happy path) and
     `TmuxBackend.enable_mouse()` (the --windows non-tiled path) so
     every team gets nudge wiring regardless of layout choice.

3. pane_map normalization (tmux_backend.py::tile_panes):
   - Post-layout readback of pane_title returned claude's dynamic
     status strings like "⠐ CEO" / "✢ ENG-MGR" (spinner glyphs prefix).
   - Normalize by matching uppercase title content against the
     pre-merge window roster (roster_upper dict). Any title containing
     a known role (e.g. "⠐ CEO" contains "CEO") maps to the canonical
     lowercase role name.
   - pane_map.json now reliably stores {"0": "ceo", "1": "pm", ...}
     regardless of what claude's currently showing.

Real-env verified:
  clawteam go --no-attach --no-window "test"
  cat ~/.clawteam/teams/<team>/tmux_pane_map.json  → clean lowercase roster
  clawteam status                                    → Panes: 0=ceo 1=pm ...
  # wait for claude to boot
  clawteam nudge --force <pane_id>                   → injects role reminder
  tmux capture-pane                                  → sees "[nudge] Reminder:
                                                      you DELEGATE, never
                                                      implement. Decompose..."

Future uses of this hook infrastructure (brainstormed but not impl):
  - HKUDS#3 pane-died → log death reason, optional respawn
  - HKUDS#5 alert-activity → append pane output to activity.jsonl timeline
  - HKUDS#6 session-created → broadcast phase+goal to all panes
  - HKUDS#7 send-keys filter → intercept dangerous commands (rm -rf, force push)
  - HKUDS#10 pipe-pane → validate agent envelope JSON against schema

Tests: 30 solo/spawn_cli still green (nudge unit tests not added yet
— next commit candidate).

Co-Authored-By: Claude Opus 4.7 (1M context) <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.

2 participants