Commit graph

41 commits

Author SHA1 Message Date
Ouroboros
d5a034397c docs: compact architecture and development guidance 2026-08-08 22:20:24 +03:00
Andrei Kaznacheev
6641081b10 feat: add apply_patch and edit_batch editing tools with editbench evidence
Two new repo-lane editing primitives beyond exact-match edit_text and
full-file write_file, both validated on the included editbench benchmark
before adoption:

- edit_batch: atomic batch of COUNTED exact replacements. Each edit
  declares the occurrence count it expects and replaces all of them; any
  mismatch aborts the whole batch with per-edit diagnostics. The safe
  replace-all: a miscount is an atomic refusal, not a silent corruption.
- apply_patch: context-anchored multi-file patch (V4A-style, no line
  numbers; optional @@ anchors; trailing-whitespace fuzzy fallback).
  Atomic across all files/hunks with per-hunk diagnostics; parser
  tolerates decorative trailing *** on headers (observed model quirk).

write_file repo lane gains two verification rails inherited from an
edit_sketch fast-apply tool that was implemented, benchmarked, and
REJECTED (data in devtools/benchmarks/editbench/README.md): a pre-write
syntax guard for .py/.json (force bypasses with an explicit
SYNTAX_GUARD_BYPASSED disclosure — no silent bypass, P3) and the unified
diff vs the previous version appended to overwrite results (capped with
an explicit truncation count, P1).

Registration follows the New Tool rule across every canonical surface:
safety.py TOOL_POLICY, tool_capabilities (CORE/ACTING envelopes + result
limits; local-readonly and heal lanes deliberately excluded), registry
(_FROZEN_TOOL_MODULES/_WORKSPACE_ALLOWED_TOOLS/_REPO_MUTATION_TOOLS),
outcomes (_ROOT_WRITE_TOOLS so patch/batch-only turns stay acceptance-
review-eligible; _RECOVERY_TOOL_NAMES), smoke EXPECTED_TOOLS, and the
SYSTEM.md/ARCHITECTURE.md/DEVELOPMENT.md/CHECKLISTS.md documentation in
the same commit (P6). The edit_text/write_file descriptions steer tool
selection at the schema source (per DEVELOPMENT's anti-pattern guidance,
not SYSTEM.md prose accretion).

devtools/benchmarks/editbench/ is the evidence and the regression rig:
5 editing tasks (trap-laden rename, surgical edit in a 1691-line module,
whole-function replacement, cross-file move, near-full-file transform),
per-config tool restriction via disabled_tools, deterministic grading,
token/latency/error mining. Migrated under the benchmark admission
contract (admit_benchmark_run/finalize_run_manifest, launcher_audit
MIGRATED_LAUNCHERS); it measures the current working tree by design, so
real runs use the recorded --allow-dirty-seed escape.

Headline numbers (grok-4.5, 3 runs/config, every run solved every task;
full tables in the editbench README): edit_batch finishes the rename
task in ONE tool call vs ~6 for edit_text/write_file; on a weak model
(gemini-3.6-flash) its advantage grows to 1.5-2.5x cheaper/faster; a
free-choice agent picked the right tool per task shape in every run.

