fix(doctor): close review findings F1/F5/F6/F2/F7 — evidence, ledgers, YAML, verify surface, file targets - #27
Merged
Merged
Conversation
_check_terminal_contradiction checked false_completion and criteria_met but never evidence, so a schema-valid Succeeded terminal with an empty evidence[] passed doctor in both validation modes — a success claim with nothing behind it. Mirror the write-time refusal in loop/emit.py: a Succeeded terminal now requires a non-empty evidence list, emitting a contradictory_terminal issue otherwise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ode jsonl F5a: _validate_optional_records globbed every .loop/*.jsonl and validated each as a rollout@1 record, so a foreign notes.jsonl false-FAILed an otherwise healthy contract. Validate only the canonical rollout ledger (rollout.jsonl) and skip unknown jsonl; "rollout" enters schemas_checked only when that ledger was actually validated. F5b: _validate_jsonl read with errors="ignore", so a ledger line carrying raw 0xff bytes decoded lossily and silently validated clean (a false PASS). Decode strictly and fail the file closed with an invalid_encoding issue on UnicodeDecodeError. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ments
_fallback_yaml did raw.split("#", 1)[0] first, so goal: "reach #1" truncated to
'"reach' — a '#' inside a quoted scalar was treated as a comment. Add
_strip_comment, which cuts a trailing comment only when the '#' is unquoted and
(YAML-style) at line start or after whitespace, so a quoted '#' survives and the
fallback agrees with PyYAML.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lves doctor never noticed a loop with no verification surface: deleting every scripts/verify-* left it green, and a task whose verify pointed at a nonexistent script was never existence-checked. Add _check_verify_surface, run in both modes: flag missing_verify_surface when no verify-* script exists and no task declares a verify command, and unresolved_task_verify when a task verify's first token is path-shaped but does not resolve under the workspace. Plain commands like pytest -q are not path-checked. _check_stub_verify_scripts is unchanged; its docstring now states the stub markers are an opt-in convention. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_workspace_from only handled directory targets, so `loop doctor .loop/state.json` or a root-level TASKS.json resolved the workspace to the file itself and every path underneath it was garbage (a wall of missing_file issues). When the target is an existing file, resolve from its parent directory: .loop/state.json now resolves to the owning workspace, and a root-level TASKS.json to the workspace root — matching the directory-target report. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This was referenced Jul 8, 2026
SollanSystems
added a commit
that referenced
this pull request
Jul 8, 2026
* feat(st2): the contract is a versioned, tool-agnostic standard Promote reference/repo-os-contract.md to the normative spec: stability note and versioning model (§0), artifact/schema table across all 7 published schemas with required keys verbatim from schemas/ (§11), lifecycle vocabulary + terminal-file-iff rule (§12), repair-record vs rollout-record two-shape clarification (§13), and the A1-E1 conformance checklist (§14). - doctor lifecycle line: validate_contract reports lifecycle: planned | running | terminated:<State> | unknown — additive reporting only, never an issue source; DG-3 regressions pin both directions in both validation modes. - scripts/test_template_roundtrip.py: every templates/* artifact, filled with schema-valid values, passes validate_contract with zero issues in both modes (in-flight + terminated scaffolds). - scripts/test_conformance.py: executes checklist A1-E1 in CI against examples/coverage-repair and a fresh template scaffold, incl. additive-key tolerance (D2), lifecycle honesty (E1), and a doc-parity guard binding every checklist ID to the normative doc. - README: pointer subsection for the versioned standard. ST2 spec: docs/superpowers/specs/2026-06-30-st2-portable-contract-spec.md (DG-1/DG-2/DG-3-core/M5/QW11 had already landed via #27-#30). Suite: 372 passed / 10 skipped (jsonschema), 361 / 21 (structural). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(release): cut 0.7.0 — portable standard CHANGELOG 0.7.0 collects the ST2 standard work, the adoption slices (A1/B1/C1/PR5, previously Unreleased), and the external-review patch set #27-#30 (previously unchangelogged). Version 0.6.1 -> 0.7.0 in pyproject.toml, plugin.json, README badge + Status; docs-version gate updated. The README Adopt-section @v0.7.0 action pin becomes accurate at this release's tag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the doctor-side enforcement gaps confirmed from the external review (findings F1, F5, F6, F2, F7). Every fix was pinned with a failing test reproducing the exploit first, then verified adversarially against the original repros plus variants in both validation modes (structural-fallback and jsonschema).
evidence[]now fails doctor in both modes (contradictory_terminal), mirroring the write-time G1 check inloop/emit.py. The one touched fixture previously encoded the exploit (asserted an evidence-free Succeeded validated clean)..loop/rollout.jsonl) asrollout@1; a foreign.loop/notes.jsonlno longer false-FAILs a healthy contract.rolloutentersschemas_checkedonly when actually validated.invalid_encodinginstead of silently passing undererrors="ignore".#inside quoted scalars (goal: "reach #1") and now agrees with the PyYAML path.missing_verify_surface) and a path-shapedtask.verifythat doesn't resolve (unresolved_task_verify). Plain commands (pytest -q) are not path-checked. Fresh-scaffold-doctor-clean invariant preserved (stub-marker substance grading stays in the inspector, per the triage correction).loop doctor .loop/state.json) resolves to its owning workspace instead of producing garbage paths.Test plan
examples/coverage-repairdoctor-clean (both modes)🤖 Generated with Claude Code