Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .beads/interactions.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@
{"id":"int-47f29fcd4eb72c055882d94bfa857cc9","kind":"field_change","created_at":"2026-07-03T03:42:55.3794412Z","actor":"gerso","issue_id":"bd-6dn","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented on claude/manager-mode-followups (a1d4fad, 6333777), merged into PR #111 (open, awaiting director merge); 702 tests green"}}
{"id":"int-55233ecb5ca93873ebc945f863041274","kind":"field_change","created_at":"2026-07-03T03:42:56.5445665Z","actor":"gerso","issue_id":"bd-a63","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Investigation complete: 4-conflict map + landing sequence in scratchpad hub-reconcile-report.md; execution requires hub session (31 unpushed commits + 1.9k uncommitted lines)"}}
{"id":"int-b72aacf782dcdef7443894371b161eb6","kind":"field_change","created_at":"2026-07-06T15:51:44.4304982Z","actor":"gerso","issue_id":"bd-dm3","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"All 14 punch-list items resolved: L1 autouse _sandbox_home fixture, L2 quickstart project-root knowledge wiring, L3 --explain+--json JSON payload, L4 dotted-stem .md fallback, L5 expanduser on knowledge roots, L6 strict missing-root issue, L7 knowledge CLI docs section, L8 talent-manager alias claims deleted, L9 posix report_path, L10 dynamic warnings before static caveats, L11 reference count 20 synced, L12 mid-run backend-error semantics documented+tested, L13 golden-test env isolation, L14 writability caveat documented. Full-suite A/B confirmed zero regressions (175 pre-existing Windows-env failures identical at baseline)."}}
{"id":"int-06334511e4a7ee5bd6f72837d144a7cd","kind":"field_change","created_at":"2026-07-06T16:28:12.7195047Z","actor":"gerso","issue_id":"bd-6z9","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed on claude/adversarial-fix-wave (8a183a5..5dc5cc2); all 16 items verified FIXED by fable xhigh adversarial gate with pre-fix test-failure proof"}}
{"id":"int-a5dba7326af80aa10e526671c1ef9dbe","kind":"field_change","created_at":"2026-07-06T16:28:12.8863553Z","actor":"gerso","issue_id":"bd-5mq","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed on claude/adversarial-fix-wave (8a183a5..5dc5cc2); all 16 items verified FIXED by fable xhigh adversarial gate with pre-fix test-failure proof"}}
{"id":"int-33199b717ee0a725eb6966299717046e","kind":"field_change","created_at":"2026-07-06T16:28:13.0518024Z","actor":"gerso","issue_id":"bd-85c","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed on claude/adversarial-fix-wave (8a183a5..5dc5cc2); all 16 items verified FIXED by fable xhigh adversarial gate with pre-fix test-failure proof"}}
{"id":"int-1f2255c088aeaa55a294239ba5db4505","kind":"field_change","created_at":"2026-07-06T16:28:13.2106971Z","actor":"gerso","issue_id":"bd-6cr","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed on claude/adversarial-fix-wave (8a183a5..5dc5cc2); all 16 items verified FIXED by fable xhigh adversarial gate with pre-fix test-failure proof"}}
{"id":"int-6ce0f88e17f0bd8bac20d0636da07030","kind":"field_change","created_at":"2026-07-06T16:28:13.3781988Z","actor":"gerso","issue_id":"bd-j9f","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed on claude/adversarial-fix-wave (8a183a5..5dc5cc2); all 16 items verified FIXED by fable xhigh adversarial gate with pre-fix test-failure proof"}}
{"id":"int-c91c0187ad5d3b0cb3232ce7980984c6","kind":"field_change","created_at":"2026-07-06T16:28:13.5388979Z","actor":"gerso","issue_id":"bd-c40","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed on claude/adversarial-fix-wave (8a183a5..5dc5cc2); all 16 items verified FIXED by fable xhigh adversarial gate with pre-fix test-failure proof"}}
{"id":"int-4f5b85d4000aeccc178776da055232d0","kind":"field_change","created_at":"2026-07-06T21:40:04.2735651Z","actor":"gerso","issue_id":"bd-2hs","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed on claude/adversarial-fix-wave: conditional post-loop save in start() per fable consult ruling; OCC test green, team_readiness persistence proven covered"}}
{"id":"int-20cf10206ee551c564520b299b9cf8ea","kind":"field_change","created_at":"2026-07-06T21:45:23.9779044Z","actor":"gerso","issue_id":"bd-ftd","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Docs synced on claude/adversarial-fix-wave commit for bd-ftd; agent also closed two pre-existing doc holes (forge 422s undocumented, baton doctor absent from cli-reference)"}}
{"id":"int-a18184d525369f5ee8a65d63deef9954","kind":"field_change","created_at":"2026-07-06T23:17:53.1621743Z","actor":"gerso","issue_id":"bd-rbt","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Tests made hermetic via KeywordClassifier injection per established pattern; production code correct. 3 tests green, planning suites 209 passed."}}
{"id":"int-934a4d09e996ae26efdcc92d16e1b860","kind":"field_change","created_at":"2026-07-06T23:47:30.1835886Z","actor":"gerso","issue_id":"bd-pz4","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed in two parts: RiskStage presence-based Review/Audit slot guarantee (2720191) + decomposition override-path roster/phase coupling per fable consult adjudication. e2e 18/18, planning 211 green, fan-out guard contract preserved."}}
5 changes: 5 additions & 0 deletions agent_baton/api/routes/pmo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2314,6 +2314,11 @@ async def forge_signal(

try:
plan = forge.signal_to_plan(signal_id=signal_id, project_id=req.project_id)
except PlanQualityError as exc:
raise HTTPException(
status_code=422,
detail=plan_quality_error_detail(exc),
) from exc
except Exception as exc:
raise HTTPException(
status_code=500,
Expand Down
52 changes: 44 additions & 8 deletions agent_baton/cli/commands/diagnostics_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -790,12 +790,30 @@ def _check_terminology() -> DoctorCheck:
)


def _with_fallback_caveat(message: str, details: dict[str, Any]) -> str:
"""Append a caveat when the plan came from an unguided fallback guess.

Only applies once a plan was actually found (``plan_path`` set) — a
``fallback-first-found`` selection with no plan at all is just "no plan",
not a guess worth flagging.
"""
if details.get("plan_selection") == "fallback-first-found" and details.get(
"plan_path"
):
return (
f"{message} (caveat: no active task resolved; validating the "
"first saved plan found, not necessarily the current one)"
)
return message


def _check_planner_validation(project_root: Path) -> DoctorCheck:
plan_candidates = _saved_plan_candidates(project_root)
plan_path, active_task_state = _select_saved_plan_for_validation(project_root)
details: dict[str, Any] = {
"active_task_id": active_task_state["active_task_id"],
"active_task_source": active_task_state["active_task_source"],
"plan_selection": active_task_state["plan_selection"],
"plan_candidates": [str(path) for path in plan_candidates],
"plan_path": None,
"machine_plan_importable": False,
Expand Down Expand Up @@ -865,7 +883,9 @@ def _check_planner_validation(project_root: Path) -> DoctorCheck:
id="planner_validation",
label="Planner validation",
status="error",
message=f"Saved plan could not be parsed: {exc}",
message=_with_fallback_caveat(
f"Saved plan could not be parsed: {exc}", details
),
details=details,
)

Expand All @@ -878,7 +898,9 @@ def _check_planner_validation(project_root: Path) -> DoctorCheck:
id="planner_validation",
label="Planner validation",
status="error",
message="Saved plan JSON has invalid top-level shape",
message=_with_fallback_caveat(
"Saved plan JSON has invalid top-level shape", details
),
details=details,
)

