Skip to content

NPUCodeSearchAgent cannot declare its write scopes: its file is at the size ceiling #16173

Description

@mrveiss

Problem

NPUCodeSearchAgent writes — index_codebase rebuilds a Redis-backed code
index — and under #15950 every write-capable agent must declare the scopes its
run will touch, so a second agent indexing the same tree is refused rather than
racing it.

It cannot. autobot-backend/agents/npu_code_search_agent.py is 1455 lines and
its recorded ceiling is 1455
. A declared_scopes override needs roughly ten
lines, and the file-size ratchet refuses all of them:

npu_code_search_agent.py: 1479 lines, over its recorded ceiling of 1455.
A grandfathered file may not grow (#14236) — the exemption freezes the size it
was granted for, it does not license more.

The ratchet is right. This issue is the extraction that makes room.

What the declaration should be, once there is room

Written out here because it was designed and verified before being reverted, and
the reasoning should not have to be rediscovered:

def declared_scopes(self, request: AgentRequest) -> List[str]:
    if request.action != "index_directory":
        return []
    directory = (request.payload or {}).get("directory")
    if not directory:
        return []
    digest = hashlib.md5(str(directory).encode(), usedforsecurity=False).hexdigest()[:16]
    return [f"project:code-index-{digest}"]

Two properties that matter and are easy to lose:

Only index_directory declares. search_code and get_capabilities are
reads; a read taking an exclusive claim would serialise every search behind one
indexer.

The scope is a hash of the directory, never the directory. A raw path would
put an internal filesystem location into the claim table and into the
work_claim_acquired events #15949 publishes, which reach an operator's browser
— against the "nothing internal in outward artifacts" rule. The hash still
collides for two runs indexing the same tree, which is the only collision that
matters, and the agent already keys its own Redis index by
md5(root_path) in _get_index_key, so the two agree by construction rather
than by coincidence.

Extraction candidates

Not yet chosen — the file needs reading before a cohesive unit is picked, and
picking an arbitrary N lines to get under a number is the failure mode
RATCHET_BASELINES.md warns about. _get_language_patterns (a large static
table of per-language regexes) looks like the same shape as the
blue_green.py → purge_playbook.py and base_agent.py →
base_agent_types.py extractions, but that is an impression from a grep, not a
verdict from reading it.

Acceptance criteria

  • A cohesive, self-contained unit is extracted from
    npu_code_search_agent.py, leaving the file under its ceiling with
    headroom — not at it
  • The extraction is behaviour-preserving: its review question is only "is
    this the same code in a different file"
  • The ceiling record is lowered (or removed, if the file drops under the
    600-line limit) in both scripts/python_file_size_known_large.py and
    repo_tests/python_file_size_ratchet_baseline.py
  • NPUCodeSearchAgent.declared_scopes is implemented as above, with a test
    asserting index_directory declares and search_code declares nothing
  • A test asserts the declared scope contains no path separator and no
    substring of the input directory
    — the leak this design avoids is the
    one a later "make the claim table readable" change would reintroduce
  • The _CEILING_BLOCKED entry in
    autobot-backend/tests/agents/test_declared_scopes_guard.py is deleted;
    that guard already fails if the entry outlives its reason

Notes

Blocking nothing today — the agent's writes are unclaimed exactly as they were
before #15950, so this is a gap in coverage, not a regression. It is recorded in
the guard as a named exemption rather than left silent.

Activity

  1. added this to the Backlog milestone on Sep 12, 2026
  2. mrveiss commented on Sep 13, 2026

    @mrveiss
    OwnerAuthor

    Closure evidence (batch 2c)

    Verified against origin/main (PR #16496, f595a89). All 6 ACs met; boxes ticked.

    AC Evidence
    A cohesive unit is extracted New autobot-backend/agents/npu_code_search_patterns.py (LANGUAGE_PATTERNS, detect_language, extract_elements_by_pattern, extract_code_elements, extract_element_code); the agent went from 1455 to 1346 lines
    Behaviour-preserving 110 of the 132 non-blank removed lines reappear verbatim; the other 22 are self.→parameter renames, language_map→_LANGUAGE_BY_EXTENSION (entries verbatim), one reflowed regex, and docstrings
    Ceiling lowered in both records scripts/python_file_size_known_large.py:41 and repo_tests/python_file_size_ratchet_baseline.py:46 both hold "...npu_code_search_agent.py": 1346, # #16173
    declared_scopes implemented, with a test npu_code_search_agent.py:297 (index_directory only, project:code-index-{digest}); tests test_index_directory_declares_a_scope, test_search_code_declares_nothing
    Scope has no path separator and no substring of the directory test_declared_scope_leaks_neither_a_path_separator_nor_the_directory asserts no /, no \\, and neither the directory nor its name
    _CEILING_BLOCKED entry removed autobot-backend/tests/agents/test_declared_scopes_guard.py:108 _CEILING_BLOCKED: dict[str, str] = {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions