Commit graph

23 commits

Author SHA1 Message Date
tobjend
19a1db48ef test: update tests for AST representation
Assertions now use isinstance() on AST nodes (Concat, Alt, Plus,
Optional, Star, Symbol, Empty) instead of comparing SORE strings.
2026-07-13 01:13:48 +02:00
tobjend
ea6cac53e3 wip: AST foundation — grammar.py, expr.py→AST, soa.py→AST labels 2026-07-13 01:13:48 +02:00
tobjend
ee60b62854 fix: YAML expansion bug and add GBNF to output
- Removed all_grammars expansion in _build_yaml_output (226→54 RAGSAK, 384→87 FastAPI)
- Added gbnf field to each YAML entry via to_gbnf()
- Updated test_roundtrip_persisted_ragsak to use correct file path

Closes #66
2026-07-12 19:53:24 +02:00
tobjend
8b2899d16e Phase 2: decomposition forest for complex sequences
Decomposition breaks long sequences into shorter fragments before
inference. This helps when sequences are too long for CRX to handle
(>5 symbols → flat bags).

Results:
- RAGSAK: 21 → 80 grammars (3.8× increase)
- FastAPI: 111 → 118 grammars (small increase)

Changes:
- bex/decompose.py: decompose_sequence(), decompose_all(), decompose_with_coverage()
- bex/tag_preprocessor/analyze.py: --decompose, --max-seq-length flags
- Skip diversity check when decomposing (decomposition creates diverse fragments)
- 12 new tests in tests/test_decompose.py

Co-authored-by: OpenCode <opencode@corentic.eu>
2026-07-12 17:49:35 +02:00
tobjend
841f5efcf5 feat: distributional clustering for better grouping (Phase 1)
Inspired by Crucio's distributional matrix (ICSE 2026).
Groups symbols by context similarity instead of first-symbol.

New module: bex/distributional.py
- extract_contexts(): get (left, right) context pairs
- build_distribution_matrix(): symbol × context counts
- cluster_symbols(): agglomerative clustering by similarity
- split_by_cluster(): split sequences by cluster membership
- distributional_split(): drop-in replacement for _split_by_first_symbol

CLI: --cluster-method distributional (opt-in, first-symbol is default)

Example: 'if' and 'while' both appear before 'return'
→ first-symbol: 3 groups (if, while, return)
→ distributional: 2 groups (if/while merged, return)

23 tests pass. Full suite: 257 tests pass.
2026-07-12 17:37:36 +02:00
tobjend
b92b7653e2 feat: iDRegEx refinement for CRX flat bags (Round 16)
Heuristic: only run iDRegEx when n_methods ≤ 10 AND CRX grammar has
>50% top-level optional parts (flat chain signal). If iDRegEx grammar
is >10x tighter by lang_size, use it. Otherwise keep CRX.

RAGSAK result: agents/capability (5 methods) refined from
slot?.(defaultCapabilityId+summarize)?... (lang_size=1432) to
(defaultCapabilityId|summarize) (lang_size=3) — 477x tighter.

Speed cost: ~0.7s per candidate, negligible on 74s pipeline.
CLI: --idregex-refine flag (default off).

Also adds _count_optionals() and _should_try_idregex() helpers
with 8 pytest tests. 234 tests pass.
2026-07-12 16:54:40 +02:00
tobjend
7b54a5ef77 feat: grammar index for runtime lookup
Add GrammarIndex class that loads grammars.yml and provides fast
lookup by (package, context_symbol). Enables agents to get the right
GBNF grammar at code generation time.

API:
  load_grammar_index(project_root) → GrammarIndex
  idx.get(file_path, context_symbol=None) → gbnf_string
  idx.get_package(file_path) → [(symbol, grammar, score, methods)]

14 tests, all passing.
2026-07-12 14:08:05 +02:00
tobjend
f57c302c91 fix(gbnf): handle disjunction inside parens and compound repetition
The GBNF parser now correctly handles SORE's overloaded + operator:
- + inside (a+b+c) → alternation (not repetition)
- + outside parens → repetition
- +? and +* compound operators → normalized to Star

Also adds implicit concatenation when LPAREN follows a repetition,
so a+(b+c) parses as a+ followed by (b|c).

28 tests pass (13 new disjunction/compound tests). Full suite: 212 passed.
2026-07-12 02:20:58 +02:00
tobjend
739000e8c6 feat: CRX refined — cluster-then-infer for tighter grammars
Standard CRX over-approximates when Hasse diagram is non-linear (24% of
RAGSAK packages). Cluster-then-infer groups sequences by (first, last,
length), infers per-cluster, picks largest cluster's grammar.

Results on RAGSAK:
  Avg max disjunction: 2.8 → 1.7 (39% tighter)
  Packages improved: 6/10

Tradeoff: cluster granularity (too coarse = over-approximation,
too fine = no generalization). Current: (first, last, length_bucket).

Exports crx_refined() and crx_with_confidence() from bex package.
20 new tests. All 199 tests pass.
2026-07-12 01:50:40 +02:00
tobjend
011df391c2 feat: implement SORE → GBNF converter
- Recursive descent parser for SORE syntax (+, ?, *, |, ., parens)
- AST intermediate representation (_Literal, _Concat, _Alt, _Plus, _Optional, _Star)
- to_gbnf(sore) → full GBNF rule string
- to_gbnf_with_rules(sore, name) → named rule for composition
- 15 tests covering all SORE operators and nesting patterns
2026-07-12 00:31:47 +02:00
tobjend
b516b2985d feat: implement Reduce algorithm (Algorithm 4, TODS 2010)
- bex/reduce.py: Faithful implementation of Reduce with support-weighted
  SOA edit distance, adjunction, iterative merging, and Minimize
