Commit graph

3634 commits

Author SHA1 Message Date
Ouroboros
cfe5adfd3c Merge remote-tracking branch 'managed/ouroboros' into fix/safe-candidate-browser-ci
# Conflicts:
#	docs/architecture/01-high-level-architecture.md
#	docs/inventories/DATA_LAYOUT_INVENTORY.md
2026-09-24 16:57:55 +03:00
Ouroboros
56c912020c test: pin LF in release-carrier and diff-capture fixtures
These fixtures assert LF diff bodies but wrote files through text mode, so on Windows they produced CRLF and relied on the runner Git system config (autocrlf=true) to normalize blobs. The isolated test environment scrubs that system config, exposing the dependency: the fixture owns its own EOL now.
2026-09-24 16:23:17 +03:00
Anton
e2ae097176 Tests read fixtures and logs as UTF-8 explicitly (Windows locale decode of the middle dot) 2026-09-24 15:40:41 +03:00
Anton
157743f5e1 Delta review: salvage summary test expects the human provider cause; browser proof writes evidence only under its temp root 2026-09-24 14:41:56 +03:00
Anton
5535a9fd34 Live Failed+Finalizing browser proof with a real actor (#1110/#1011); provider_unavailable speaks a human cause on the card (#869 wording) 2026-09-24 14:28:16 +03:00
Ouroboros
9b87e1bfb4 test: make the containment-token regressions hold on Windows and under a live container
Windows folds environment keys to upper case, so the regression token is spelled upper; the audit spawn allowlist admits the inherited OURO_PROC_CONTAINER_* keys and nothing else; the encoding regression covers PYTHONIOENCODING on the commit-gate env too.
2026-09-24 14:22:30 +03:00
Ouroboros
77ce2c6f02 test: keep the platform default text encoding in isolated test environments
Forcing PYTHONUTF8/PYTHONIOENCODING onto every pytest child and the hermetic commit gate would hide exactly the cp1252 bugs Windows CI exists to catch. Isolation is about roots, never the interpreter encoding; pin it with a regression.
2026-09-24 14:14:26 +03:00
Anton
14a5b5c4f4 Review repairs: an unstamped finalizing replay still paints its settled outcome (#1110); a completed lifecycle with a failed outcome never reads as a clean completion (#1087) 2026-09-24 14:13:54 +03:00
Ouroboros
6db1ba0979 fix: let the historical audit child inherit the containment token
Container membership is env-token based; the audit spawner built an allowlisted child env that dropped OURO_PROC_CONTAINER_*, so a forced server teardown could reap the container while the audit child kept writing the data root. Propagate the token and pin it with a regression.
2026-09-24 13:54:47 +03:00
Anton
9520456161 Merge remote-tracking branch 'upstream/ouroboros' into presentation/truthful-cards 2026-09-24 13:45:04 +03:00
Anton
2fe79e56f3 Merge official ouroboros (21d0b57a, PRs #1243 #1245 #1246 #1247) into presentation/truthful-cards; review repairs (#1154 readiness gate, early-final outcome, leaf cost scope, DOMAIN_MAP regen) 2026-09-24 13:45:04 +03:00
Ouroboros
f5d7eee23d Merge remote-tracking branch 'managed/ouroboros' into fix/safe-candidate-browser-ci
# Conflicts:
#	docs/inventories/DATA_LAYOUT_INVENTORY.md
2026-09-24 13:42:50 +03:00
Ouroboros
10bf08ae82 test: make candidate checkout identity and EOL fixtures portable to Windows
Compare file modes between two path stats (Windows adds execute bits by filename to a path stat but not to fstat), derive the origin-proof sentinel mode from an observed sibling, keep child patches as bytes, pin LF fixtures and posix worktree paths, unlink a stampless orphan monetary lock after a proven reap, and trim chapters 01/06/14 under their budgets.
2026-09-24 13:42:20 +03:00
Ouroboros
b709879ba0 Merge managed/ouroboros into claude/snapshot-lock-20260923
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 12:54:03 +03:00
Ouroboros
f040266650 Keep the private snapshot's index consistent with the copied bytes on Windows
The Windows full-test leg of #1247 found three defects in the new lock-scope
tests and one pre-existing runtime wart the tests exposed.

Runtime: after `reset --hard` the snapshot copies the source's exact bytes
over the checkout. Under `core.autocrlf=true` (Git for Windows' default) the
checkout wrote CRLF and recorded that size in the index; the copy restored the
source's LF bytes, and git trusts a size mismatch as a modification without
re-hashing, so every such file (`.gitmodules` on the runner) read as modified
in the child's `git status` for the run's whole life. One `update-index -z
--stdin` over the copied paths re-hashes them through the same clean filters
the baseline used and re-records their stat; the blob is unchanged.

Tests: the lock holder reports its own pid (a venv `python.exe` on Windows is a
launcher whose child is the interpreter, so `Popen.pid` is not the pid in the
lock) and exits on stdin EOF so a killed launcher never leaves a child holding
the OS lock; the populate test runs a second time under an autocrlf=true
global config so the stat re-record is proven on every OS (it fails with the
re-record removed); the consumer scan compares POSIX path spellings.

Docs: the populate sentence names the stat re-record; chapter budget raised.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 12:29:22 +03:00
Anton Razzhigaev
971660160f Merge remote-tracking branch 'managed/ouroboros' into claude/predecessor-door-20260924
# Conflicts:
#	tests/test_reference_book_budgets.py
2026-09-24 11:15:04 +03:00
Anton Razzhigaev
e9e11f2eb1 Merge remote-tracking branch 'managed/ouroboros' into claude/predecessor-door-20260924
# Conflicts:
#	docs/architecture/06-agent-core.md
#	tests/test_reference_book_budgets.py
2026-09-24 10:50:30 +03:00
Ouroboros
c789438d05 Merge managed/ouroboros into claude/snapshot-lock-20260923
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 07:39:52 +03:00
Anton Razzhigaev
409a9a0ae5 Name a helper predecessor by what its row knows, and read the route landing from the receipt
Second review wave, four accepted advisories. A helper's row may carry only
its parent, or only the subagent role: the note now says "its root is",
"its parent is" or "its root is unknown" and never goes silent on a helper.
The route receipt reads the landing project from the admission receipt like
the promote receipt does (today identical to the requested id, so the claim
in the door commit is literally true on both verbs). The tool text says "any
settled status" instead of enumerating three of the four settled statuses.
The child capability summary and the pointer-stamp comment describe the
lineage and the hint as they are now. Pinned on both verbs, on a nested
helper and on a role-only helper.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 07:35:05 +03:00
Ouroboros
3a31e955c8 Pin the last two guards and keep the refusal stash contract explicit
The focused Fable delta review of cd04248b0 found the head red on one
pre-existing expectation and two guards that no test would miss:

- tests/test_configured_session_prestart.py pins the startup-refusal stash
  exactly; it now expects the `detail` key a refused provision fills (empty
  for a blocked route), the contract fix batch 2 introduced.
- `_deletable` is strict: the snapshot root itself (which holds every live
  snapshot) is never a deletable path; `_remove_paths` and the payload stale
  delete reuse the one guard; a registry row naming the root deletes nothing
  (test).
- The busy-first-section guard is two-sided: the typed refusal must arrive
  after the one lock wait, never after a second discard wait.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 07:33:22 +03:00
Anton Razzhigaev
de7e191ffc Say "settled result" wherever the routing text still said "finished root"
The first review wave read the candidate and found four sentences that
described the door the way it was: the missing-selector error and the
pending-promote refusal told the model to name a finished root, the room
manifest's docstring said the predicate admits a settled root, and the
last-result lookup's docstring said a child is never the room's
continuation because the promote door refuses it. The handler continues any
settled result, a helper's included, and the hint offers roots only; the
sentences now say that. Wording only, no behaviour change.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 07:24:58 +03:00
Anton
9799d32f6c Merge remote-tracking branch 'origin/ouroboros' into planning/serial-turns 2026-09-24 06:18:22 +03:00
Ouroboros
f839e625a7 test: await durable parent terminal before ordering assertions 2026-09-24 05:50:29 +03:00
Ouroboros
0188a0e5bb test: make repository capture fixtures portable to Windows 2026-09-24 05:46:08 +03:00
Ouroboros
4ff299846e feat: support addressed continuing participant turns 2026-09-24 05:39:44 +03:00
Ouroboros
f7669143a6 Merge remote-tracking branch 'managed/ouroboros' into fix/safe-candidate-browser-ci
# Conflicts:
#	docs/DOMAIN_MAP.md
#	docs/inventories/DATA_LAYOUT_INVENTORY.md
#	tests/test_persistence_inventory.py
2026-09-24 04:43:38 +03:00
Ouroboros
acbdfecba5 test: assert host failure and stale evidence without synthetic reviewers 2026-09-24 04:12:53 +03:00
Ouroboros
b5fd785a59 test: await observable settlement and retain stuck-thread evidence 2026-09-24 04:08:00 +03:00
Ouroboros
697fd1e1ed fix: revoke approval when delivery subject cannot be verified 2026-09-24 04:01:33 +03:00
Ouroboros
75f17f15dc fix: preserve evidence and terminate local acceptance failure loops 2026-09-24 03:42:48 +03:00
Ouroboros
24bf285354 fix: preserve staged intent and confine browser temporary writes 2026-09-24 02:55:04 +03:00
Ouroboros
cd04248b02 Close the delta-review findings on the snapshot-lock change
Three delta reviews of e1727bc25 (Fable, grok-4.7, gpt-6-astra) agreed on the
remainder:

- The non-UTF-8 fixture name is created only off Windows: that platform decodes
  names with surrogatepass and raised before any OSError, which the guard did
  not catch; the fixture's DOS device names (`nul.*`) are renamed.
- The three lock-scope sentences and the PR text say what the code does now:
  the acting self_worktree lane populates and deletes outside the lock (its
  post-checkout hook no longer fires at provision), only the boot-time
  prune_orphans sweep and the genesis init still work under it; the binary
  verdict is one process, two when empty files need their attribute verdict,
  with the per-file fallback named.
- A busy FIRST lock section is a plain refusal: nothing was registered, so
  nothing is discarded (no second wait, no spurious warning); a failure after
  the row still discards row, pin and admin dir, now pinned by injections at
  update-ref and worktree add.
- The START_FAILED row carries the producer's detail beside the typed facts;
  the refusal-fact keys have one owner (delegate_shared.REFUSAL_FACT_KEYS).
- One `_deletable` guard for every pre-lock checkout delete; candidate order
  matches the per-file predicate (PEM head before the size cap).

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 02:08:30 +03:00
Anton Razzhigaev
02f865260c Continue a helper's result with its root disclosed instead of refusing it
The door still refused a delegated helper's result as a predecessor and
told the model to name the root: the accident the refusal guarded against,
a room's pointer moved onto a helper by a child finalization, is closed by
construction now that only a root stamps the pointer and the hint window
never offers a child. What remained was a refusal with no danger behind it,
and one real gap: a helper's own files live under the helper's id, so a
continuation of the root cannot read the design a helper wrote, while a
continuation of the helper can.

A named helper's result is continued like any settled result, and the
receipt says whose helper it was and where its root is, beside the landing
note; the receipt's two facts ride one render-only event key that is popped
before emission. The predicate is now what the tool descriptions say: a
settled result (completed, failed or cancelled), not a live root and not a
pending promote. A failed root is pinned as a settled predecessor, because
the coordinator's first refused predecessor had failed at its ceiling and
was still the work to continue. The routing docstrings that equated
addressability with the host list say what the list is, a hint.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 02:07:24 +03:00
Anton Razzhigaev
d21d7e2cb5 Let a continuation read the task files of the predecessor it continues
A continuation admitted with a forked execution drive could read its
predecessor's complete result, artifact path and hash included, and could
not open the artifact: the lineage read covered the actor's own, its
parent's and its root's task_drive/artifact_store, and a predecessor named
by the work order was not in that set, so the task asked the owner to upload
a file that already existed (issue #1232).

lineage_task_ids now also names the ONE predecessor the task's contract
carries (predecessor_authority.source.task_id, the host-minted pointer
written at startup binding), one hop only and read-only: the same lineage
seam PR-era T4=A opened for parent and root, over the canonical data root
and the task's own drives. A child that inherits the envelope through the
contract spread reads it too; a write into the predecessor's drive stays
refused, a stranger's drive stays refused, and a task without the envelope
keeps today's lineage. Eight two-sided tests pin it; six of them fail with
the new id removed.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 01:59:40 +03:00
Anton Razzhigaev
3ab35879c0 Read the project registry from the canonical root in the routing verbs
A promoted task with a workspace runs on a forked execution drive under
state/headless_tasks/<id>/data, and the fork never carries
state/projects.json. list_projects, route_to_project and the promote
receipt's project name read the registry through ctx.drive_root, so such a
task answered "No projects yet" on an install with dozens of projects and a
task-authored route_to_project refused every existing project as
target_not_found. Five of the six rooms on the live install have a working
folder, so a coordinator in any of them could not route at all; the promote
path was already right because the durable project lookup reads the
canonical root.

The three reads now go through canonical_data_root (the task's budget root,
then its own drive), the same resolver the lineage reads use. A context
with no canonical root keeps reading its own drive.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 01:57:03 +03:00
Anton Razzhigaev
0c5e6b788e Judge a predecessor by the root itself, never by the caller's room
A coordinator task in one project named the settled roots of five other
projects, each as the predecessor of work it sent INTO that project, and
was refused seven times: the door accepted a predecessor only when the host
had listed it this turn or when it belonged to the caller's own room, and a
pooled task carries no host manifest at all. The workaround was four bridge
tasks promoted into each room, which then continued the exact predecessor
from inside - the same successor, two hops and a re-stamped pointer later.

The room comparison protected nothing. The pointer the door withholds is
rebuilt from the task id alone; the successor inherits data (its ceiling,
origin and contract come from the caller and admission); a fresh root into
any project needs no room check; and a Main-lane turn already continued a
listed root of one project into another. The door is now the predicate on
the root the refusals were really made of: a ROOT (not a delegated child),
a readable result, not live (a live root is steer_task, and a pending
promote is not a result). Where the caller sits and where the work lands
are no longer inputs; a continuation landing outside its predecessor's
project is disclosed in the receipt like the second-project note, on both
verbs, from the project admission actually returned. The render-only fact
rides the event only until emission, so the supervisor sees nothing new.

The tool descriptions stop telling the model that a host-listed id is
required and name the refusals that remain. Invariant 27 and the routing
paragraph state the predicate; both chapters' byte budgets rise with the
reason recorded beside the number.

Tests: the two pins that encoded the room comparison and the wake pin are
inverted; the coordinator shape (a pooled task with only its client surface
and contract as metadata, continuing another room's root into that room on
both verbs), the disclosed landing note (fires away from home, silent at
home), a project-less Main root continued from a room, and a public
conversation continuing a settled root while its promote still lands
without a project are pinned two-sided. With the room comparison restored
seven of these tests fail.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 01:54:15 +03:00
Ouroboros
e1727bc25e Close the review findings on the snapshot-lock change
Five reviews of 226285a1f (Fable triad, grok-4.7 triad and scope, gpt-6-astra
triad and scope; dispositions in the sprint ledger) converged on these fixes:

- untracked_binary_verdicts: a path the first diff omits is identical to the
  staged empty blob, i.e. an empty file, which git still classifies by
  attribute; those paths get a second batch staged as a one-byte blob, so an
  empty `-diff` / `binary` / driver-binary file is binary exactly as the
  per-file verdict said. Only the two staging blobs enter the target's object
  database. Scratch-index allocation is inside the guarded lifecycle, so an
  unavailable temp dir also falls back to the per-file verdict with a warning.
- binary_verdict_candidates: the dotenv policy, the name rules, the PEM head
  (restricted modes) and the size cap decide BEFORE the batch, so a vetoed or
  over-cap file is never handed to git and never reaches a clean filter or an
  encoding conversion; both callers batch only candidates.
- provision_execution_snapshot: the provisional row carries no per-file maps;
  the first lock section is inside the cleanup scope, so a failed update-ref or
  worktree add after the row discards row, pin and admin dir; a discard after a
  busy lock waits 5 s, not the full timeout.
- provision_worktree / remove_worktree follow the same split: admin dir and
  branch under the lock, the checkout populated (`reset --hard --quiet
  --no-recurse-submodules`) and deleted outside it.
- A refused snapshot provision keeps its facts on the configured-child path:
  cause, holder, waited seconds and the producer's detail ride
  `subagent_availability`, the $0 terminal text, the START_FAILED row and the
  acceptance evidence.
- Tests: platform guard on the newline-named fixture entry; non-UTF-8 name
  only where the filesystem accepts it; hook positive control; `_git_env`
  spy; acting-lane split; empty-file classes; filter-tee guard; refusal facts
  on the bootstrap path; the receipt's timing facts join the per-case identity
  set of the directory-geometry payload comparison.
- Docs: the delegated-lane sentences name the acting checkout/delete, the
  registry read-modify-write residual and the target object-database growth
  (owner decision: disclose only); data-layout inventory regenerated.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 01:38:17 +03:00
Ouroboros
1f52eaac18 fix: bind candidate identity to staged entries, refuse any existing basetemp, bound the browser lane 2026-09-24 01:11:08 +03:00
Ouroboros
03d8d16eec Merge official ouroboros (567fa533, PR #1236) into presentation/truthful-cards 2026-09-24 00:57:36 +03:00
Ouroboros
f04fb1ebfe Truthful cards and history: presentation batch #1011 #1087 #1110 #1154 #1061 #931 #1073 #516 #869 #498 (candidate) 2026-09-24 00:48:30 +03:00
Ouroboros
226285a1f8 Keep private-snapshot provisioning off the machine-wide worktree lock
A mutating delegate_start provisioned the child's execution snapshot inside
subagent_worktrees' ops lock, and the untracked-file classification inside
it spawned one `git diff --no-index --numstat` per file. One project with
67,692 untracked files held the lock for 40 minutes; every other mutating
start on the machine timed out after 120 s (issue #1241).

subagent_worktrees: the ops lock now guards shared metadata only. Provisioning
takes it twice for milliseconds - registry row FIRST, then the baseline pin,
then `worktree add --no-checkout` - so a crash after the row is reclaimable
by the startup GC; the tree walk, hashing, populate (`reset --hard --quiet
--no-recurse-submodules`, what `worktree add` runs internally, minus the
target's post-checkout hook, which no longer executes project-authored code
at provision) and the raw-bytes copy run outside it. Removal deletes files
outside the lock and forgets admin dir, pin and row inside. Payload snapshots
copy and commit outside the lock. A malformed registry refuses before the
tree is hashed. The lock file names its holder (pid/task/op/since/target) so
the owner-aware stale check evicts a SIGKILLed holder at once, and a timeout
is a typed WorktreeOpsLockBusy.

workspace_patch_capture: untracked_binary_verdicts stages every regular file
as the empty blob into a scratch index and asks ONE index-versus-worktree
`git diff --numstat -z`, so the verdict stays git's own (attributes, diff
drivers, clean filters, working-tree encodings) with one process per
inventory; a failed batch falls back to the per-file verdict with a warning.
Both the snapshot and the finalization patch capture use it.

delegate: every pre-POST provisioning refusal is definitely_unrun (a
configured leaf ends at $0), carries the lock holder when the cause is a
busy lock, and settles its invocation with a durable START_FAILED row; the
started receipt discloses the snapshot's entries, untracked files,
file-input bytes and provisioning seconds.

Docs: ARCHITECTURE section 6 snapshot paragraph, section 1 module row,
DEVELOPMENT delegated-lane bullet; two chapter byte budgets raised for the
added rationale text.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-24 00:22:26 +03:00
Ouroboros
211d4f955f Merge current official ouroboros into safe candidate verification 2026-09-23 23:56:59 +03:00
Ouroboros
f48687d1bb fix: preserve candidate snapshots and test process custody 2026-09-23 23:55:22 +03:00
Ouroboros
14a05d7fd5 test: guarantee CRLF export fixture changes on Windows 2026-09-23 17:21:32 +03:00
Ouroboros
568bf7f420 fix: retain newline semantics through committed carrier export 2026-09-23 16:57:22 +03:00
Ouroboros
ccaae88702 fix: preserve Git text decoding and catalog button ownership 2026-09-23 16:26:35 +03:00
Ouroboros
75dcfbf7ea Refuse browser fixture success when supervisor failed to initialize 2026-09-23 09:55:15 +03:00
Ouroboros
57c3d30aa0 Preserve explicit bytecode probes and ceiling-aware shell effect checks 2026-09-23 09:40:45 +03:00
Ouroboros
d8a1f0ebb8 Keep xdist sibling temporary directories inside Git discovery ceiling 2026-09-23 09:16:40 +03:00
Ouroboros
f3f70b646f Isolate candidate verification and expand event-driven browser checks 2026-09-23 08:59:49 +03:00