Commit graph

4 commits

Author SHA1 Message Date
Ouroboros
55b7113b75 plan-review: merge answers by finding_id; answer and review in one call; drop the automatic delta
A reviewer's question or objection reached the author, but the author's answer could not
travel back as a normal move: a second review_disposition call REPLACED the wave's whole
answer list (8 of 9 answers were lost on one live wave), answering and re-asking in one
call was refused as PLAN_REVIEW_DISPOSITION_MIXED_ENVELOPE (21 refusals in 7 tasks), items
beside an author finish were refused, and the host bought a delta panel by itself whenever
every blocking finding carried a valid reject (a path that ran 0 times in production).

Now answers MERGE by finding_id across calls (plan_spec.merge_dispositions: a later answer
supersedes only its own id; two entries for one id in ONE call stay contradictory and the
closure table keeps the finding open), both in the engine's closure/exact artifact and in
the durable writer under its lock. An envelope sent beside review_disposition items is
validated FIRST through the read-only prepare seam (an invalid envelope records nothing,
so the answered wave stays current), the answers are recorded merged, and the envelope is
then reviewed with them in view (_apply_disposition(then_review=...)). An author finish or
stop carries its items: they are validated against the critic wave and recorded before
the author source; the kept guard (finish while reviewers run) still refuses and writes
nothing. The automatic earned delta and plan_spec.blocking_fully_rejected are deleted: an
identical envelope without items always replays free, and re-judgement is the mind's
explicit move.

Owner authority: DECISIONS "Communication" item 2 (communication is an option, not an
obligation; reuse surfaces, no if-else); D4 with Q-v = A; "Blocking installs: no skip".
_apply_disposition is split into _disposition_items and _record_disposition so the author
path reuses them. task_results.py stays under its hard line cap (1596/1600).

Tests: tests/test_plan_review_answer_channel.py (merge across calls, supersede-own-id,
same-call duplicate, durable writer, author finish with items, refused finish writes
nothing, unknown id beside a finish, invalid envelope records nothing, changed envelope
with items reviews every slot with the rationale in PRIOR CYCLES); plan_spec units for
merge_dispositions; the MIXED-envelope pins rewritten to the validate-first form; the
earned-delta tests deleted or rewritten as "replay is free until the mind addresses".

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-26 20:35:59 +03:00
Ouroboros
a5413fae1d Bind author choices to received reviews and preserve truthful projections 2026-09-18 13:22:00 +03:00
Ouroboros
becededcb7 Preserve typed failures across built-in plan, image and GitHub tools (#739)
A built-in tool that already knows its call failed must leave the registry
a typed result. The legacy adapter types a string by its first-line
`⚠️ IDENTIFIER` marker, so identifier-less prose and bare `ERROR:` strings
were recorded as successful calls in tools.jsonl, the outcome classifier
and the acceptance packet.

- plan_task: a schema-equivalent empty optional field (blank goal/plan,
  `{}` or a spec of declared keys holding [] / "") beside a real disposition
  no longer reads as a mixed envelope; a non-empty list, unknown key or
  wrong type still refuses typed. Every plan-review refusal publishes typed
  (argument vs state), and `_plan_unavailable` splits faults (error) from
  availability outcomes such as a budget-declined panel (unavailable).
- view_image / vlm_query: the local image loader publishes its own
  refusals as TOOL_ARG_ERROR; policy markers keep their owners' typing; the
  host's auto-attach stays non-fatal outside a registry call.
- GitHub: `_gh_run` returns a structured result (exit code, bounded and
  redacted stderr head, gh's own `(HTTP NNN)` marker read before bounding,
  failure class); `_gh_cmd` keeps the string ABI and its typed target
  refusals. Publication carries error_detail / github_status /
  github_operation beside the stage code and through the structured
  attempt projection; hints state producer facts and name Settings →
  Secrets; mandatory fork sync still stops before any mutation and PR
  settlement stays a read-only exact lookup.
- tests/test_typed_tool_refusals.py: shrink-only source lint over returned
  failure literals in ouroboros/tools (oracle: the real adapter); its
  allowlist is the disclosed residual for the other packages.
- docs: DEVELOPMENT (typed-refusal rule, plan closure), ARCHITECTURE
  (vision, skill publication, github.py row).
2026-09-08 16:16:24 +03:00
Ouroboros
ccbb933a95 v7next F3.1 lane A: loop cutover to published ToolResult codes, typed extension/MCP dispatch, T1 outcome partition (D02/D04/D14/D15)
Re-derived on tip bytes; oracle v7_wip @ 9f691656 is the structural contract.

- loop_tool_execution (rows 157-164, 826-828): the retired result-text
  classifiers (_FAILURE_PREFIXES/_FAILURE_MARKERS/_EXIT_CODE_RE/_SIGNAL_RE and
  the elif ladder) are gone; status/is_error and the process/plan facts are
  READ from the dispatcher's published ToolResult (ABI-6(b): the unreachable
  _typed_or_adapted branch is NOT reproduced — the loop holds the typed result,
  text-only callers get the ONE adapter through compatibility wrappers).
  trace rows carry tool_result_status/code/meta alongside the legacy fields.
