Commit graph

13 commits

Author SHA1 Message Date
Ouroboros
aafaa37138 fix(tz2): close seven exact-range review findings (D15 quiz ingress, paid interruptions below adapters, action-only stop, suppressed-origin corpus, telegram card ordering, degraded reflection/promotion, split-root ceiling)
Repair batch authored by a delegated Claude Fable run; reproduced each finding via a failing test through the real seam.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-26 00:59:44 +03:00
Ouroboros
6d52bf4dea feat(tz2 B2): typed wake reasons (answer/owner_text/hurry/mail:<task_id>/timeout/control), no-rollback on a closed wait, one wake-notice seam warm and cold
Drafted by a delegated Claude Fable 5.1 session (run-4824fce9655c); patch read and applied by the host; 225 owner-wait/quiz/cancel tests pass.
2026-09-26 00:04:06 +03:00
Ouroboros
3f9fe1b654 WIP: preserve TZ-2 open-question and factual-terminal candidate
Keep this version-neutral contribution local. B1/B2/B3 and C1/C4/C5 are partial; C2/C3, exact diff review, full suite and PR are outstanding. Do not merge this checkpoint without final-candidate checks.
2026-09-25 06:03:38 +03:00
Ouroboros
af5336f2b1 fix(escalate): cede the wait-bound semantics to upstream, keep the typed refusal
Upstream landed its own answer to the same class while this branch was out
(f554260be, 4bc05ffb4): an optional question ignores a habit-filled bound, a
required wait REFUSES `0` and a bound past the task ceiling, and every refusal
names the repair. This branch had clamped instead of refusing and allowed `0`
as "no bound". Released, reviewed semantics win; nothing here re-opens them.

- core.py: the `max_wait_minutes` schema text returns to upstream's. Mine
  promised "pass 0 for no bound" and "lowered to the ceiling" — behaviour the
  code no longer has, and a schema must not promise what the code will refuse.
