Skip to content

feat(extract): deterministic business-process path extractor + Tier-1 processes gate - #27

Merged
v0ropaev merged 1 commit into
masterfrom
feat/process-paths
Jul 7, 2026
Merged

v0ropaev merged 1 commit into
masterfrom
feat/process-paths

Conversation

@v0ropaev

@v0ropaev v0ropaev commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What

Step 2 toward the crown jewel (DESIGN §14 item 2): deterministic named real paths — extracted entrypoint (api_route/event_handler handler) → shortest chain of resolved call_edges → terminal function containing a sink (registry match). The LLM labeler is the next slice; the path itself needs no model.

Architecture

  • First second-order extractor: ExtractContext.prior_artifacts + pipeline threading (dataclasses.replace per extractor; registration order is load-bearing — ProcessPathExtractor runs last). Existing gates unaffected (they pass their own extractor lists).
  • .kb/ materialization: the materialized tree previously contained only *.py; a new iter_files_under_at + extra_files channel ships the analyzed repo's .kb/sinks.yaml into the snapshot without touching root discovery/parsing/diff-reuse.
  • PathEngine (first shipped increment of the §11 seam): BFS, visited-on-enqueue (cycle-safe, shortest, deterministic tie-breaks), terminate-at-first-sink, 0-hop supported, depth/path caps retro-flagged in limitations (no silent caps).
  • Sink registry: built-in defaults (collision-averse names only) ⊕ per-repo .kb/sinks.yaml override (strictly validated, loud ValueError on malformed input). The effective registry's digest is identity-bearing (framework_versions) — a registry edit can never silently serve a stale payload (identity-v2 discipline).
  • Confidence 1.0, honestly argued (DESIGN §9 note added): a found path is machine-checked exact; the bounded-recall unknown-unknowns are priced into the future labeled artifact, with incompleteness as explicit payload facts here.
  • Sink scan reuses calls.py's attribution machinery (_caller_scan_root lifted to module level) — edges and sinks agree bit-identically about which function contains a call.

Gate #14 (tier1_processes_test, 8 tests)

Hand-labeled oracle: 2-hop cross-file chain to an override-only sink; 0-hop built-in sink; event-handler entrypoint; reachable cycle no-hang; no-sink route yields nothing; ONE artifact grounded across THREE files (the thesis apex); .kb/sinks.yaml override proven end-to-end (git blob → materialization → merge); re-index determinism; depth caps. Headline HARD gates: thirteen → fourteen.

Checks

  • ruff + mypy --strict clean (77 files); 102 passed, 1 skipped (94 + 8 new)
  • pyyaml → runtime deps (uv lock refreshed); kb index stays static/offline.

Next slice: LLM labeling of paths via kb describe (target_kind="process", same validate_claims floor) + the span-binding validator.

… processes gate

Step 2 toward the grounded business-process extractor (DESIGN §14 item
2): materialize NAMED REAL PATHS deterministically — an extracted
entrypoint (api_route / event_handler handler) -> a shortest chain of
resolved first-party call edges -> a terminal function containing a SINK
call. The LLM labeler is the next slice; the path itself needs no model.

This is the first SECOND-ORDER extractor: ExtractContext gains
`prior_artifacts` (the pipeline threads each extractor's outputs to
later ones via dataclasses.replace; registration order is load-bearing
— ProcessPathExtractor runs last in default_extractors()). The pipeline
also materializes the analyzed repo's `.kb/` directory (new
git.repo.iter_files_under_at + an extra_files channel kept OUT of the
Python file map, so root discovery / parsing / diff reuse never see
non-Python paths).

PathEngine (the first shipped increment of the DESIGN §11 seam)
BFS-slices the call_edge graph: visited-on-enqueue (cycle-safe, O(V+E),
shortest path, deterministic tie-breaks via sorted adjacency), paths
terminate at the first sink-bearing node, 0-hop supported (a handler
with a direct sink grounds a single-span artifact, the direct-recursion
precedent), depth/path caps retro-flag `limitations` — never silent.
Sinks are typically third-party calls that the precision-first
call_edge extractor skips, so sink detection is a separate textual scan
against a registry, reusing calls.py's exact attribution machinery
(_caller_scan_root lifted to module level) so edges and sinks always
agree. Registry = built-in defaults (collision-averse) merged with an
optional `.kb/sinks.yaml` override (strictly validated, loud on
malformed input); the effective registry's digest is folded into
framework_versions so a registry edit can never serve a stale payload
(the identity-v2 discipline). Found paths are exact (confidence 1.0);
incompleteness is an explicit payload fact, priced into the future
labeled artifact.

One `process_path` per (entrypoint, sink, terminal), grounded on EVERY
span along the path (roles entrypoint/step/terminal — multi-file
provenance, the thesis apex: the gate proves ONE artifact spanning
THREE files). pyyaml moves to runtime deps; summarize/embed_text gain
process_path branches.

New Tier-1 HARD gate tier1_processes_test (hand-labeled oracle): 2-hop
cross-file chain via the override-only sink, 0-hop built-in sink,
event-handler entrypoint, reachable cycle no-hang, no-sink route yields
nothing, override chain proven end-to-end, re-index determinism, depth
caps. Headline HARD gates: thirteen -> fourteen. 102 eval tests pass.
@v0ropaev
v0ropaev merged commit b903ddc into master Jul 7, 2026
4 checks passed
@v0ropaev
v0ropaev deleted the feat/process-paths branch July 7, 2026 13:06
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