- experiments/context_eval.py: Multi-codebase support (RAGSAK + Flask),
  Reduce experiments with thresholds 0.05-0.4
- tests/test_reduce.py: 24 tests covering all Reduce components
- Flask cloned to external_refs/flask for cross-validation

Results:
- RAGSAK: 12.0% coverage (First 3 symbols)
- Flask: 10.7% coverage (First 3 symbols)
- Reduce has minimal impact (1-2 merges per codebase at ε=0.3)
- Coverage ceiling appears to be ~10-12% for prefix-based grouping
2026-07-12 00:11:38 +02:00
tobjend
dfb56a083a WIP: language size scoring + diversity threshold (step 1 pending) 2026-07-11 22:56:42 +02:00
tobjend
710da56916 drop kORE from default ensemble, add --kore flag to opt in
- Remove kORE from top-level imports, _ALGORITHMS, and infer_ensemble body
- Add include_kore=False parameter, runs kORE only when opted in
- Add --kore CLI flag threaded through all pipeline layers
- Remove koreinference from --prefer choices
- Keep kore.py module in repo for reference/future use
- Update tests: remove test_prefer_koreinference, update algorithm assertions
2026-07-04 02:58:07 +02:00
tobjend
e3ad256321 feat: add --slice package (per-directory grouping), --include/--exclude, --verbose, drop root group inference, run full ensemble on all groups 2026-07-04 02:43:03 +02:00
tobjend
fd574da53d feat: language-agnostic import/arg/package extraction
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- Add _classify_arg_node, _find_arglist_node, _iterate_arg_nodes,
  extract_arg_info, _summarize_arg_info (no per-language branches)
- _find_arglist_node: drop call_suffix from fallback list
- _iterate_arg_nodes: generic named-child iterator only
- Add IMPORT_PATTERNS + _extract_imports (regex-based, all languages)
- Add _file_to_package / _top_packages (pure relpath from project root)
- Add --json output format for prompt injection
- analyze_clusters returns 4-tuple with meta (files, imports, arg_patterns, packages)
2026-07-03 22:41:04 +02:00
tobjend
73b94af959 feat: cluster methods by n-gram patterns before inference
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- _extract_call_tokens filters to call-like captures only
- cluster_methods groups sequences by shared 3-gram call patterns
- analyze_clusters runs per-cluster CRX/iDRegEx/kORE inference
- Lists 17 convention clusters for RAGSAK test code
- iDRegEx and kOREInference now produce ordered grammars per cluster
- (other) cluster captures diverse conventions as CRX vocabulary
- min-cluster-size (default 3) and ngram-size (default 3) CLI flags
2026-07-03 21:41:46 +02:00
tobjend
2620b6e49f feat: method-level sequence extraction via child_by_field_name('body')
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- _find_method_bodies uses tree-sitter's universal body field (9/10 grammars)
- Kotlin fallback: scan children for body-like types
- preprocess_by_method groups highlight captures by enclosing method body
- Returns per-method sequences for k-ORE ordering analysis
- analyze.py infer() now uses preprocess_by_method
- Document findings in ANALYSIS.md
- 97 tests pass
2026-07-03 21:34:25 +02:00
tobjend
0c7703f63b feat: universal tag-preprocessor orchestrator with frequency filter
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- Rename bex/tag-preprocessor/ to bex/tag_preprocessor/ (valid Python package)
- Add analyze.py: scan_directory, frequency_filter, infer, analyze_directory
- Frequency filter removes symbols below min_coverage threshold (Phase 1.0 step 4)
- infer() wires preprocess → frequency_filter → ensemble (Phase 1.0 step 5)
- --dir CLI mode for running full pipeline on directories (Phase 1.0 step 6)
- 9 new tests (test_analyze.py), all 94 tests pass
2026-07-03 20:58:18 +02:00
tobjend
9045769d57 feat: core+outlier analysis via min_coverage parameter, 6 new tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
2026-07-01 15:09:10 +02:00
tobjend
edd6d9d4dd feat: implement kOREInference (Algorithm 4) with MDL scoring, add to ensemble, 79 tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
2026-07-01 14:50:09 +02:00
tobjend
6b60e0131f clean up agent-betraying comments; fix stale test names
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-07-01 13:26:03 +02:00
tobjend
6bf7a681ce purge make_charts.py, examples/, full-text papers, blog_post (moved to ~/Desktop/kesai/); translate German CLI to English 2026-07-01 11:28:42 +02:00
tobjend
7c00c6713d Initial commit: BEX-based grammar inference engine
- CRX: direct CHARE inference (Algorithm 7, TODS 2010)
- iDRegEx: k-ORE inference (Algorithm 4, arXiv 2010)
- RWR₀: SORE repair (Algorithm 6, TODS 2010)
- rwr²: k-ORE extraction (Algorithm 3, arXiv 2010)
- SOA, k-OA, iKoa, 2T-INF, Baum-Welch
- Ansible role grammar adapter
- Generic YAML key-path converter
- 28 tests, all passing
2026-07-01 08:01:16 +02:00