- extension_dispatch (D04 entry 5, rows 187/188) ADOPTED WHOLE from the
  reference WITH BYTE PROOF (tip == merge-base == v6.64.0 for this file, md5
  4e9ad3ba, so reference == tip+delta exactly): _dispatch_extension_tool_result
  / _dispatch_mcp_tool_result / _extension_dispatch_candidate produce native
  EXTENSION_*/MCP outcome facts; dispatch_extension_tool stays the text
  projection. registry_core retires the ToolRegistry dispatch methods and the
  hoisted candidate; the dead-extension unknown-name answer is typed
  EXTENSION_UNAVAILABLE (helper extracted per the function-size law).
- extension_process_runner (D14 entry 10): ExtensionProcessError gains
  failure_kind ('timeout' at the deadline kill) consumed by the typed
  dispatcher's EXTENSION_TIMEOUT arm.
- _outcome_tool_errors T1-partition (D15 entries 3-4, re-derived against the
  upstream status handling): every produced status is homed by its nearest
  analogue; tool_reported_failure and unavailable are policy-denial-partitioned
  (spec 1.15) while argument_error stays a real failure; retired codes'
  status names survive for stored traces; _UNPARTITIONED_BUCKETS makes the
  deliberate vlm_error hole explicit; untyped joins _OK_TOOL_STATUSES.
- reflection (row 166): the 4 CLAUDE_CODE markers retire (0 emitters, pinned
  by a repo scan test); _trace_call_errored reads the ok-status SSOT so
  untyped/ok_autocorrected successes stop triggering error reflections.
- plan-review typed control: _parse_plan_review_control moves to plan_render
  (its render-side home); publish_plan_review_projection/publish_rendered_wave
  emit the typed plan result whose meta the loop trusts (wave_control_state is
  the same projection the rendered footer reads); the plan handler pool-hops
  through contextvars.copy_context so the sidecar publication reaches the
  dispatching thread (reference delta, tip timeout design kept).
- tools/git facade re-exports _publish_git_error/_publish_review_blocked.
- Carried suites adapted to this tree (docstring/comment disclosures at each
  non-verbatim spot): test_tool_result{,_meta_boundaries,_t46}, test_registry_core,
  test_registry_guard_process, test_process_guard_codes, test_tool_catalog,
  test_tool_classification_differential + corpus + legacy fixture; the two
  loop_misc structured-failure tests re-home into the classification suite.
  Notable adaptations: facade keeps the broad historical surface (AST 'defines
  nothing' pin replaces the reference's exact-32 vars equality); guard patch
  points follow the _registry() call-time handle; the strict managed-update
  resolver is pinned with its corrupt-marker A4 channel; SCOPE_REVIEW_FLOOR
  rows dropped (ABI-5, Q10=A).
- ARCHITECTURE.md same-commit delta (extension_dispatch + loop rows); size
  ratchet regenerated officially (test_tool_result.py enters the band with
  rationale); ruff F clean; -m size_ratchet 5 passed.

(cherry picked from commit c12800b3cf320490f59f1d2532fa45ce62e9486a)
2026-08-31 18:05:03 +00:00