Skip to content

DEV-1591: SLayer agent prompts use compact=True for broad search - #58

Merged
ZmeiGorynych merged 34 commits into
mainfrom
egor/dev-1591-slayer-agent-prompts-use-compacttrue-for-broad-search
Aug 11, 2026
Merged

DEV-1591: SLayer agent prompts use compact=True for broad search#58
ZmeiGorynych merged 34 commits into
mainfrom
egor/dev-1591-slayer-agent-prompts-use-compacttrue-for-broad-search

Conversation

@ZmeiGorynych

@ZmeiGorynych ZmeiGorynych commented Jun 23, 2026

Copy link
Copy Markdown
Member

What

Teaches the SLayer agents explicit compact-mode search discipline to cut avoidable token cost.

A glm-5.2 run on households_16 paid ~6x cache-read and ~3.8x prompt tokens vs raw mode: the agent ran a broad search(question=…, max_results=10, compact=False), returning 10 full entity renders (~55K chars) that then rode in cached context every subsequent turn. SLayer 0.8.1: SearchHit.text == "" if compact else <full render>, so compact=False only pays off for a small, already-chosen entity set; broad discovery only needs the one-line description.

Fix (prompts only)

New single-source, param-free, brace-free constant _COMPACT_SEARCH_DISCIPLINE in _shared_otf_prompts.py:

  • Broad exploration (search(question=…), large max_results) → compact=True (default).
  • Targeted detail (search(entities=[…]), small known set / single memory:<id>) → compact=False.
  • Plus cypher_filter kind-narrowing guidance (MATCH (n:Memory|ModelColumn|…) RETURN n.id AS id) so broad searches spend their slots on the right kind.

Embedded (via import + concatenation, so no duplicated literal text → no drift) into every SLayer prompt surface:

  • HOST_DISCOVERY_PLAYBOOK (stays one object, no .format() placeholders) + its broad-search example made explicit (compact=True).
  • the orphan _SLAYER_TOOLS_BLOCK and both SLAYER v0 snapshots.
  • the live v1 head blocks _ENCODE_CORE_HEAD / _AINTERACT_SLAYER_TOOLS.
  • claude_sdk SLAYER_A_INTERACT / SLAYER_C_INTERACT.

Raw prompts untouched. The v0 SLAYER snapshots are deliberately patched (no longer pure-frozen); their docstrings were updated to say so.

Forward-compatible with DEV-1590/1588: when inspect_entity lands, the targeted-detail half migrates to it; the exploration→compact=True rule stays.

Tests

Per the project no-prompt-content-tests rule, no new prompt-content/behavioral tests. Re-baselined the two v1 SLAYER SHA snapshots in tests/test_shared_otf_prompts.py, added the constant to the existing non-empty check, and fixed stale V0 comments. Full non-integration suite: 3297 passed, 94 skipped, 0 failures.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added compact-mode search discipline to keep broad discovery lightweight and detail retrieval targeted.
    • Updated discovery prompts to explicitly vary by query mode and cap discovery turns.
    • Introduced run annotation version/agent-model provenance, with version-aware latest-run selection and reporting.
    • Added a one-time backfill utility to stamp missing/outdated version metadata.
  • Bug Fixes
    • Improved provenance propagation during annotation merges and re-grading.
    • Fixed discovery to consistently use the intended query-mode prompt.
  • Documentation
    • Refreshed prompt documentation and updated CLI smoke-test instructions for defaults.
  • Tests
    • Re-baselined golden prompts and expanded coverage for compact discipline and version/provenance behavior.

Broad `search(question=…)` exploration runs returned full per-entity
renders under compact=False (a glm-5.2 households_16 run paid ~6x
cache-read tokens vs raw mode because a 10-hit broad search rode in
cached context every turn). SLayer 0.8.1: SearchHit.text == "" when
compact else <full render>, so compact=False only pays off for a small,
already-chosen entity set.

Add a single-source, brace-free `_COMPACT_SEARCH_DISCIPLINE` constant
(broad question= → compact=True; targeted entities=[…] → compact=False;
plus cypher_filter kind-narrowing) and embed it into every SLayer prompt
surface: the host-discovery playbook, the orphan _SLAYER_TOOLS_BLOCK, the
two SLAYER v0 snapshots, the live v1 head blocks (_ENCODE_CORE_HEAD /
_AINTERACT_SLAYER_TOOLS), and claude_sdk SLAYER_A_INTERACT /
SLAYER_C_INTERACT. Raw prompts untouched.