- core_artifacts.py: `_validate_wait_bound`, `_wait_bound_note` and the child
  receipt are upstream's. Kept from this branch: the quiz refusal is published
  through `argument_refusal` (typed `TOOL_ARG_ERROR` plus "The quiz was not
  sent.", so a refusal states what did NOT happen), and a blocked link stays a
  policy denial via its own marker. Both are orthogonal to the validation rule.
- tests: the assertions that pinned the dropped wording, the value-in-refusal
  and "0 waits unbounded / a huge bound is lowered" now pin upstream's actual
  contract. The tolerant path stays pinned on the OPTIONAL question, which is
  the affordance this class was about.
- inventories regenerated: both source docs merged from two sides, so neither
  side's recorded line range and SHA was still true.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-19 10:51:34 +03:00
Ouroboros
520a6f2e32 fix(tools): a filled optional argument that asks for nothing is not a refusal
Models fill every key of a tool schema. Five handlers refused the empty or
mode-irrelevant form of an optional argument with a text that restated the
rule, the retry kept the same key set, and several of those refusals were
recorded as successful calls, so neither the task nor its reflection could
locate the fault.

- escalate: a wait bound on a quiz that does not wait, or 0 on one that does,
  takes the omitted path and the receipt says so; a bound past the task ceiling
  is lowered to it; the ignored bound is never persisted with the quiz.
- knowledge_read: an end past the note is lowered to it, 0..0 reads the whole
  note, one bound alone is allowed; the returned range is the range delivered.
- delegate_wait: the empty pair (0, "") asks for no checkpoint and the wake
  says so; a half-filled pair is refused naming the missing half.
- schedule_followup: a zone beside an absolute run_at is ignored, disclosed
  and not stored.
- get_task_result source ranges: an invalid range still returns no text, now
  with the complete length and the range received, published as an argument
  error instead of ok.

The remaining refusals at these sites are published typed and name the value
received (tools/arg_feedback). The typed-refusal source lint now counts
interpolated marker returns per file, growth-only.
2026-09-19 10:42:28 +03:00
Ouroboros
4bc05ffb44 fix(escalate): review round 1 — say what really ends the shared wait, name the repair on every bound refusal
The description claimed the shared wait "ends on the first owner reply". Any
incoming message ends it (a descendant's message, a hurry, a system notice), so
it now says "the first incoming message"; 935 -> 932 bytes against the base,
and the catalog pin is rolled with that number.

The above-ceiling refusal now carries the same "omit it for an unbounded wait"
repair as the other invalid required bounds. The child's receipt discloses an
ignored bound in brackets instead of gluing a second period onto an assumption
that already ends with one. Tests pin the child path, the ceiling repair and
the consumer of the wait fields (the parked wait carries no bound).

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-19 03:01:40 +03:00
Ouroboros
f554260be4 fix(escalate): an optional question no longer trips over a habit-filled wait bound
A schema-filling model names max_wait_minutes on a question it does not wait
for. The validator refused that as a contradiction, and in the live log the
asker reacted by switching to blocking questions asked one by one. Naming the
documented default is not a different request: on an optional question the
bound now takes the omitted path and the receipt says it was ignored. A
required wait keeps its refusal, and both refusals now name their repair.

A bounded wait also leaked its deadline into a later unbounded question of the
same tool batch; the wait fields are now reset per question.

The tool description carries the criterion for waiting (irreversible or costly
next step, or a choice that is the owner's to make) and the one mechanical
fact that waiting questions in a batch share one wait. 935 -> 927 bytes.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-19 02:59:48 +03:00
Ouroboros
56198be6bb Consciousness: review round 5 fixes (execution verbs withheld at Observe, refusal debounce, closed-bound reconciliation)
- Observe does without skill_exec and run_ci_tests (an enabled skill's script; a branch
  push plus a workflow dispatch) — the two remaining built-in execution verbs.
- A refused wake launch debounces the next event like a skip does, so the backoff it
  armed is never undone on the next supervisor pass.
- The direct lane names the card's chat in the closed-bound frame; reconciling a replayed
  row into an existing card projects the closed bound too (a missed timeout frame).
- Docs: PERSISTENCE drops the retired observation fold; architecture/06 names the two
  round-4 gates the mode cap binds at; DESIGN describes the question pointer's states.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-16 12:22:17 +03:00
Ouroboros
8ab2d13ce8 Consciousness: review round 4 fixes (capped tree keeps its own repo untouched, deferred follow-ups, direct-lane wait end, empty model slot keeps its local flag)
- A capped tree (Act/Observe = light) cannot schedule a self_worktree child nor land a
  system-repo patch through integrate_*: the scheduling gate and the integration's
  protected-path gate read the task's effective mode, not the install mode alone.
- A one-shot follow-up the consciousness door refuses (allowance, concurrency) moves
  its run point forward by the alarm floor instead of re-firing every supervisor pass.
- The DIRECT lane announces a timed-out bounded wait too (one seam with the pool), and
  history replay carries the closed bound (wait_ended_at, no wait_for_answer).
- An empty consciousness model slot keeps the role's own local flag when it differs
  from Main's (В25=B); /api/state computes the alarm snapshot on the worker thread;
  a resumed campaign drops its stale pause reason; the caller's enabled flag wins in
  the status projection; wake_gate_open takes no chat id.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-16 11:55:24 +03:00
Ouroboros
c4d7669456 Bound a required owner wait with escalate(max_wait_minutes=N)
A root that must have an answer could only wait forever. escalate now takes an
optional max_wait_minutes: the task still parks at the completed-tool boundary,
and if no answer arrives within that window it resumes on its own with a
[SYSTEM NOTICE] instead of holding the task open indefinitely. The card is
untouched by the timeout — it stays open, and a later answer reaches the task's
chat as an ordinary owner message (the half that landed in the previous
commit).

The bound is validated by the shared quiz validator (a whole positive number of
minutes, only with wait_for_answer, capped by the task's absolute wall-clock
ceiling — beyond it the ceiling ends the task first, so a larger bound would be
a promise the runtime cannot keep) and refused as QUIZ_WAIT_BOUND_INVALID.

It travels as an ABSOLUTE instant in the owner-wait checkpoint
(wait_deadline_at plus the minutes it named), so a planned restart resumes the
SAME bound instead of granting the full wait again, and the cold continuation
emits the same notice as the warm one. Both continuation callbacks now return
"owner_input" or "timeout": the direct loop breaks on the deadline only AFTER
control_reason() is consulted, so Stop, cancel, the task deadline and the
absolute ceiling keep precedence; the pooled worker turns the spent bound into
a second reason for the SAME resume request the mailbox already sends, from
inside the parked gate, with no new scheduler (disclosed: that resume is a
request, not a guarantee — the grant can still be refused, and the hard axes
end the task in that case).

No new quiz or wait state: the row resumes with the additive
resume_reason: "timeout", which the activity projection now carries so the
project question pointer keeps reading "Answer needed" — the question was never
answered. The notice itself names the recorded assumption when there is one and
otherwise says plainly that no answer is not consent. The bound is deliberately
invisible on the cards and in Telegram (DESIGN: no timers, no countdowns); the
escalate receipts now state what the task actually agreed to.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-16 05:19:22 +03:00
Anton Razzhigaev
cc7269a5d5 Repair cross-platform test isolation and retain Docker failure evidence
Use short pytest labels without reducing large Unicode inputs, block provider/catalog calls at their existing seams instead of OS-local sockets, and decode UTF-8 task-state fixtures explicitly. Retain browser/container facts on Docker UI failure without changing the acceptance condition or timeout. Seven test files only; production behavior is unchanged. Focused combined Windows-related modules: 72 passed.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-09 01:04:57 +03:00
Anton Razzhigaev
59ce693b36 Prepare v7.0.0 with verified synthesis follow-ups
Preserve execution-limit causes and separate Telegram host notices from the assistant silent chain. Remove the obsolete unconditional continuation instruction, align reviewed schema pins, and retire duplicate extraction size policy. Correct browser test flow control and synchronize final release carriers. Publication awaits final exact-candidate tests, review convergence and CI.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-08 23:20:03 +03:00
Anton Razzhigaev
d5418e05b8 Complete native owner waiting and cross-stream result delivery
Connect ordinary chat actors to the existing completed-tool wait and control/budget tail. Preserve host notices in batch child handoffs, correct reviewed integration test contracts, and retain the queue-deadline repair and stronger cancellation tests. Consolidate stale/duplicated documentation without new gates or stores. Exact-candidate verification and external synthesis reviews follow before publication.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-08 22:48:14 +03:00