No version carriers touched (maintainer assigns the release version).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 00:03:01 +03:00
Anton Razzhigaev
8cee0a17a3
fix: stabilize mobile UI and refresh reviewer defaults (#82)
Remove the v6.82 mobile swipe gestures, make drawer opening clear keyboard state, and keep deeply nested live cards usable in narrow consumers. Set fresh-install triad defaults to Luna, Gemini Flash, and Sonnet while preserving saved settings.

Co-authored-by: Ouroboros <ouroboros@local.mac>
2026-07-31 08:13:53 +03:00
Anton Razzhigaev
3f9d504b76 fix(v6.81.0): the submission scrubber must refuse symlinks, not certify past them
scrub_submission_secrets.py walked `root.rglob("*")` filtered by `p.is_file()` and
wrote with `path.write_text()`. Both follow symlinks, so the tool had two failures,
each demonstrated against the pre-fix code.

A FILE symlink was swept THROUGH: the write landed on the link's target, outside
--root. A pack containing a link to the live settings.json therefore had its real
keys replaced with <REDACTED:...> by the tool whose job is to protect them. `cp -a`
preserves symlinks, so the procedural "run this on a COPY" rule did not help.

A DIRECTORY symlink was worse. rglob does not descend through one, so its contents
were never enumerated — and the verify pass then printed verify_leftovers=0 and
exited 0. The tool affirmatively certified a tree it had never read, for content
reachable under --root and about to be uploaded to a public leaderboard. Silent
non-coverage reported as cleanliness is exactly the class of false claim this
release exists to remove, and here the consequence is a live API key published.

Both are now a hard refusal before a single byte is written, reusing the fail-closed
discipline the --env-passthrough refusal already established: every offending link is
named with its target and its kind, nothing is modified, exit 2. Refusing beats
resolving-and-continuing, because under --root a symlink is either an accident or an
escape and only the operator can say which. With the links removed the tool sweeps
and verifies exactly as before, so this refuses an unsafe shape rather than removing
a capability.

Pre-fix, the new test fails with `assert 0 == 2` — the old tool reported success.
2026-07-26 06:03:31 +00:00
Anton Razzhigaev
0b06de8fdb fix(v6.81.0): close the two cross-phase misses the green gates passed over
Both defects were invisible to every phase on its own base and appeared only once
the chain was assembled. Neither was caught by the full gate battery, because
neither was pinned by a test — which is the actual finding.

_CACHE_INCLUSIVE_PROMPT_TOKEN_PROVIDERS omitted "anthropic". P6 introduced the set
correctly, while the direct-Anthropic path still reported bare input_tokens. P3
then made that path report prompt_tokens = input + cache_read + cache_creation.
On the merged tree every cache-bearing direct-Anthropic send therefore failed the
membership test and returned early, so P6's token-density learning was vacuous on
the main and heavy slots — precisely the routes it exists to measure — and every
review pack was frozen at the cold-start density. The docstring asserted the
opposite of the tree's behaviour, in a release whose thesis is that artefacts must
not claim what did not happen. GigaChat stays excluded: its precached_prompt_tokens
semantics are still undocumented.

ARCHITECTURE.md stated the migrated-launcher count twice and contradicted itself —
"ELEVEN" from P2/P3 and "ten" from P5, surviving side by side in one 33 KB physical
line that git merged without a conflict marker. The registry holds fourteen. The
first claim is now explicitly historical, the second states the current count, and
a test pins any unqualified count to len(MIGRATED_LAUNCHERS) so a future migration
that forgets the prose fails instead of shipping a document that misdescribes its
own gate. Also repaired the README roll-off sentence, where 6.76.0 had been
appended after the closing clause instead of inside the parenthesised list.

Tests added in both directions for the density gate, which had no coverage at all.
2026-07-26 05:51:45 +00:00
Anton Razzhigaev
f05bf94362 feat(v6.81.0): benchmark provenance becomes a gate, and the artefacts stop lying
Six reviewed phases land as one release.

Admission is the outer boundary: every migrated launcher records a manifest before
it can touch the filesystem, and finalizes a typed outcome on every path — success,
refusal, crash, and the real exit status. A structural audit enforces that boundary
across all fourteen launchers, together with confinement computed from the active
checkout and a single manifest publisher, judging by effect rather than by callee
name and failing closed on any write form it cannot resolve.

Harness exit codes are no longer trusted as run status: inspect returns zero for an
eval that raised and harbor returns zero for a job whose trials all errored, so the
launchers now read the harness's own artefact and keep "the harness failed", "it
scored nothing" and "it scored honest zeros" distinguishable.

The acceptance dialogue reconciles receipts through one typed identity that is an
equivalence by construction, so a passing check can no longer clear a red it never
addressed. Prompt caching is normalized at every send site and cached calls stop
under-reporting their input. The owner's context mode becomes explicit and
fail-closed, with one enforcement point for every writer of a disk-authored setting.

Deliberate limits are disclosed in each bench's METHODOLOGY.md rather than implied
by silence. Isolated benchmark egress and the multi-lane script generator are
deferred to a later release with restoration patches and carry-forward notes.
2026-07-26 03:40:44 +00:00
Anton Razzhigaev
e879ffc675 fix(v6.75.0): benchmark run provenance becomes a gate, not a report
Every claim a benchmark run makes about itself is now either enforced before
money is spent or refused with a durable typed record.

Admission is the outer boundary, and that is a tested property, not a
convention: `admit_benchmark_run()` builds the manifest, WRITES it, and only
then lets the seed gate enforce, raising `BenchmarkAdmissionRefused` with the
refusal already on disk. A `finalize_run_manifest()` context manager records a
typed outcome, a typed refusal/error and the REAL exit status on every exit
path, including an escaping exception (an integer `SystemExit.code` is
preserved). All seven migrated launchers route through both seams; none calls
the builder directly; and an `ast` guard in the seam meta-test fails if any
denylisted operation — filesystem assertions, docker, subprocess, state dumps,
writers — precedes admission. The guard was verified to bite: against the
pre-fix tree it reports four violations, two of which no review round had
reached.

Refusals are one family. `BenchmarkAdmissionRefused`, `RuntimeAttestationRefused`
and `SeedShapeRefused` are all `RuntimeError` subclasses carrying a typed
reason, deliberately not `SystemExit` — a `SystemExit`-raising assertion had
made a refusal handler dead code, because `SystemExit` is not an `Exception`
subclass. A behavioural parity test computes what `raise SystemExit(main())`
hands the OS for each launcher and asserts it EQUALS the `exit_code` the
manifest records, so a recorded status can no longer diverge from reality.

`runtime_attestation()` records both facts about a live server — the HTTP
`runtime_version` from the frozen `/api/health` contract and the local
HEAD/VERSION of its checkout — and requires the contracted field: a bare
`version` key now refuses with the non-overridable `runtime_version_absent`, so
an unrelated HTTP server can no longer attest. `OBO_ALLOW_EVOLVED_VOLUME` waives
only `runtime_skew`, in the shell as well as in Python, and commit availability
is decided before skew so a missing commit cannot be mislabelled. Lineage is a
descent check (`merge-base --is-ancestor`), never equality, so an evolution run
legitimately moving HEAD forward is not corruption.
`CAMPAIGN_FATAL_PROVENANCE_REASONS` is a single shared authority consumed by
both SWE-Pro drivers, which now stop the schedule immediately — before any
volume archival — instead of one driver burning every task.

Grading gains a third state: `pass|fail|ungraded` with typed reasons beside the
UNCHANGED headline formula, plus `grade_summary.json`, and the probe
orchestrator reads that artifact instead of scraping log tokens and refuses to
publish a grade that a failed or stale grader produced. ProgramBench's ledger is
append-only at both the run root and the instance directory, skip rows included.
`common/manifests.py::write_json` is atomic and byte-identical, importing
`ouroboros.utils` lazily so the module stays stdlib-only for the container-side
harbor agent, and `openrouter_key_remaining()` reads the authoritative
`limit_remaining`.

Egress isolation was built in this phase and is NOT part of this release: it is
off by default per owner decision, it produced a finding in five separate review
rounds, and round 10's was a direct recurrence of round 5's, so it was extracted
and deferred with its diagnosis preserved. Solve containers run the same open
network as before v6.75.0. The measured evidence stays in METHODOLOGY: the
official SWE-bench Pro harness does not regulate the solve container's network
at all (`--block_network` applies to the EVAL container), and 31 of 287 attempted
instances are musl/Alpine, 84% of which previously produced a non-empty patch.

GAIA, CL-Bench, Terminal-Bench and OSWorld keep their pre-v6.75.0 behaviour here
and migrate in their own phases. No `ouroboros/` runtime behaviour changes.

Reviewed through eleven rounds of the production commit gate (advisory, triad
`claude-fable-5` + `gpt-5.6-sol` + `gemini-3.5-flash` at high effort, scope
`claude-fable-5`): 24 findings, 22 fixed and 2 refuted with the evidence recorded
in the changelog. Per-phase tags are deliberately not created — a single release
tag lands with the campaign synthesis, an owner-approved deviation from the
tag-per-commit norm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 18:24:25 +00:00
Anton Razzhigaev
1fcb1d32c3 feat(v6.74.4): workspace-tree freeze directives (mitigation) + truthful ProgramBench submission contract
Root cause (PB cmatsuoka__figlet smoke): the agent committed a compiling state, then broke the tree with one last uncommitted edit as the acceptance improvement loop hit its pass cap; the harness ships the LIVE tree, so the verified commit protected nothing — all salvage machinery guards the answer TEXT only. Prompt-only fix (P5) over existing channels (P7): the acceptance rails line marks the last admitted improvement pass (passes_done+1 >= cap, cap>0) as FINAL and, for workspace deliveries (canonical is_workspace_mode() with an attribute fallback), EVERY workspace improvement capsule carries the tree directive — a deadline or cost rail can end the loop between capsules (triad r1) — keeping the tree at a VERIFIED state (rebuild, verify, and commit if the task calls for a commit; revert unverified edits); the 10% deadline flush AND the cost wrap-up note gain one shared commit-NEUTRAL tree sentence (acting self_worktree subagents cannot commit; a moved HEAD fails patch capture closed), byte-identical for non-workspace tasks; the ProgramBench instruction now states the exporter's true submission contract (SOURCE tarball from the CURRENT tree state; .git, root binaries, .ouroboros/ and named build/cache noise excluded at any depth; run ./compile.sh one final time), replacing the false fresh-checkout framing. Tests pin the pacing/rails seam, the workspace gating on both axes, byte-identical non-workspace texts, the real tarball contract, and the instruction truth phrases. P9 carriers bumped to 6.74.4; changelog row added. Disclosed residual (this is a MITIGATION of the incident class, not a closure): a forced tool-less exit — deadline grace or budget stop crossed inside one long round with no pacing note or capsule in the terminal stretch — can still ship an unverified last edit; the structural verification-freshness seam is a filed follow-up pending an owner decision (triad r1-r3, codex full-access review concur).
2026-07-22 00:37:27 +00:00
Anton Razzhigaev
d60b3a2afa fix(v6.74.2): CI portability of the two new GAIA sandbox-staging tests
They imported inspect_ai directly — an optional benchmark dependency absent on CI runners — and failed quick-test with ModuleNotFoundError. The tests now inject a fake inspect_ai.util.sandbox module via monkeypatch, keeping the success-path coverage on every environment. P9 carriers bumped to 6.74.2; changelog row added (oldest patch row rolled off). No runtime code changes.
2026-07-21 20:32:59 +00:00
Anton Razzhigaev
0a2bd58014 fix(v6.74.1): CI lint gate — remove one unused test import
The v6.74.0 tag CI failed on the deterministic ruff F-rule gate: an unused types.SimpleNamespace import in tests/test_devtools_benchmarks.py (added with the final GAIA staging tests). Import removed; P9 carriers bumped to 6.74.1; changelog patch row added (oldest patch row rolled off). No runtime code changes. Fix-forward per protocol — the published v6.74.0 tag is not re-tagged.
2026-07-21 20:15:46 +00:00
Anton Razzhigaev
68c119cfa9 feat(v6.74.0): acceptance review becomes a reviewer-authored terminating dialogue
A: verdict-visible improvement capsule (verdict+tier+real blocker via one panel_reason reducer, open obligation ids, money/time/rounds/passes rails line, three real moves); reviewer-authored obligation identity (disposition_kind new|re_raise validated against the host catalog, fail-closed to new, per-pass dedup, reuse-immutable) with surviving rebuttals (previous_disposition/previous_reason/reopened_count); typed dialogue_status (continue_actionable|unreachable_here|stable_disagreement) reduced over ALL contract-valid actors with the panel quorum — termination is reviewer-authored or a real rail, never a host counter.
B: two cache-marked review-prompt segments (governance + task-stable contract), slot label off byte 0, breakpoint cap asserted on the final payload.
C: GAIA sandbox attachment staging (prompt-declared /shared_files channel, exact shared-root lookup, per-file provenance, typed per-sample infra error); CLB acceptance-claims operator patch (receipt-bound claims, knowledge nudge in the steer slot, bounded cost-finality wait); SWE-Pro cumulative shard budget (auto_run derives per_task x scheduled, run_pro seeds from cumulative spend); CLI/PB bounded task_cost_finalized waits for completed/degraded only.
D: light-mode shell guard resolves cwd before judging repo targets (resource-root label false-block fixed); post-task cost publish uses try_get_bridge.
E: generative surface-duty in commit/plan review checklists; all P9 carriers bumped.

Reviewed: 2 adversarial rounds + production triad+scope (PASSED) + codex final (GO); smoke 5x5 on all five benches verified the dialogue/staging/budget mechanics live.
2026-07-21 19:57:55 +00:00
Ouroboros
058d578cb7 feat(v6.68.0): contributor fast path with target-bound review evidence 2026-07-17 07:52:58 +03:00
Anton Razzhigaev
291e825c56 fix: release Ouroboros v6.64.2 benchmark integrity hotfix 2026-07-15 00:20:19 +00:00
Anton Razzhigaev
6a357d338d release: v6.64.0 2026-07-14 18:55:54 +00:00
Anton Razzhigaev
0713bb3f58 bench(tb): launch via named job config for leaderboard-valid submissions (operator, approved)
TB2.1 leaderboard static analysis matches config.agents[].name against the
agent name trials report; bare --agent-import-path records name=null, which
can never match (terminal-bench-2-1#121) and is unfixable after upload.

- run_tb.py: generate agent_job_config.json (name = adapter class name() +
  import_path + kwargs) and launch harbor with -c instead of bare agent
  flags; OUROBOROS_EFFORT_TASK at launch is recorded as the declared
  reasoning_effort of the submission key.
- harbor_installed_agent.py: accept the reasoning_effort kwarg and forward
  it into the container as OUROBOROS_EFFORT_TASK (declared == effective).
- README/METHODOLOGY: replace the removed 'harbor leaderboard submit' CLI
  flow with the verified GitHub-PR flow (terminal-bench-2-1 lb submit,
  promotion, /judge, /apply), document the named-config requirement,
  trajectory_path pitfalls and the TUS upload fix pointer.
- tests: assert the new -c job-config shape (name/import_path/kwargs/effort).
2026-07-14 18:47:48 +00:00
Anton Razzhigaev
5a8bba943c release: Ouroboros v6.56.0 — generalizable fixes from the SWE-Pro autopsy + PB/TB TZ
Generalizable runtime + harness improvements distilled from the 35-FAIL SWE-bench Pro
autopsy, the ProgramBench improvement spec, and the TB2.1 forensics — one minor release,
no benchmark overfit.

Runtime (A/C):
- Scratch is now idempotent/adoptable: an existing untracked in-cwd file can be declared
  scratch (sha recorded at declaration, re-declaration idempotent); tracked files and
  directories stay blocked. The undeclared-output guard is stat-verified (real filesystem
  writes, not string-shape) and, for run_script, audits on EVERY exit path — a write-then-
  fail body no longer smuggles an undeclared user_files deliverable.
- Cost axis: budget_profile.cost_hard_stop_pct (0..100; None→50% historical; 0 = NO in-task
  cost stop, deadline/rounds/global-gate only; malformed → 50%, never a silent 0). Latched
  cost milestones (50/25/10% + wrap-up) replace the old [INFO] nudge. CLI --task-metadata-json
  merges into body.metadata with host-owned keys (delegation_role/source) unforgeable.

Bench harness (D/PB/TB):
- SWE-Pro e1v2: /app is the default active workspace (via user_files root), empty memory
  default, budget metadata (until_deadline, cost_hard_stop_pct=0) threaded through; bench1
  fixes (shard-safe auto_run, k=1, timeline) ported into the repo; the image-load lock and
  utility-image use are cross-platform (platform_layer, preflight-pulled, fail-safe restore).
- Workspace acting-integration allowlist (+integrate/compare_subagent_patches) with a
  fail-closed self_worktree-under-external-workspace integration guard.
- Protected-artifact policy round-2: structural (operation-identity) false-positive
  exceptions for differential-testing harnesses — vcs_diff/stat classifier, spawn-argv=argv[0]
  execute, interpreter script/module operand screening, writer-target segmentation — while
  read/copy/hash/introspection of the black-box reference stay blocked (incl. alias-separated
  reads); pinned by a new permanent policy test.
- ProgramBench instruction v2, until_deadline profile, acceptance claims. TB ffmpeg resolver
  chain (platform_layer/imageio-ffmpeg/PATH) + agent-prefix install + cv2 fallback hint.
- 4 verify-guidance clauses in prompts/SYSTEM.md (probe the consumer interface, exercise every
  provided input, robust-under-ambiguity, never read hidden graders).

Docs/versions: 6.56.0 across VERSION/pyproject/web/api_types/README/ARCHITECTURE; SWE-Pro +
TB METHODOLOGY (workspace/budget/memory/retry-gate disclosure), PB gate-20 operator method,
pricing sonnet-5, DEVELOPMENT scratch contract.

Reviewed via operator triad (openai/gpt-5.5 + google/gemini-3.5-flash + anthropic/claude-fable-5)
+ scope (anthropic/claude-fable-5) to convergence: scope clean; residual triad items are a
verified reviewer false-positive and the plan-accepted single-parameter budget-threading
tradeoff on a grandfathered core-loop function (advisory-bypass, documented).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 07:15:51 +00:00
Anton Razzhigaev
ef363ff243 feat(gaia): bwrap filesystem isolation masking the answer cache from all solvers
The GAIA answer key is cached on the host (metadata.parquet Final answer column +
per-task .jsonld under ~/.cache/inspect_evals and the HF dataset cache), and every
solver runs its agent as a host subprocess with shell access — so the agent can read
the answers off disk (observed: a Codex row ran `find … gaia_dataset … jq
<sample>.jsonld`; the leakage audit caught it). This is a filesystem sibling of the
web-lookup cheat.

Wrap every solver subprocess (Ouroboros + codex/claude/hermes, symmetrically) in
`bwrap --dev-bind / /` with the answer-cache directories masked by empty tmpfs,
leaving the rest of the FS, the network (web search), and CLI config intact. The
inspect scorer runs in the main process outside the wrapper, so scoring is unaffected.
New bwrap_isolate.py (default-on; GAIA_BWRAP_ISOLATE=0 to disable; fails loudly if
bwrap is missing rather than running silently unprotected). Disclosed in METHODOLOGY.
Verified: answer cache invisible inside the wrap; codex/claude solve end-to-end;
the Ouroboros dedicated server binds loopback and runs inside the namespace.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 21:21:31 +00:00
Anton Razzhigaev
bd8a2bc33a feat(gaia): anti-lookup instruction, native-web default, leakage audit v2, full harness traces
The 2026-07-04 GAIA runs caught agents looking up the published answer key
(googling "GAIA benchmark ... answer", downloading metadata.jsonl from mirrors)
and running the weak strict_ddgs retriever instead of native web search — the
latter mislabeled as parity with the native-searching Codex/Claude Code targets.

- Anti-lookup prompt: SSOT GAIA_ANTI_LEAK_INSTRUCTION appended by all four
  solvers, worded to avoid the benchmark name / "FINAL ANSWER" marker / the
  leak-query regex so it neither primes the model nor self-flags in traces.
- Full trace capture for audit parity: Claude Code -> --output-format
  stream-json --verbose (per-sample claude_code_trace.jsonl); Codex -> --json
  (codex_trace.jsonl). Both were black boxes before.
- Observability: persist usage.web_search_sources on llm_usage rows in
  events.jsonl so the audit can see native (server-side) web-search citations,
  which never appear in tools.jsonl (behavior-neutral).
- Audit v2 (audit_leakage.py + new SSOT leak_targets.py): strip prompt
  boilerplate before scanning traces (no self-flag); catch quoted "FINAL ANSWER"
  queries and dash-named GitHub mirror paths; STRONG gold-verbatim only when the
  gold answer came FROM a leak source (plain gold in a normal page is weak);
  scan events.jsonl native citations by root_task_id; parse CC/codex JSONL
  traces; fix WEB_TOOLS (+skill_exec/start_service, -nonexistent fetch_url/bash).
- Scoring: score_gaia.py --leakage-audit reports leakage_adjusted_accuracy
  (STRONG-flagged samples counted incorrect) alongside the authoritative score.
- Docs: METHODOLOGY (quality_openrouter_web is the publishable default; strict_ddgs
  is a handicap, not parity; pre-registered zeroing rule; per-harness coverage),
  README_harness_compare (who-searches table), ARCHITECTURE (three web-access
  mechanisms and their model/observability consequences).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 20:13:56 +00:00
Ouroboros
0a091cc9d1 feat: v6.55.0 bench devtools alignment — scaffold defaults, ProgramBench e2e, CLB launcher, OSWorld 2.0
Commit 3/3 of the bench post-mortem sprint (plan smooth-skipping-charm;
commits 1-2 = bf8bde7 v6.54.3, ef786bb v6.54.4). Minor bump per plan.

Shared bench-template scaffold defaults, disclosed in the benchmarks index
and per-bench METHODOLOGY files: OUROBOROS_MAX_WORKERS=4 (same-model
decomposition slots within one task, never best-of-N; TB 2->4, GAIA
--max-workers default 1->4 with explicit 1 as the strict-baseline ablation
and the quality-profile silent 1->5 bump removed, SWE-pro 5->4),
OUROBOROS_SAFETY_MODE=light (disposable jails; deterministic guards stay),
RUNTIME_MODE=pro for container benches (GAIA deliberately stays light: its
solver runs unisolated against a live repo), and claude_code_edit disabled
in every bench solve task (single-model harness measurement). TB raises
_DEADLINE_SAFETY_SEC 30->105 from measured finalization overhead, mirrors
the registry _WEB_TOOLS denylist (youtube_transcript drift fixed, pinned by
a sync test), and the README pins why --all-model keeps review single-model.

ProgramBench e2e runner ported from the colleague's tree, adapted to our
APIs: metadata.budget_profile onto the v6.54.4 contract (footer keys
dropped, reserve pct unit-fixed 0.15->15), solve-model preflight through
migrate_model_value (fail-fast on direct-route legacy ids), atomic
per-instance checkpoints with honored reattach (client poll timeout leaves
the executor alive; the next run skips seed/start and reattaches), explicit
payload-status terminal detection, denominator-preserving ledgers
(skipped_existing rows; skipped = successful for exit code), source-only
submissions (both root binaries excluded by name), idempotent workspace
normalization shared by the prepare-only flow.

New continual_learning/ launcher wraps the EXTERNAL CL-Bench runner
(nothing vendored; fails loudly with obtain instructions), strict-sequential
guard (parallel opt-in is exclusively-stateless-bridge only), standard-path
pointer rows keep the ledger denominator, fidelity gaps of the pinned
external adapter recorded and warned. OSWorld aligned to the official 2.0
protocol (pinned OSWorld-V2@c261cb57, 500-step default, show_result.py
layout, official traj rows), bridge-level final_answer capture with
VM-state-only prompting, preflight verifies the target server's effective
scaffold settings via /api/settings (env cannot configure a --url server)
and refuses the live desktop URL without an explicit flag.

LifelongAgentBench documented as blocked (its 100% run was a no-gold-oracle
artifact). Carriers synced to 6.55.0. Review: 6 triad+scope rounds to a
fully clean verdict (16 confirmed criticals fixed, each with a regression
test); gemini/opus clean in all rounds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 22:49:01 +03:00
Ouroboros
c736267db1 feat: release v6.54.0 follow-up audit hardening 2026-07-01 14:50:35 +03:00
Ouroboros
49f6d142b3 feat: harden benchmark-derived task evidence and runtime reality 2026-07-01 10:32:18 +03:00
Ouroboros
f3291bafeb feat(v6.52.1): GAIA-derived capability hardening + TB2.1 verification hygiene
P1 first-class attachment access (stage every task's attachments into agent-readable
artifact_store/attachments/ + ready read_file manifest + auto native-image blocks; CLI/API,
GAIA, desktop chat unified; staged inputs excluded from deliverables); tool_access default-deny
dotted components with a benign project-dotdir allowlist + workspace_task user_files READ.
P4a image<->tool_result ordering fix at the send-time chokepoint (all providers). P4b ocr_pdf
(text-layer) + youtube_transcript media tools. P2 finalize marker nudge. C verify_and_record
after-only artifact-lifecycle FLAG (executor/host surface-aware, traversal-confined). GAIA
adapter: agent-visible deadline + shared format prompt + staging + METHODOLOGY honesty notes.
D run_tb 3-tier low-k report_grade. (6.52.0 was tagged but full-test/windows caught a path-
confinement test bug; fixed-forward to 6.52.1.)
2026-06-29 05:44:17 +03:00
Ouroboros
060cbea317 feat(v6.50.0): add subagent reconciliation layer and harden SWE-Pro adapter 2026-06-27 08:04:57 +03:00
Ouroboros
6228735e4a devtools(gaia): --sample-id rerun selector + manifest lockstep
run_gaia.py gains --sample-id (comma-separated ids) to replay a chosen subset of tasks, mirrored into the Inspect argv. _write_manifest now records the EXACT selected ids via a shared _requested_task_ids() helper when --sample-id is set (else the limit-derived level list), so a sample-id rerun no longer writes a manifest claiming the first N level tasks — keeping the audit/denominator contract honest. Focused test covers the manifest selector and the argv lockstep.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:19:16 +03:00
ndrew1337
45d77ff785
tests+ci: green & de-flake the pre-push suite (P3/P6/xdist-safety) + parallelize CI ~9x (gate stays serial) (#55)
* test(improvement_backlog): stub semantic-dedup LLM in groom tests (P6)

_seed_many() seeds items via append_backlog_items(), whose C9.2 semantic-redirect
pre-pass calls semantic_dedup.find_semantic_duplicate_id() once per fingerprint-MISS
with candidates — a real light-model NETWORK call. The seeding runs BEFORE
_patch_groom_llm installs its mock, and that mock only covers chat_observed, not the
detector's own client path. With no API key the call retry-storms for minutes before
failing open to None, making test_groom_backlog_rejects_invented_items ~129s alone
(~40% of the whole suite) and non-deterministic.

Add a module-level autouse fixture that stubs find_semantic_duplicate_id to its own
fail-open default (None = no duplicate — exactly what the doomed call eventually
returns for the distinct seeded items), so the module is network-free and
deterministic. No production change; the dedup contract stays covered by
test_semantic_dedup_v6370.

Effect: test_groom_backlog_rejects_invented_items 129.12s -> 0.02s; whole file
~165s -> 2.37s, all 14 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(core): validate regex up front in _code_search so invalid-regex contract holds for both backends (P3)

_code_search ran the ripgrep path first and returned its formatted result before
ever reaching the Python-fallback re.compile guard. ripgrep accepts some malformed
patterns permissively — an unterminated '[' yields "no matches" instead of erroring
— so an invalid regex like "[invalid" silently returned no-match on the rg path while
only the fallback (rg absent/failed) emitted "⚠️ SEARCH_ERROR: invalid regex". This
made test_code_search_invalid_regex fail whenever ripgrep is present (i.e. always, in
CI and the pre-push preflight), so the suite exited non-zero on every candidate diff
regardless of the change under test.

Compile the regex once up front (regex queries only; literal queries need no check)
and return SEARCH_ERROR on re.error before dispatching to either backend, so both the
rg path and the Python fallback share the same invalid-regex contract.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: guard the conftest repo-root pollution sweep to the xdist controller (xdist-safety)

Under pytest-xdist, pytest_sessionfinish fires on the controller AND every worker against
the SHARED repo root, so the mock-pollution sweep (shutil.rmtree of leaked <MagicMock>
paths + session.exitstatus=1) had workers racing the same rmtree and each independently
failing the run — a non-deterministic, failed-shaped result. Guard the repo-root sweep +
exitstatus mutation behind `if not hasattr(session.config, "workerinput")` so it runs only
on the controller (the single authority); the per-process _PYTEST_DATA_DIR cleanup stays
outside the guard and runs on every process. Serial runs are unaffected (the guard is
always True without -n).

Adds tests/test_conftest_xdist_guard.py (sweep runs on the controller, skipped on a worker).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: parallelize the test suite with pytest-xdist (~9x faster), keep the gate serial

The full-suite CI jobs (quick-test, full-test) now run a PARALLEL pass plus a short SERIAL
pass. Empirically ~270s serial -> ~30s parallel (~9x). The per-commit preflight GATE stays
serial by design (a flaky parallel fail-closed gate manufactures non-deterministic
TESTS_FAILED indistinguishable from a real immune rejection).

- requirements: pytest-xdist + pytest-timeout (a hang-guard).
- pyproject: register the `serial` marker (addopts unchanged).
- ci.yml (quick-test, full-test): two-step. Parallel
  `-m "not serial and <default lane exclusions>" -n auto --dist loadscope
  --max-worker-restart=0 --timeout=300 --timeout-method=thread`, then serial
  `-m "serial and <exclusions>"`. A command-line -m REPLACES the pyproject addopts markexpr,
  so the default lane exclusions are repeated and ANDed with the serial split — the union
  exactly reproduces the old default suite (4594 parallel + 122 serial = 4716, disjoint).
- conftest: a tryfirst pytest_collection_modifyitems hook marks the real-process/port files
  (workspace_executor[+cleanup], process_custody, kill_process_tree_orphans, zombie_prevention,
  worker_crash_retry, process_resource_leaks, restart_reconnect, preflight_runner,
  services_tool_v2) `serial`; plus an autouse fixture isolating workspace_executor._SERVICES/
  _FOREGROUND between tests (a latent ordering bug -n redistribution exposes).

Test-isolation fixes surfaced by running the suite under -n:
- test_task_constraint_tools: 3 bare `sys.modules["...claude_code"] = mock` (no restore ->
  polluted the worker's sys.modules -> later SDK-dependent tests failed) -> monkeypatch.setitem.
- test_workspace_executor: poll until the spawned process's command-sha is readable before
  registering (the PID-reuse safety check compared the sha recorded at registration vs
  recomputed at kill; right after fork+exec the command line is unreadable -> shas diverge ->
  kill silently skipped -> flaky), + 5->15s kill-confirmation deadlines.

docs/DEVELOPMENT.md + docs/CHECKLISTS.md: guidance so future tests are parallel-safe or
marked `serial`. Reviewed by adversarial subagents (ship); verified parallel 8/8 + serial 3/3
green, partition exact + disjoint, gate byte-identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* tests+ci: parallel-safety follow-ups (services-global isolation, serial-lane guard, monkeypatch conversions)

Three non-blocking follow-ups from the parallelization review, hardening the
xdist split shipped earlier in this PR:

F1 (tests/conftest.py): extend the autouse _isolate_workspace_executor_globals
fixture to ALSO snapshot/clear/restore ouroboros.tools.services._SERVICES (the
legacy services registry, a separate module-global from workspace_executor's)
under its plain threading.Lock _LOCK. Closes the legacy-services-path
global-leak class generally; raw dict ops only under the lock (no re-entrant
deadlock on the plain Lock), registry-only (never reaps the live Popen
handles), each module lazy-imported under its own guard.

F2 (.github/workflows/ci.yml): add a "Guard non-empty serial marker lane" step
to marker-guards. `pytest --collect-only -m serial` exits 5 on an emptied
_SERIAL_TEST_FILES; set -euo pipefail + tee surfaces it, and a positive anchor
grep on test_workspace_executor.py is the working assertion (the existing
browser-guard's `! grep "no tests collected"` is a dead no-op under -q).

F3 (test_skill_loader / test_iteration2_fixes / test_marketplace_clawhub /
test_devtools_benchmarks): convert remaining bare os.environ / sys.modules
mutations (no save-restore) to auto-reverting monkeypatch.setenv/delenv/setitem,
so the parallel suite has no cross-test env/module leaks. tests/_shared.py's
intentional process-wide SDK mock left untouched.

Verified: parallel lane 4574 pass (-n auto --dist loadscope), serial lane 140
pass, the 4 converted files 159 pass. Two subagent reviews: no regressions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: prune 26 redundant/tautological/obsolete tests (immune coverage retained)

Three-pass audit (finder+skeptic -> 31 empirical verifiers with rename+mutation
experiments -> delete-and-run dry-run) of the 275-file / 4067-test suite found 26
tests whose value is fully backstopped by a stronger survivor or is near-zero:

- tautological / zero-production pins (assert hasattr/callable; inline-simulated
  branches; closed-loop regex; TypedDict dict-literal; CPython-only checks);
- proven duplicates with strict-superset twins (test_consolidator, test_commit_gate,
  test_cache_optimization, test_review_intent_split, TestGrepRegexHint, ...);
- registry-registration one-liners, all backstopped by test_smoke::test_tool_set_matches
  (set-equality vs EXPECTED_TOOLS -- mutation-proven to FAIL on a lost registration);
- dead-feature tests (retired skill_migrations module) + obsolete version regressions
  (v636 import now unconditional; README "(N tests)" convention abandoned).

Removes ~47 test functions across 20 files (incl. the whole test_shell_regex_hint.py,
mirrored 1:1 in test_shell_run_shell.py::TestGrepRegexHint, and the whole
TestGoalScopePrecedence class). Also drops 2 now-unused imports + 1 orphaned helper.

KEPT (not redundant): test_smoke::test_git_commit_with_tests_exists -- sole guard of the
post-commit gate seam (a rename experiment proved nothing else catches its loss).

Verified: ruff F clean; collection exit 0 (4703 collected, no emptied class); full
parallel + serial suites green; two subagent reviews confirm exact set + no broken refs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Andrew <andgri200@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 02:56:34 +03:00
Ouroboros
9eae6e9c63 devtools(gaia): run_gaia.py works out-of-the-box beside a running desktop app
The v6.46.0 GAIA adapter could not start its dedicated benchmark server while the
desktop app was running: (1) it bound the default Host Service port 8767, which the
live app holds, crashing startup ("port 8767 busy"); (2) settings_base.json ships
EMPTY provider-key placeholders, which apply_settings_to_env pops from os.environ,
erasing the real keys _sanitized_host_env preserved ("No supported provider configured").

Fix (devtools-only, no runtime-core change):
- _free_port(): auto-pick distinct free ports for BOTH the main server (GAIA_OUROBOROS_URL
  / OUROBOROS_SERVER_PORT) and the Host Service (OUROBOROS_HOST_SERVICE_PORT), so the bench
  server coexists with the desktop app and parallel configs never collide on a port.
- _resolve_provider_keys(): inject the REAL keys for the configured models + the pinned web
  backend (from os.environ, then data/settings.json) into the rendered settings so the
  server detects the provider; keys land only in the isolated, gitignored run dir. 'auto'
  web pulls all keys (cascade); a pinned backend only its own; OPENAI_BASE_URL is dropped
  for an 'openai' web pin (official web_search needs an empty base_url).

Verified out-of-the-box: plain run_gaia.py started the dedicated server cleanly (free Host
Service port, Supervisor ready, key injected) alongside a running desktop app + two live
L1 runs. New focused test (test_gaia_render_injects_keys_and_free_host_service_port) + all
90 devtools tests green; ruff F clean. devtools-only follow-up to v6.46.0 (no version bump,
matching the devtools-commit precedent).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:42:29 +03:00
Ouroboros
c36e9cd4cf feat(v6.46.0): GAIA-forensic hardening — generalizable runtime fixes + empirical context-window probe
A GAIA validation audit surfaced harness artifacts that masked Ouroboros's real
capability. This lands the GENERALIZABLE fixes (helping all users, not fitting the
benchmark), a Max-mode generative context-window probe, and a reviewed GAIA adapter.

Runtime:
- Budget exhaustion TERMINALIZES undispatched PENDING tasks (`fail_tasks`,
  reason_code=budget_exhausted + task_done event, canonical budget_drive_root,
  cancel-requested -> CANCELLED) instead of a silent never-dispatched freeze.
- `search_code` gains a shared wall-clock deadline (rg walk + batch loop + Python
  fallback, one budget) and a DISTINCT deadline-truncation signal so a timed-out
  search never reads as an authoritative "no matches" (OUROBOROS_SEARCH_CODE_WALL_SEC).
- `web_search` backend pin (OUROBOROS_WEBSEARCH_BACKEND: auto|ddgs|openai|openrouter|
  anthropic; openai/ddgs are TRUE pins, no cascade); `ddgs` is now a dependency with
  429 backoff so a fixed-model run can force pure retrieval.
- `OUROBOROS_OR_PROVIDER` (resilience/repro presets) routes OpenRouter providers for
  rate-limit resilience without losing prompt-cache warmth (gap-merged; never overrides
  the require_parameters / reasoning-continuity pins), behind a supports_message_cache_control predicate.

Answer integrity: a tool-count-stamped latch recovers a produced FINAL ANSWER whose
marker a later (un-grounded) round drops, while new tool work invalidates a stale latch
(Q7 no-downgrade); acceptance review on the ADVISORY task surface stops over-failing a
grounded answer (surface-keyed: majority-not-single-FAIL, no solved->DEGRADED on empty
coach). The P3 commit/scope immune gate is untouched.

Security: `user_files` honors OUROBOROS_USER_FILES_ROOT (jailed scratch home; '~'/'~user'
and unnamed deliverables stay IN the jail); the authoritative observability blob is
redacted by default (env-only OUROBOROS_OBSERVABILITY_KEEP_RAW opt-in) with an allowlist
secret matcher that spares cognitive content (sha/commit/uuid/route_fp/model/answer).

Capability: a generative context-window probe (public LLMClient.probe_oversized_context
seam) empirically confirms a route's >=1M window from a FREE over-window reject — only on
the explicit Max toggle/save, never auto-confirming a possibly-paid 200, fail-closed,
bypasses a stale lazy cache; plus a cloud.ru route base_url fix.

Bench: the GAIA adapter (devtools) stages attachments robustly, injects the FINAL ANSWER
protocol, crash-isolates per-sample timeouts (+ server-side ceiling so a hung sample
cannot orphan the shared queue), and exposes per-config knobs (vision slot, review models,
web backend, budget, epochs) with cross-provider credential preservation.

Version carriers bumped 6.45.5 -> 6.46.0; MAX_TOTAL_FUNCTIONS 3520 -> 3524 (reviewed
single-purpose helpers); ARCHITECTURE/README updated. Reviewed to convergence (adversarial
subagents + codex gpt-5.5 + real triad+scope) with a green full suite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 12:40:40 +03:00
Ouroboros
83d37c5110 devtools(gaia): parse official string scores
Treat Inspect GAIA scorer string values such as C/I as authoritative correct/incorrect outcomes so smoke summaries match the official accuracy table.
2026-06-24 14:36:45 +03:00
Ouroboros
fedb09bda5 devtools(gaia): harden solver smoke startup
Keep GAIA run roots valid when their own per-run settings/data env is active, and retry the transient supervisor startup window so the first sample does not flake before producing a structured answer.
2026-06-24 14:25:02 +03:00
Ouroboros
563cbef01c release: Ouroboros v6.45.4 Terminal-Bench timeout smoke fix-forward 2026-06-24 07:09:45 +03:00
Ouroboros
ab483c6344 release: Ouroboros v6.45.0 Phase 3 vision routing and GAIA adapter 2026-06-24 06:28:14 +03:00
Ouroboros
4ebbd2b2dd release: Ouroboros v6.44.0 Phase 2 benchmark and capability fixes 2026-06-24 06:22:31 +03:00
Anton
24991292e8 devtools(tb): faithful-network tool-policy + agent deadline awareness (TB2.1 methodology fix)
WIP checkpoint (local, not pushed) — to be reviewed-merged into repo/ after the re-run.

Fixes two TB2.1 methodology bugs that depressed gpt-5.5's measured score:

1. Network: the adapter set allowed_resources={web:false,network:false} on
   disable_agent_web, which blocked `git clone` even though TB2.1 tasks need it
   (every task.toml allow_internet=true; verifier clones in-container). Replace
   with a declarative `disabled_tools` tool-policy: withhold the agent's own
   web_search/browse/browser/analyze_screenshot/vlm_query tools (anti-reward-hack,
   == original _WEB_TOOLS set) while leaving shell egress (git/pip/curl) intact.
   - task_contract.disabled_tools (additive frozen-ABI field) + normalize_disabled_tools
   - registry hides disabled tools from schemas()/core_only/get_schema_by_name/
     available_tools (+ dynamic extension/MCP) and blocks them at execute
   - /api/tasks + TaskCreateRequest (+ api_types.js mirror) thread the field
   - propagates to subagents via the parent-contract spread
   - view_image intentionally kept (local image-to-model, outside _WEB_TOOLS)

2. Deadline: Harbor's per-task wall-clock cap was never plumbed into Ouroboros
   (deadline_at=""), so pacing/graceful-finalize were dormant and the agent was
   hard-killed mid-work with empty results.
   - D1: adapter resolves the per-task [agent].timeout_sec from cached task.toml,
     subtracts elapsed install/server time + 30s safety, passes timeout_sec ->
     deadline_at so the agent paces and self-finalizes a partial before the kill
   - D2: surface inherited deadline_at from task_contract into task_metadata so
     spawned subagents also pace/finalize
   - _capture_current_task_summary records captured_after_cancellation only on a
     real interruption (not a terminal infra_failed exit), so the disclosure
     ledger no longer misreads a terminal provider_unavailable as a cancellation

Plus the run_tb disclosure-ledger honest taxonomy (pass/provider_infra/cancelled/
genuine) and tests (test_disabled_tools_policy.py, test_run_tb_methodology regression,
adapter terminal-nonzero-exit test) + docs/ARCHITECTURE.md ABI rows.

Reviewed: codex (gpt-5.5) + 7 rounds triad+scope to convergence; only the
version-bump touchpoint remains, intentionally deferred to the eventual merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 22:09:02 +03:00
Ouroboros
c133be3ceb devtools(tb): align adapter to OUROBOROS_MODEL_HEAVY (v6.39 rename), doc disclosure_ledger, fix 2 stale tests
The in-container HEAVY lane reads os.environ["OUROBOROS_MODEL_HEAVY"] (config.py:275);
the legacy OUROBOROS_MODEL_CODE env var is a dead no-op after the v6.39 Phase-2 slot
rename (the rename-alias migrate_legacy_slot_keys covers only the settings-file path,
not env vars). Harmless for the single-model run already executed (HEAVY empty -> main
fallback -> gemini) but a silent bug for future ensemble runs where HEAVY != main, as
the neighbor's release plan anticipated. Forward + set OUROBOROS_MODEL_HEAVY instead.

Update two now-stale tests in tests/test_devtools_benchmarks.py that the merge breaks:
- assert OUROBOROS_MODEL_HEAVY (not _CODE) in the container env (slot rename above);
- the default harbor_command must OMIT --agent-setup-timeout-multiplier /
  --environment-build-timeout-multiplier: Harbor static_validation rejects them
  (static_validation.py _trial_timeout_override_fields), so the cherry-picked Fix-1
  leaderboard-faithful default is correct; the old assertions + "methodology-allowed"
  comment encoded the now-rejected behavior.

Also documents the post-run disclosure_ledger.json (schema tb_disclosure_ledger.v1) in
the devtools-benchmark paragraph of docs/ARCHITECTURE.md (deferred merge-time doc TODO).

No version bump: devtools dev-infra work; the bump rides the next release.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 20:30:59 +03:00
Ouroboros
b09a60fa7f feat(core): v6.40.0 — LLM-first project naming, per-model self-DoS guard, soft join-ledger, orchestrator read-only roots, turn-into-project ordering, deferrals 1-5
Naming (B): SSOT `ouroboros/project_naming.py` coins a short human project title via a
bounded LIGHT-model call (P5, no keyword gates; fail-soft to a heuristic; spend recorded
through chat_observed + update_budget_from_usage). A proactive card namer
(`supervisor/workers.py::_spawn_proactive_namer`) names a fresh main-chat card up front —
background thread → `suggested_name` on the result + a `task_named` WS broadcast → the live
card shows the title (UI-buffered if the card races ahead; persisted across reload via
history.py for progress AND task_summary rows). turn-into-project reuses that name with ZERO
extra call; the heuristic `task-…` is gone. ensure_project_scope/agent paths share the SSOT.

Ordering (A): the owner's request sorts to the TOP of the converted project thread —
`_owner_message_send_ts` matched in the originating chat at/before task creation (dup-text
safe), then queued_at / result ts / now. chat_id persisted on the direct-chat RUNNING result.

Self-DoS (#4): a per-(model,use_local)-route `threading.BoundedSemaphore`
(`ouroboros/model_concurrency.py`, `OUROBOROS_MODEL_MAX_CONCURRENCY` from the config SSOT,
default-on, fail-soft, deadline-bounded, cap in the cache key) caps CONCURRENT provider
calls within a process so a task's loop + in-process subagent threads + status pings can't
storm one rate limit. PER-PROCESS (like fallback_cooldown); cross-worker is future work.

Soft join (#7): cancel_task gains a recorded reason; new peek_task inspects a child WITHOUT
absorbing; new discard_child_result(reason) is the EXPLICIT (not prose-parsed) abandon —
both stamp a durable parent_decision the handoff reminder honors, lineage-gated to own
children (cancel fail-closed for constrained profiles). The prose acknowledgement gate is
REMOVED (P5): the reminder is suppressed only by structured decisions/absorption, and a
forced/deadline/provider finalization records orphaned (incl. completed-unread) children
instead of dropping them. peek/discard/cancel extracted to `ouroboros/tools/join_ledger.py`.

Deferrals 1-5 (C): read-only `subagent_projects`/`deliverables` ResourceRoots (never
write/shell, never to subagents); a freshly provisioned genesis root must be empty
(fail-loud); a genesis project emits a typed `deliverable_manifest` on the artifact axis; a
shared `_str_match_replace` gives the data-plane editor the repo editor's match feedback; a
data-plane shrink-guard blocks accidental overwrite/edit truncation (force bypass) across
_data_write/_write_file (single+batch)/_edit_text incl. skill_payload.

Workstreams (E): bench swe_bench_pro/osworld slot keys CODE/FALLBACK/USE_LOCAL_CODE →
HEAVY/FALLBACKS/USE_LOCAL_HEAVY; stale joi-lab catalog URLs → razzant in repo.

Surface: peek_task/discard_child_result tools, OUROBOROS_MODEL_MAX_CONCURRENCY,
subagent_projects/deliverables resource roots, TaskNamedOutbound WS contract. Reviewed:
triad+scope converged (scope pass + gemini/opus SAFE) + codex SAFE TO COMMIT.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:32:37 +03:00
Ouroboros
83e3217766 devtools(bench): upgrade harness-bench-fast adapter + rebase slot keys to v6.39 HEAVY/FALLBACKS
Dev-infra only (not runtime). Integrates the upstream terminal-bench-fast adapter:
- Apply the upstream harbor patch: terminal_bench/harbor_installed_agent.py env allowlist
  (OUROBOROS_MODEL_DEEP_SELF_REVIEW + EFFORT_* keys; tree-sitter-optional requirements) and
  run_harbor_smoke.py CLI (-k, agent/environment timeout multipliers, --ouroboros-light-model).
- Replace harness_bench_fast/ouroboros_cli_wrapper.py (54 -> 227 lines: workspace git-init,
  per-task logs, model env, --start, retries, --result-json-out, --actor-id, pro+advisory),
  rebased to the v6.39 Phase-2 slot rename (OUROBOROS_MODEL_HEAVY / _FALLBACKS, never the
  legacy CODE / FALLBACK), and keep honoring the OUROBOROS_BIN env override for --ouroboros-bin.
- Add harness_bench_fast/run_harness_bench_fast.py (orchestrator) with the hardcoded
  DEFAULT_BENCH_ROOT parameterized to env HARNESS_BENCH_ROOT or a repo-relative fallback (no
  contributor home path).
- Update the coupling test to the new command-shape + Phase-2-slot contract (the old
  build_command unit no longer exists).

Verified: py_compile, ruff --select F clean, test_devtools_benchmarks + test_headless_cli
green; reviewed by claudexor codex (gpt-5.5, the OUROBOROS_BIN-override regression it flagged
is fixed). Pre-existing legacy slot keys in other benchmark suites (swe_bench_pro, osworld)
remain functional via the runtime's heavy->main fallback + FALLBACK alias; renaming them is a
separate follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:44:06 +03:00
Ouroboros
eb33abd491 feat(skills/bench): unix_computer_use overhaul with coordinate normalization and Wayland support, native launcher-seed trust, bench adapter hardening (v6.31.0)
Phase 1 Blocks 4+6 of the combined release plan (owner-approved single commit):

Block 4 — unix_computer_use (renamed from computer_use; Windows stays a
future separate skill per P7):
- Coordinate normalization: screenshots downscale to fit WXGA and persist
  the exact image->input transform; input tools consume the last
  screenshot's image space (raw=true bypass); honest approx flags for
  multi-display unions (incl. deceptively clean sub-1.0 scales) and
  TCC-denied logical-size failures.
- Wayland: session detection, grim capture, ydotool pointer (mask codes
  0x40|btn / 0x80|btn), wtype typing; key/hold_key are honestly
  unsupported on Wayland (ydotool key takes raw keycodes only — silent
  no-op success is refused).
- New actions: left_click_drag, mouse_down/mouse_up, triple_click,
  hold_key (macOS pure-modifier-only honesty), cursor_position, wait.
- X11 keys: f1-f16 aliases, super/meta modifiers, original-case
  preservation for case-sensitive keysyms in key AND hold_key; '--'
  option terminator in type_text.
- ax_tree: macOS set-of-marks of the frontmost window (numbered
  role/title/center marks, INPUT-space coordinates) with honest
  degradation; Linux degrades to window list.
- Native launcher-seed trust (named, hash-pinned, audited exception —
  CHECKLISTS §Skills, plan-approved): the launcher stamps
  review.json status=clean (repo_commit_gate/native_seed) at its three
  payload-write moments; verdict hash-pinned AFTER seeding and
  provenance-BOUND at load (no .seed-origin or unverifiable provenance
  => pending); hash exemption covers ONLY the top-level marker of
  native-bucket payloads; one-shot legacy-hash migration cannot
  whitewash edits; zero-grant skills (tool/subprocess surface only)
  auto-enable only when no explicit owner choice exists (a disable
  survives version resync); OUROBOROS_TRUST_NATIVE_SEEDED_SKILLS
  default-on opt-out.

Block 6 — bench adapters (devtools):
- run_tb.py: methodology-allowed setup/build timeout multipliers (4x);
  per-task multiplier stays 1.0.
- Single-model metric hardening: the container fallback is pinned to the
  effective main model in every reachable configuration (kwarg ->
  forwarded host model -> packaged default) so SETTINGS_DEFAULTS cannot
  resurrect a different fallback model inside the settings-less
  container; host fallback is never forwarded.
- max_workers default 2 (plan_task scouts); defensive AgentContext
  deadline probe (no-op today, harbor-docs-verified).

Also: SYSTEM.md attempt-cap paragraph (plan-approved surface, v6.30
catch-up doc-sync). Upgrade note: legacy computer_use payloads remain as
reclassified non-launcher skills until manually deleted.

Gauntlet: adversarial pass 1 (GPT+Gemini, 5 blockers fixed) + pass 2
(Fable, SAFE TO COMMIT, 3 minors applied); triad+scope rounds 1-5 with
scope responded every round; round 5 clean (0 criticals).
2026-06-13 02:55:12 +03:00
Ouroboros
c3d730546f swe-pro: e1v2 evolution harness (replaces evolve_pro)
New SWE-bench-Pro E1v2 harness: Docker-isolated per-task runs with optional
post-task self-evolution, an autonomous multi-task runner with last-good
snapshot/restore, and offline grading. Secrets reach the container only via a
name-only env opt-in (never argv); a refused opt-in / infra skip is surfaced
through the timeline so the runner stops or skips instead of counting a
non-executed task as legitimate; --cadence off disables evolution via the
documented contract; predictions carry the leaderboard model_name_or_path.
English-only operator strings. Removes the superseded evolve_pro path.
2026-06-11 16:10:31 +03:00
Ouroboros
6ff64927c4 feat(devtools): add auditable benchmark ledgers
Add denominator-preserving benchmark manifests and result ledgers across the devtools adapters, tighten Terminal-Bench/Harbor and OSWorld fail-closed preflights, and harden workspace patch artifacts for unborn, invalid, and acting-subagent git baselines.\n\nVerification: focused benchmark/headless/acting suites, isolated full pytest, adversarial review rounds, and real Ouroboros triad/scope review artifacts under bench_runs/devtools_sync_20260607_010949/reviews.
2026-06-07 09:44:20 +03:00
Ouroboros
e035e527d4 fix(release): restore green full-test (windows-latest) for v6.20.1
The v6.20.0 tag CI failed only on full-test (windows-latest); ubuntu and macOS
were green. Two unrelated, test-only failure classes:

- Acting-subagents (this feature): the _make_child_patch test helper wrote
  workspace.patch via write_text(), which translates "\n" -> "\r\n" on Windows,
  so the file sha256 (read as bytes by integrate_subagent_patch) diverged from
  the manifest digest and tripped INTEGRATE_PATCH_CORRUPT. The helper now writes
  the exact hashed bytes (write_bytes), matching production (headless.py writes
  the patch with open("wb")). Product code unchanged.

- Pre-existing (devtools/executor from d863197, surfaced by the first tag since
  the untagged devtools-benchmarks release): test_official_command_builders used
  a hardcoded POSIX path literal (now compares str(Path(...))); four
  workspace-executor tests assume POSIX path spellings / process-group kill
  semantics and are skipped on Windows with explicit reasons. macOS/Linux keep
  full coverage.

Version 6.20.0 -> 6.20.1 across all carriers (VERSION, pyproject, package.json,
GATEWAY_CONTRACT_VERSION, ARCHITECTURE header, README badge + relabeled history
row). No runtime behavior change.
2026-06-06 16:25:33 +03:00
Ouroboros
d863197cf6 feat(devtools-benchmarks): add official benchmark harnesses and workspace executor 2026-06-06 12:03:30 +03:00