Re-baseline the two v1 SLAYER SHA snapshots; no new prompt-content tests
(per the no-prompt-content-tests rule). Full non-integration suite green.

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

linear Bot commented Jun 23, 2026

Copy link
Copy Markdown
DEV-1591 SLayer agent prompts: use compact=True for broad search exploration (token fix)

Unblocked subset of DEV-1590 — independent of DEV-1588 (inspect_entity). This is a pure prompt change to the bird-agents SLayer agents that cuts tokens today, with no SLayer-side dependency.

Problem

In a glm-5.2 bird-interact run on households_16, the SLayer-mode agent used ~6x the cache-read tokens and ~3.8x the prompt tokens of the raw-mode agent. The dominant avoidable cause: the agent ran a broad exploration search with compact=False:

search(question="economic status of a house", max_results=10, compact=false)

That returned 10 full entity renders in one ~55K-char message, which then rode along in cached context every subsequent turn.

Confirmed in SLayer 0.8.1: SearchHit.text = "" if compact else <full render>. So compact=False only matters when you want the full per-entity text (Type / Description / Allowed aggregations / SQL / Sample values) for a small, already-chosen set. For broad discovery you only need the one-line description, which compact=True gives.

Fix (prompts only)

Add explicit compact-mode discipline to the SLayer-agent prompts:

  • Exploration (search(question=…), large max_results) → compact=True.
  • Targeted detail (search(entities=[…]), small known set) → compact=False.

Touch points:

  • agents/_shared_otf_prompts.py
  • agents/_host_discovery_playbook.py (already uses compact=False for known-column reads and the cypher_filter discipline; add the explicit "broad question= search → compact=True" rule alongside it)
  • agents/claude_sdk/prompts.py

Notes

  • No new tests (per the no-prompt-content-tests rule); run the full non-integration suite to confirm nothing breaks.
  • This is forward-compatible with DEV-1590 / DEV-1588: when inspect_entity lands, the targeted-detail half migrates to it, but the exploration→compact=True rule stays.

Review in Linear

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds shared compact-search prompt text, threads it through SLayer and discovery prompts, and introduces run-record version provenance with backfill, filtering, and stamping across annotation IO and reporting.

Changes

Compact Search Discipline Propagation