Expand All @@ -891,7 +913,9 @@ def _check_planner_validation(project_root: Path) -> DoctorCheck:
id="planner_validation",
label="Planner validation",
status="error",
message=f"Saved plan validation could not run: {exc}",
message=_with_fallback_caveat(
f"Saved plan validation could not run: {exc}", details
),
details=details,
)

Expand All @@ -912,9 +936,10 @@ def _check_planner_validation(project_root: Path) -> DoctorCheck:
id="planner_validation",
label="Planner validation",
status="error",
message=(
message=_with_fallback_caveat(
f"Saved plan validation found {error_count} errors and "
f"{warning_count} warnings"
f"{warning_count} warnings",
details,
),
details=details,
)
Expand All @@ -923,14 +948,18 @@ def _check_planner_validation(project_root: Path) -> DoctorCheck:
id="planner_validation",
label="Planner validation",
status="warning",
message=f"Saved plan validation found {warning_count} warnings",
message=_with_fallback_caveat(
f"Saved plan validation found {warning_count} warnings", details
),
details=details,
)
return DoctorCheck(
id="planner_validation",
label="Planner validation",
status="ok",
message="Saved plan validation passed with no findings",
message=_with_fallback_caveat(
"Saved plan validation passed with no findings", details
),
details=details,
)

Expand Down Expand Up @@ -1062,6 +1091,7 @@ def _select_saved_plan_for_validation(
"active_task_id": active_task_id,
"active_task_source": active_task_source,
"active_plan_missing": False,
"plan_selection": "active-task" if active_task_id else "fallback-first-found",
**active_task_details,
}
if active_task_id:
Expand Down Expand Up @@ -1097,7 +1127,13 @@ def _resolve_active_task_for_validation(
def _read_active_task_id_from_sqlite(
context_root: Path,
) -> tuple[str | None, dict[str, Any]]:
db_path = context_root / "baton.db"
# Honour BATON_DB_PATH (mirrors bead_cmd._resolve_db_path's override
# precedence) so doctor probes the same DB the rest of the CLI uses.
override = os.environ.get("BATON_DB_PATH", "").strip()
if override:
db_path = Path(override).expanduser().resolve()
else:
db_path = context_root / "baton.db"
from agent_baton.core.storage.active_task import (
read_active_task_id_from_db_copy,
)
Expand Down
13 changes: 13 additions & 0 deletions agent_baton/cli/commands/execution/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from agent_baton.cli.errors import user_error, validation_error
from agent_baton.core.engine.errors import ExecutionVetoed
from agent_baton.core.engine.executor import ExecutionEngine
from agent_baton.core.engine.team_backends import UnknownTeamBackendError
from agent_baton.core.engine.persistence import StatePersistence
from agent_baton.core.events.bus import EventBus
from agent_baton.core.storage import get_project_storage
Expand Down Expand Up @@ -804,6 +805,18 @@ def _print_action(action: dict, *, terse: bool = False) -> None:


def handler(args: argparse.Namespace) -> None:
# UnknownTeamBackendError can surface from any engine call that walks a
# team step (start / next / resume / run) when BATON_TEAMS_BACKEND is
# unknown under BATON_TEAMS_BACKEND_STRICT=1. Catch it at the command
# entry so the CLI prints a clean message (matching the API's str(exc)
# mapping) and exits non-zero instead of surfacing a traceback.
try:
_dispatch(args)
except UnknownTeamBackendError as exc:
user_error(str(exc))


def _dispatch(args: argparse.Namespace) -> None:
if args.subcommand is None:
# bd-8944: consolidated single validation_error with the full list of
# registered subcommands (removed stale duplicate that was unreachable).
Expand Down
Loading