diff --git a/curllm_core/autonomy.py b/curllm_core/autonomy.py index 69bbc61..ac9ec4f 100644 --- a/curllm_core/autonomy.py +++ b/curllm_core/autonomy.py @@ -151,11 +151,13 @@ def run_command(spec: dict, repository: Path) -> dict: if ok and spec.get("oracle", "exit") == "json": try: result = json.loads(raw) + status = result.get("status") if isinstance(result, dict) else None # A zero exit code does not prove the application's semantic result. ok = (isinstance(result, dict) and result.get("success") is True and not result.get("error") and not result.get("errors") and not result.get("failed") - and result.get("status") not in {"failed", "error"}) + and (status is None or (isinstance(status, str) + and status not in {"failed", "error"}))) except (ValueError, UnicodeError): ok = False code = "passed" if ok else "semantic_failed" diff --git a/project/ticket-007/README.md b/project/ticket-007/README.md new file mode 100644 index 0000000..ebc1376 --- /dev/null +++ b/project/ticket-007/README.md @@ -0,0 +1,15 @@ +# Malformed probe status + +- **Owner**: agent:codex +- **Status**: IN_PROGRESS +- **Workflow state**: PUBLICATION +- **Workstream**: application + +SESSION_EXECUTION_AUTHORIZATION: continuous improvement, tests, repairs and deployment authorized by user on 2026-10-06; STARTER-019 records reproduced malformed JSON failure after frozen PR12. Preserve that publication and fix in this bounded slice. + +## Acceptance criteria + +- [x] AC-01: Invalid JSON status types become semantic failure; monitor cycle continues. +- [x] AC-02: Native gate and autonomy regressions pass. + +Validation: four new adverse-result regressions failed before repair; 30 autonomy tests passed after repair (8.81s). Native gate passed without errors/warnings. diff --git a/project/ticket-007/intent.json b/project/ticket-007/intent.json new file mode 100644 index 0000000..a5ee727 --- /dev/null +++ b/project/ticket-007/intent.json @@ -0,0 +1,84 @@ +{ + "schema": "new-project.intent/v3", + "ticket": "ticket-007", + "summary": "Classify malformed probe status without interrupting autonomy", + "workstream": "application", + "classification": { + "kind": "BUG", + "priority": "P1", + "origin": "requested" + }, + "allowedPaths": [ + "project/ticket-007/**", + "TODO.md", + "project/TICKETS.md", + "curllm_core/autonomy.py", + "tests/test_autonomy.py" + ], + "forbiddenPaths": [ + "project/ticket-*/user-*.md" + ], + "stacks": [], + "dependsOn": [ + "ticket-006" + ], + "conflictsWith": [], + "integrationTicket": null, + "delivery": { + "acceptedBaseSha": "473dcf782d67452a81da879830fde9927a4630b1", + "targetBranch": "main", + "outcome": "Publish malformed-result regression fix before continuous monitor deployment (STARTER-019).", + "nonGoals": [ + "No self-authorized source changes or review bypass", + "No edits to reference repositories", + "No interaction with user browser pages" + ], + "complexity": "XS", + "estimatedMinutes": 8, + "budgets": { + "maxImplementationFiles": 2, + "maxAffectedComponents": 1, + "maxPublicInterfaceChanges": 0, + "maxRuntimeDependencies": 0 + }, + "architecture": { + "status": "accepted", + "decision": "Validate JSON status type before semantic evaluation; malformed application results are failures, not monitor exceptions.", + "components": [ + { + "name": "autonomy-runtime", + "paths": [ + "curllm_core/autonomy.py", + "tests/test_autonomy.py" + ] + } + ], + "responsibilityChanges": false, + "interfaceChanges": [], + "dataChanges": [], + "ui": { + "impact": "none", + "states": [], + "evidence": [] + }, + "rollback": "Revert malformed-result guard." + }, + "runtimeDependencies": [], + "validation": [ + { + "criterion": "AC-01", + "commands": [ + "python -m pytest tests/test_autonomy.py -q" + ], + "evidence": "Malformed list, object, number and boolean status returns semantic_failed; monitor lifecycle remains functional." + }, + { + "criterion": "AC-02", + "commands": [ + "bash project/governance-check.sh --actor agent" + ], + "evidence": "Native gate passes." + } + ] + } +} diff --git a/tests/test_autonomy.py b/tests/test_autonomy.py index f4c7716..c7462d3 100644 --- a/tests/test_autonomy.py +++ b/tests/test_autonomy.py @@ -172,7 +172,9 @@ def test_concurrent_cycle_cannot_run_probe(tmp_path): @pytest.mark.parametrize("output", ['{"success":false}', '{"success":true,"errors":["bad"]}', - '{"success":true,"failed":1}', '{"status":"ok"}', 'not json']) + '{"success":true,"failed":1}', '{"status":"ok"}', 'not json', + '{"success":true,"status":[]}', '{"success":true,"status":{}}', + '{"success":true,"status":0}', '{"success":true,"status":false}']) def test_semantic_failure_with_zero_exit(output, tmp_path): spec = {"argv": [sys.executable, "-c", f"print({output!r})"], "oracle": "json"} result = run_command(spec, tmp_path)