Layer / File(s) Summary
Define shared discipline and update v0 prompts
src/bird_interact_agents/agents/_shared_otf_prompts.py
Adds _COMPACT_SEARCH_DISCIPLINE, refactors shared SLayer prompt assembly, and inserts the discipline into the v0 one-shot and ainteract prompt snapshots.
Inject discipline into Claude SDK prompts and host playbook
src/bird_interact_agents/agents/claude_sdk/prompts.py, src/bird_interact_agents/agents/_host_discovery_playbook.py
Imports _COMPACT_SEARCH_DISCIPLINE into Claude SDK prompt constants and the host discovery playbook, converting those prompt definitions to concatenated string expressions.
Make discovery prompts depend on query_mode
src/bird_interact_agents/agents/claude_sdk/partition.py, src/bird_interact_agents/agents/claude_sdk_otf_v1/agent.py, src/bird_interact_agents/agents/claude_sdk_otf_ainteract_v1/agent.py, src/bird_interact_agents/agents/claude_sdk_otf_raw_v1/agent.py, src/bird_interact_agents/agents/claude_sdk_otf_ainteract_raw_v1/agent.py, src/bird_interact_agents/agents/claude_sdk_otf/prompts.py, src/bird_interact_agents/agents/claude_sdk_otf_ainteract/prompts.py, tests/data/dev1603/*.golden.txt, tests/test_shared_otf_prompts.py, tests/test_otf_host_discovery_playbook_propagation.py, CLAUDE.md
Adds _DISCOVERY_COMPACT_NOTE and query_mode to build_discovery_prompt, updates the four agent call sites to pass "slayer" or "raw", and refreshes prompt docs, goldens, smoke-test notes, and prompt coverage tests.

Run Version Provenance

Layer / File(s) Summary
Add provenance schema and resolver helpers
src/bird_interact_agents/eval/annotation_schema.py, src/bird_interact_agents/eval/versioning.py
Adds optional version and agent_model fields to SubmissionAnnotation and introduces version-resolution, manifest parsing, local-manifest loading, and provenance stamping helpers.
Stamp provenance during writes and reads
src/bird_interact_agents/eval/annotation_io.py, src/bird_interact_agents/cloud/post_run_merge.py, src/bird_interact_agents/eval/grade_in_place.py, src/bird_interact_agents/eval/regrade.py, src/bird_interact_agents/eval/cascading_report.py
Extends run-annotation writers and latest-run selection to support optional provenance inputs and version filtering, and updates merge, grade, regrade, and cascading report call sites to pass run context.
Backfill and filter run records by version
scripts/backfill_run_versions.py, scripts/cascade_for_combo.py
Adds the backfill script for stamping existing run records and updates cascade selection plus its CLI to filter results by version and report the new counters and payload fields.
Cover provenance stamping and version filtering
tests/scripts/test_backfill_run_versions.py, tests/scripts/test_cascade_for_combo.py, tests/test_cascading_report.py, tests/test_dev1591_versioning.py
Adds tests for backfill stamping, cascade version filtering, cascading report version selection, and version-resolution and write-path provenance behavior.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90 minutes

Possibly related PRs

  • MotleyAI/bird-agents#44: Shares the same _shared_otf_prompts.py prompt-fragment extraction and SLayer prompt composition path.
  • MotleyAI/bird-agents#48: Touches the same scripts/cascade_for_combo.py selection flow and run-record handling.

Poem

🐇 I hopped through prompts with compact grace,
Then stamped each run with versioned trace.
Old paths now bloom with fields aligned,
And search rules dance, neatly twined.
A rabbit smiles beneath the moon —
Two tidy threads stitched into tune.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the main change: updating SLayer prompts to use compact=True for broad search.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

…agent

origin/main brought in the DEV-1581 R2 two-stage v1 split: `ask_discovery` is a
separate warm discovery LLM that owns `search` / `inspect_model` /
`models_summary`, and the main v1 loop reaches it via `ask_discovery` instead of
holding those tools.

Conflicts resolved:
- _shared_otf_prompts.py: kept BOTH new constants (_COMPACT_SEARCH_DISCIPLINE and
  origin/main's _RAW_HOST_PATH_PRINCIPLE).
- test_shared_otf_prompts.py: recomputed the v1 SHA snapshots for the merged
  prompts.
- DEV-1603 V0 goldens: re-baselined the two slayer V0 goldens for the deliberate
  DEV-1591 V0 edit (raw goldens untouched).

Relocation (the merge moved where search is actually called): _COMPACT_SEARCH_-
DISCIPLINE no longer rides the v1 MAIN heads (the main loop can't call search —
build_main_workflow_note overrides it). It now lives on the v1 DISCOVERY client
prompt (partition.build_discovery_prompt, slayer-only via a new query_mode arg),
the half that actually calls search. Raw discovery prompt stays byte-identical;
v0 snapshots / claude_sdk a·c-interact / shared playbook unchanged.

Full non-integration suite green (3627 passed).

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/bird_interact_agents/agents/claude_sdk/partition.py`:
- Around line 125-137: build_discovery_prompt() currently treats any
non-"slayer" query_mode as raw mode, which can hide caller typos; update this
function to validate query_mode explicitly and fail fast on unknown values,
using the existing build_discovery_prompt symbol and the same mode-checking
pattern already used by build_main_workflow_note(). Keep the current behavior
only for the recognized "slayer" and raw discovery modes, but raise an error for
anything else so invalid selectors cannot silently change prompt behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 93031dcd-5b39-4d97-8093-63edff3c68a4

📥 Commits

Reviewing files that changed from the base of the PR and between 7d45824 and 581b901.

📒 Files selected for processing (9)
  • src/bird_interact_agents/agents/_shared_otf_prompts.py
  • src/bird_interact_agents/agents/claude_sdk/partition.py
  • src/bird_interact_agents/agents/claude_sdk_otf_ainteract_raw_v1/agent.py
  • src/bird_interact_agents/agents/claude_sdk_otf_ainteract_v1/agent.py
  • src/bird_interact_agents/agents/claude_sdk_otf_raw_v1/agent.py
  • src/bird_interact_agents/agents/claude_sdk_otf_v1/agent.py
  • tests/data/dev1603/slayer_ainteract_v0.golden.txt
  • tests/data/dev1603/slayer_one_shot_v0.golden.txt
  • tests/test_shared_otf_prompts.py
✅ Files skipped from review due to trivial changes (1)
  • src/bird_interact_agents/agents/claude_sdk_otf_ainteract_v1/agent.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/test_shared_otf_prompts.py
  • src/bird_interact_agents/agents/_shared_otf_prompts.py

Comment thread src/bird_interact_agents/agents/claude_sdk/partition.py Outdated
DEV-1586 retired --slayer-setup (slayer_setup is now derived from
--pre-encoded-models; omitting it = on-the-fly). The two cloud-smoke command
examples still passed `--slayer-setup on-the-fly`, which now errors with
"unrecognized arguments". Drop the flag (on-the-fly is the default) and point
at --pre-encoded-models for the pre-encoded path.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLAUDE.md`:
- Around line 189-191: The smoke command snippet currently uses backticked note
text inline with the continued invocation, which makes it behave like command
substitution instead of a shell comment. Update the affected command block(s) in
CLAUDE.md so the explanatory notes are plain `# ...` shell comments placed
outside the command continuation, or move them above the command entirely, while
keeping the actual command lines copy/pasteable. Use the existing smoke command
sections and their continued `--mode a-interact` invocation as the anchors when
editing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a2313266-8609-406d-93f8-87b5b0471a59

📥 Commits

Reviewing files that changed from the base of the PR and between 581b901 and ba64912.

📒 Files selected for processing (1)
  • CLAUDE.md

Comment thread CLAUDE.md Outdated
ZmeiGorynych and others added 2 commits June 29, 2026 15:13
- partition.build_discovery_prompt: raise ValueError on an unknown query_mode
  instead of silently treating any non-"slayer" value as raw (mirrors
  build_main_workflow_note in the same file), so a caller typo can't silently
  drop the compact-search discipline. (CodeRabbit)
- CLAUDE.md: the inline `# ...` smoke-command notes were backticked, which
  shells parse as command substitution (not copy-pasteable); move them to
  plain `# ...` lines above the command block. (CodeRabbit)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per-task runs/ records (SubmissionAnnotation) carried no signal of which
agent code version produced them. The cascade buckets only on
(query_mode, agent_model) from the manifest and never reads framework, so
a run from this branch's modified agent code (same claude_sdk token as
clean origin/main) silently overrode clean-v0 baselines per task.

* eval/versioning.py: version taxonomy + resolve_version (run-id override
  table -> framework map -> default-v0 -> framework token for unmapped),
  provenance_from_manifest, stamp_provenance. The override table is the
  only durable v2/v3 signal (manifests have no code-version field).
* SubmissionAnnotation: additive optional version + agent_model fields
  (schema_version unchanged; legacy records parse with both None).
* annotation_io: write-time stamping in write_run_annotation[_no_overwrite]
  (explicit benchmark/run_id from the three runs/ writers, path-inference
  fallback); version filter on latest_run_per_instance.
* regrade / grade_in_place / cloud post_run_merge: pass benchmark/run_id so
  stamping works even under an explicit repo_root.
* cascade_for_combo: record is now the authoritative source for
  agent_model + version (manifest only a fallback for legacy records), so
  a missing/stale manifest no longer drops a stamped record; new --version
  filter excludes wrong-version records before the latest-per-task pick.
* cascading_report.aggregate_cascading_latest: optional version filter.
* scripts/backfill_run_versions.py: idempotent migration (--dry-run,
  --no-gcs) stamping existing records; flags agent_model/manifest mismatch.

Tests cover resolve_version precedence, schema round-trips, write-time
stamping (incl. repo_root + override-without-manifest + no-clobber),
backfill idempotency/override/missing-manifest/dry-run, and the cascade +
report version filters. Full non-integration suite green (3654 passed).

Stream 1 (the compact/inspect prompt rewrite) is parked on DEV-1612 (the
SLayer inspect reference->str|list[str] widening).

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/cascade_for_combo.py`:
- Around line 175-179: Defer manifest loading in cascade_for_combo.py’s
candidate processing so load_manifest() is only called when the record actually
needs fallback data. Update the logic around manifest_cache and the
stamped-record path to first use the local record fields (such as agent_model
and version) and only fetch/cache the manifest when those values are missing or
insufficient. Keep the behavior in the surrounding loop and manifest_cache
lookup intact, but move the load_manifest() call behind the fallback-needed
check.

In `@src/bird_interact_agents/eval/regrade.py`:
- Around line 312-315: The provenance stamping call in regrade_run is missing
the regraded run’s manifest, which can cause out-of-tree regrades to be stamped
with the wrong default version. Update the write_run_annotation invocation to
pass the run manifest from run_dir (or the equivalent manifest object already
available in regrade_run) through to stamp_provenance, alongside the existing
benchmark and run_id arguments. Use the regrade_run and write_run_annotation
symbols to locate the call and ensure provenance is derived from the actual
regraded run rather than only paths.results_root().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1e3a1694-3a24-4627-8016-120f9523bc87

📥 Commits

Reviewing files that changed from the base of the PR and between ba64912 and 6731385.

📒 Files selected for processing (15)
  • CLAUDE.md
  • scripts/backfill_run_versions.py
  • scripts/cascade_for_combo.py
  • src/bird_interact_agents/agents/claude_sdk/partition.py
  • src/bird_interact_agents/cloud/post_run_merge.py
  • src/bird_interact_agents/eval/annotation_io.py
  • src/bird_interact_agents/eval/annotation_schema.py
  • src/bird_interact_agents/eval/cascading_report.py
  • src/bird_interact_agents/eval/grade_in_place.py
  • src/bird_interact_agents/eval/regrade.py
  • src/bird_interact_agents/eval/versioning.py
  • tests/scripts/test_backfill_run_versions.py
  • tests/scripts/test_cascade_for_combo.py
  • tests/test_cascading_report.py
  • tests/test_dev1591_versioning.py
✅ Files skipped from review due to trivial changes (1)
  • CLAUDE.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/bird_interact_agents/agents/claude_sdk/partition.py

Comment thread scripts/cascade_for_combo.py Outdated
Comment thread src/bird_interact_agents/eval/regrade.py Outdated
ZmeiGorynych and others added 6 commits June 29, 2026 19:41
* cascade_for_combo: defer load_manifest() until a record actually lacks
  agent_model. Post-backfill every record self-describes, so the eager
  per-candidate manifest load (a GCS fetch/cache write per run under the
  default allow_gcs=True) was wasted work.
* regrade_run: read the run's manifest from run_dir and pass it into
  write_run_annotation. stamp_provenance would otherwise self-load only from
  paths.results_root()/..., mis-stamping an out-of-tree / legacy-flat regrade
  of a clean claude_sdk_v1 run as default v0.

Full non-integration suite green (3654 passed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
eval.annotate --run-id reads attempts from the legacy-flat run dir
results/cloud/<run_id>/ and called write_run_annotation(ann, dest) bare, so:
* stamp_provenance self-loaded only the benchmark-scoped manifest
  (results/<benchmark>/cloud/<run_id>/), missing the flat one -> a clean
  claude_sdk_v1 run got stamped default-v0 with no agent_model;
* with a custom repo_root, path inference couldn't recover benchmark/run_id
  at all.

Fix: load_local_manifest now falls back to the legacy-flat layout, and
annotate passes benchmark/run_id explicitly (matching regrade/cloud-merge).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The backfill resolved manifests only via cascade.load_manifest (benchmark-
scoped local + GCS), so a clean claude_sdk_v1 run whose manifest lives at the
legacy-flat results/cloud/<run_id>/ (with --no-gcs or no GCS) backfilled as
default v0 with no agent_model. Fall back to versioning.load_local_manifest,
which now checks both local layouts — matching the write-time stamping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously only the three hardcoded override run-ids were tagged v2/v3;
every FUTURE run from this branch would self-stamp clean v0/v1 (Codex High),
so branch-modified results could still pollute clean baselines.

Add _BRANCH_IS_MODIFIED — a code-baked marker (travels into the cloud image,
unlike git state) that this process is the modified branch. The LIVE
write-time stamp now resolves with live_run=True: a clean framework maps to
its modified twin (claude_sdk->v2, claude_sdk_v1->v3) and a missing framework
defaults v2. So any run this branch produces is tagged distinctly from clean
main without a per-run override.

The BACKFILL / historical path keeps the clean resolution (live_run=False):
a historical record's branch is unknown, so it stays v0/v1 unless the override
table says otherwise — else backfill would re-tag genuinely-clean runs from
other branches. Backfill now also only fills a MISSING version, so it never
clobbers a live v2/v3 stamp on a re-run.

Reset _BRANCH_IS_MODIFIED to False when these mods land on main / are retired.
Full suite green (3660 passed).

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

Replaces the reconstruction machinery (the _BRANCH_IS_MODIFIED marker, the
code_modified manifest flag, resolve_version's framework-map + live_run, and the
run-id override table) with: the PRODUCER writes the run's version into the
record at creation; everything downstream only copies/preserves it.

* versioning.py: VERSION_BY_FRAMEWORK = {claude_sdk: v2, claude_sdk_v1: v3}
  (this branch's identity, applied ONLY by producers) + version_for_framework()
  + copy_provenance_from_manifest() (downstream copy of the manifest literal).
  DEFAULT_VERSION survives only as the cascade --version READ-filter default.
* grade_in_place._apply_config_provenance: at the single build point for the
  cloud actor AND local run.py (plus the harness-confirmed/failed paths), stamp
  ann.version/agent_model from the agent config — so the record carries its
  version before it is uploaded or written locally.
* driver.build_manifest: write manifest["version"] from the framework at submit.
* annotation_io / merge / regrade / annotate / backfill: copy the producer's
  literal; no framework→version mapping on the merge/regrade workstation, so a
  clean run processed here stays clean. backfill kept (copies manifest version).

Reset VERSION_BY_FRAMEWORK to {v0,v1} when these mods land on main / are
retired. Full non-integration suite green (3657 passed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* backfill: agent_model is now record-authoritative (fill only when missing),
  matching the version rule — a producer-stamped agent_model is no longer
  overwritten by a stale/mismatching manifest value.
* migrate_submission_annotations_to_runs: route through write_run_annotation so
  a migrated record copies version/agent_model from the run's manifest like
  every other runs/ writer, with a raw-copy fallback when a legacy file fails
  schema validation (never silently drops a record).

Full non-integration suite green (3657 passed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ZmeiGorynych and others added 13 commits June 30, 2026 12:19
Hardwire SLayer `search` to compact mode and route every targeted detail
read to the `inspect` point-lookup, so broad discovery never drags full
per-entity renders into the warm/cached context.

Enforcement lives at the two distinct choke points the agent families use:
- v0 OTF (direct SLayer stdio MCP, `mcp__slayer__search`): a PreToolUse
  hook `_force_compact_search_hook` overrides `compact=True`.
- v1 / native path (`_make_slayer_native("search")`): we own the advertised
  schema, so we DROP the `compact` param entirely (the agent never sees it)
  and pin `compact=True` in the handler as belt-and-suspenders.

Prompts (shared discipline, column/memory drill-ins, host-discovery
playbook, claude_sdk a/c-interact + v1 discovery) now teach search=discovery
/ inspect=detail; detail reads use `inspect(reference=[…], entity_type=…,
compact=False)` with no `cypher_filter` (inspect has no RRF fusion).

`inspect` was only "not disallowed", not executable — `allowed_tools` gates
auto-execute, so a prompted `inspect(...)` would be denied headless. Added
it to the v0 allow-list, the v1 native names + discovery surface, and the
partition bridging clause. pydantic_ai* expose the full toolset already.

Re-baselined the deliberate drift guards (v0/v1 prompt SHA pins + the two
dev1603 slayer goldens). Bumped motley-slayer pin to >=0.9.1 for batch
`inspect` (DEV-1612). New contract test pins the hook, the native wrapper
force + schema strip, and the `inspect` allow-list seats. Full
non-integration suite green (3673).

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

Brings in DEV-1609 (claude_sdk_otf_encode), DEV-1613 (in-task LLM judge),
and cloud stall diagnostics. Only conflict was CLAUDE.md (otf_encode smoke
recipes) — kept both the on-the-fly/--pre-encoded-models note and the
DEV-1602 subscription-auth note. Stream-1 search/inspect changes auto-merged
intact; full non-integration suite green (3797).

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

Main landed its own DEV-1591 stream-2 versioning (PR #68, v0/v1 mapping),
which collided with this branch's earlier stream-2 implementation across the
versioning core + producers + scripts + tests. Resolved by taking main's
better-reviewed version of every conflicted file (it ported this branch's
stream-2 and then hardened it over 4 review rounds: manifest-fallback guard,
migration masking, dry-run cache fix), then flipping the module-level
VERSION_BY_FRAMEWORK back to {claude_sdk:v2, claude_sdk_v1:v3} — THIS checkout
is the modified-agent branch, so its producers must stamp v2/v3, not v0/v1.

Main's versioning tests pin the map via a fixture and assert the mechanism,
so they pass against the v2/v3 module constant. Full non-integration suite
green (3805).

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

Brings in the JSONB-leaf sampling fix (_phase3_jsonb now profiles the leaf
columns it adds) + the slayer 0.9.1 bump. Only conflict was the slayer-floor
test docstring/message (both branches bumped the floor to 0.9.1) — combined
both rationales (DEV-1588 encoder deps + DEV-1612 batch inspect).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…agent-prompts-use-compacttrue-for-broad-search
collect_latest_per_task + runs-records-carry-correctness-not-tokens (gcs row for turns/tokens).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…agent-prompts-use-compacttrue-for-broad-search

# Conflicts:
#	tests/test_shared_otf_prompts.py
Intelligent merge of the claude_sdk recommend_root_model host-selection
work (DEV-1629, PR #74) with this branch's compact-search discipline +
enforcement. Both branches rewrote the same SLayer-agent prompt/tool
surface; resolved semantically (union, not ours/theirs):

* Host selection (claude_sdk): PR 74 wins — the hand-rolled HOST DISCOVERY
  playbook is deleted from the two v0 slayer snapshots and replaced by the
  shared QUERY_ROOT_GUIDANCE / ENCODE_HOST_GUIDANCE blocks (recommend_root_model).
* Compact discipline + enforcement (DEV-1591) preserved: _COMPACT_SEARCH_DISCIPLINE,
  the v0 _force_compact_search_hook, and the v1 _make_slayer_native compact-drop.
* D1 (new): PR 74 moves search/inspect onto the v1 slayer MAIN loop, so
  _COMPACT_SEARCH_DISCIPLINE is now also spliced into the slayer branch of
  build_main_workflow_note (present in slayer main note, absent in raw).
* Column/memory "READ A KNOWN ..." paragraphs unified to terse inspect form,
  each followed by the discipline block (least-redundant).
* Surfaces union both branches' additions (inspect + recommend_root_model),
  deduped. partition._INTROSPECTION_TOOLS_BY_MODE slayer key removed (PR 74);
  build_discovery_prompt query_mode plumbing kept (DEV-1591).
* _COMPACT_SEARCH_DISCIPLINE reworded (two Codex rounds): "discovery" = the
  candidate-finding activity (not the subagent); root/host selection deferred
  to recommend_root_model where the surface offers it (no dangling section ref).
* Pin motley-slayer[advanced-search]>=0.9.3 (PR 74). pydantic_ai
  _host_discovery_playbook.py untouched. eval/versioning.py v2/v3 kept.

Goldens (dev1603 v0) regenerated; v1 SHAs re-baselined (unchanged vs PR 74 —
the discipline rides the runtime workflow note, not the static prompt).
Full non-integration suite: 3918 passed, 94 skipped, 0 failed.

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

Two consistency gaps surfaced by the post-merge Codex review, where DEV-1591's
compact-search enforcement now reaches surfaces that still assumed `search`
could return full bodies:

* _pre_encoded_prompts.py — the deferred-KB fallback (both one-shot and
  a-interact variants) told the agent to `search` for the `[kb=<n>]` memory
  AND read its body. But `_force_compact_search_hook` applies to pre-encoded
  mode too (registered before the `if not self.pre_encoded_source` guard), so
  `search` returns one-line descriptions only. Migrated both to the merge's own
  pattern: `search` to find the memory id, then `inspect(reference=[
  "memory:<id>"], entity_type="memory", compact=False)` to read the full body.

* claude_sdk_otf_encode/setup_encoder.py — the build-time encoder registered
  only the write-normalize PreToolUse hook, so its stdio SLayer `search` could
  still be called with compact=False. Added the shared `_force_compact_search_hook`
  on the `mcp__slayer__search` matcher (parity with the on-the-fly task agents;
  its own prompts already route detail reads through `inspect`). New wiring test
  in test_dev1589_setup_encoder.py.

Full non-integration suite: 3919 passed, 94 skipped, 0 failed.

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

origin/main advanced with PR #73 (sudo-free local postgres benchmark runner +
local/cloud instrumentation parity) and a DEV-1629 follow-up (93d6a8e) that
landed after this branch merged the DEV-1629 branch.

Only conflict: tests/test_shared_otf_prompts.py v1 SHAs. The DEV-1629 follow-up
reworded the v1 slayer tool-inventory line (list `search` = find /
`inspect_model` = whole model / `inspect` = a single known column's Description
+ Sample values) and re-baselined the v1 SHAs. The v1 prompts.py auto-merged to
that reworded version, so took origin/main's SHAs (942ce8e9 / 39eecf2f) —
verified by recomputing post-merge — and dropped the now-stale "UNCHANGED vs
DEV-1629" note, keeping the still-accurate point that the DEV-1591 compact
discipline reaches v1 main via build_main_workflow_note (runtime), not the
static prompt hashed here.

Everything else (PR #73 scripts/tests, _run_capture/run.py parity + atomic
attempt-row write, CLAUDE.md local-postgres section) auto-merged cleanly.
Full non-integration suite: 3940 passed, 94 skipped, 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
origin/main advanced with PR #75 (DEV-1638): the local-benchmark CLI
unification — postgres bootstrap folded into `bird-interact` behind
`--benchmark`, with the provisioning/annotation/env logic moved out of
scripts/ into src/{local_postgres,local_annotations,env_file}.py and
run.py gaining the db_backend dispatch.

Clean auto-merge — DEV-1638 touches the runner/CLI + scripts, DEV-1591
touches the agents/prompts, so the two are disjoint (only CLAUDE.md
auto-merged). Full non-integration suite: 3993 passed, 94 skipped, 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…urrency, PR #77)

origin/main advanced with PR #77 (DEV-1640): the local runner now spawns each
task in its own worker process instead of running all tasks as coroutines on a
single shared asyncio event loop — fixing the shared-loop hang that wedged the
livesqlbench-large v2 slayer run at concurrency 3 (a blocking call in one
slayer task froze the whole loop). This mirrors the cloud Ray-actor isolation.

Clean auto-merge — DEV-1640 touches run.py's concurrency + tests, DEV-1591
touches agents/prompts. Full non-integration suite: 4027 passed, 94 skipped,
0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…agent-prompts-use-compacttrue-for-broad-search

# Conflicts:
#	src/bird_interact_agents/agents/claude_sdk_otf_ainteract/agent.py
#	tests/test_shared_otf_prompts.py
ZmeiGorynych and others added 6 commits July 7, 2026 12:08
…agent-prompts-use-compacttrue-for-broad-search
…-interact examples

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…agent-prompts-use-compacttrue-for-broad-search
Document that the bare `list` does a bucket-wide manifest scan (slow) and
that `list <run-id>` queries only that run. Applied to CLAUDE.md (cloud-ops
notes + polling note) and README.md (run-completion section).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…agent-prompts-use-compacttrue-for-broad-search
Two independent slayer-only flags on the SLayer query agents that shrink the
per-turn tool schema (and matching prompt wording) to cut the ~2x token
overhead of slayer vs raw runs. Not a version token — a run's identity is
(framework, lean_introspection, readonly_mode), recorded per-run.

* lean_introspection (default True): drops read tools redundant with
  search/inspect — inspect_model, the 3 knowledge natives, and list_datasources.
* readonly_mode (default False): drops the SLayer write tools
  (create_model/edit_model/save_memory/validate_models).

Scope: v0 (claude_sdk) + v1 (claude_sdk_v1) query agents and their direct
otf/ainteract variants; claude_sdk_otf_encode, raw, and non-claude_sdk are
exempt (flags ignored + recorded None). False/False == today byte-for-byte
(tool surface + prompts), pinned by tests + the existing SHA-256 snapshots.

Mechanism: a single shared drop-set helper in _slayer_tool_surface filters each
agent's allow-list / native-tool lists; prompt gating is STATIC (authored
lean/readonly block variants, no runtime string surgery). Flags thread through
run.py (new build_arg_parser) + cloud/cli.py submit, the cloud manifest +
_build_job_args/_build_resubmit_args, ray_app run_pool/cfg, and every in-scope
agent constructor.

Follow-ups (tracked in code comments): prompt-text gating of the pre-encoded /
v1-static templates and the embedded query-root disciplines, and the full
readonly encode-workflow-block removal — the tool surface leans regardless.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ZmeiGorynych and others added 4 commits July 10, 2026 14:38
Codex review caught that main() parsed --no-lean / --readonly-mode (and warned
on them) but the run_evaluation(...) call omitted both kwargs, so local
bird-interact runs silently used the defaults and ignored the flags. Pass them
through; add an ast regression test that main()'s run_evaluation call forwards
both.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codex round-2: under readonly_mode=True on an on-the-fly run, the v0 OTF
one-shot / a-interact templates still named `create_model` / `edit_model` (via
`_DEFINE_BEFORE_REFERENCE`) even though readonly drops those tools — so the
prompt instructed unavailable write-tool calls. Add a readonly variant that
tells the agent to project from the prior stage instead, threaded through the
v0 build functions. False/False stays byte-identical (SHA snapshots green);
new test pins the whole readonly v0 template is write-tool-free.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Local sweeps run at patience 500, so make it the local default instead of
250 (the old value borrowed from bird-interact-cloud, which keeps 250). This
is an intentional local-vs-cloud divergence; the alignment test is updated to
assert 500 locally and document why.

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

DEV-1666: slayer-only lean_introspection + readonly_mode flags
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant