{"record":{"id":"9726e927f1728999","repo":"HKUDS/Vibe-Trading","slug":"not-applicable-criteria-require-acceptance-notes","errorCode":null,"errorMessage":"not-applicable criteria require acceptance notes","messagePattern":"not-applicable criteria require acceptance notes","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/goal/store.py","lineNumber":917,"sourceCode":"    def _validate_completion_audit(\n        self,\n        goal: GoalRecord,\n        audit: list[AuditRow],\n    ) -> None:\n        criteria = self.list_criteria(goal.goal_id)\n        rows_by_criterion = {row.criterion_id: row for row in audit}\n        for criterion in criteria:\n            if not criterion.required:\n                continue\n            row = rows_by_criterion.get(criterion.criterion_id)\n            if row is None:\n                raise ValueError(f\"missing audit row for criterion {criterion.criterion_id}\")\n            if row.result not in _COMPLETION_RESULTS:\n                raise ValueError(f\"criterion {criterion.criterion_id} is not satisfied\")\n            if row.result in {\"satisfied\", \"satisfied_with_caveat\"} and not row.evidence_ids:\n                raise ValueError(\"complete goals require verified evidence\")\n            if row.result == \"not_applicable_user_accepted\" and not row.notes.strip():\n                raise ValueError(\"not-applicable criteria require acceptance notes\")\n            has_verified_evidence = False\n            for evidence_id in row.evidence_ids:\n                evidence = self._get_evidence(evidence_id)\n                if evidence is None or evidence.goal_id != goal.goal_id:\n                    raise ValueError(f\"unknown evidence_id: {evidence_id}\")\n                if evidence.criterion_id != criterion.criterion_id:\n                    raise ValueError(\n                        f\"evidence {evidence_id} does not match criterion {criterion.criterion_id}\"\n                    )\n                if evidence.verification_status == \"verified\":\n                    has_verified_evidence = True\n            if row.result in {\"satisfied\", \"satisfied_with_caveat\"} and not has_verified_evidence:\n                raise ValueError(\"complete goals require verified evidence\")\n\n    def _get_evidence(self, evidence_id: str) -> EvidenceRecord | None:\n        row = self._conn.execute(\n            \"SELECT * FROM goal_evidence WHERE evidence_id = ?\",\n            (evidence_id,),","sourceCodeStart":899,"sourceCodeEnd":935,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/goal/store.py#L899-L935","documentation":"An audit row used result not_applicable_user_accepted but its notes field was empty or whitespace. Waiving a criterion requires a recorded user-acceptance rationale.","triggerScenarios":"update_status with AuditRow(result=\"not_applicable_user_accepted\", notes=\"\" or \"   \") for a required criterion.","commonSituations":"Programmatically marking criteria N/A without capturing the user's reason; notes field omitted by a dataclass default; LLM-generated audit forgetting notes.","solutions":["Populate notes with the concrete reason the user accepted skipping the criterion","If the criterion is actually satisfied, use satisfied with evidence ids instead","Validate non-empty notes for N/A rows before calling update_status"],"exampleFix":"// before\nAuditRow(criterion_id=\"c2\", result=\"not_applicable_user_accepted\", notes=\"\", evidence_ids=[])\n// after\nAuditRow(criterion_id=\"c2\", result=\"not_applicable_user_accepted\", notes=\"User accepted: out of scope for this run\", evidence_ids=[])","handlingStrategy":"validation","validationCode":"for row in audit:\n    if row.result == \"not_applicable_user_accepted\":\n        assert row.notes and row.notes.strip(), f\"{row.criterion_id} N/A without notes\"","typeGuard":"def na_rows_have_notes(audit: list) -> bool:\n    return all(r.notes.strip() for r in audit if r.result == \"not_applicable_user_accepted\")","tryCatchPattern":"except ValueError as e: if 'acceptance notes' in str(e): collect the user's rationale, set notes, retry","preventionTips":["Capture the acceptance reason in the same interaction that waives the criterion","Treat notes as mandatory metadata for N/A decisions","Prompt explicitly for rationale when LLMs assemble audits"],"tags":["goal-store","completion-audit","acceptance-notes","python"],"backgroundTag":"missing-required-field","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}