Commit graph

34 commits

Author SHA1 Message Date
tobjend
8fc459e06b docs: add hype document for grammar inference breakthrough
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
2026-07-13 02:33:29 +02:00
tobjend
becbd82c56 feat: add post-hoc noise filtering for grammars
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
- Add filter_noise() to remove test/stdlib tokens from AST
- Add grammar_noise_ratio() to calculate noise fraction
- Integrate into _build_json_output() and _build_yaml_output()
- Precision improvement: 28-55% → 84-94% across all 3 codebases
- Grammar count unchanged (233) — filtering is post-hoc, preserves recall
2026-07-13 02:23:37 +02:00
tobjend
36f9e9173d docs: update experiment log, results, and handover for Round 19-20
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
2026-07-13 01:18:32 +02:00
tobjend
8b3a454a15 feat: enable idregex_refine by default + AST rewrite of _count_optionals
- idregex_refine=True default across all entry points + CLI
- Added --no-idregex-refine flag to CLI
- Rewrote _count_optionals from SORE string parser to AST walker
- Added _is_pure_bag() helper for bag detection
- Updated _should_try_idregex() to trigger on pure Plus(Alt) bags
- Updated tests for AST-based _count_optionals
- Added RAGSAK v4 experiment results
2026-07-13 01:13:49 +02:00
tobjend
8460c3c862 experiments: round 20 v3 results (decompose default + cap fix)
v3 runs for RAGSAK/fastapi/zod with decompose default-on and _COUNT_CAP
raised. Updated SUMMARY.md with before/after quality table.
2026-07-13 01:13:48 +02:00
tobjend
1810a695d0 experiments: round 20 AST-migration verification across 3 languages
Run RAGSAK (Kotlin), fastapi (Python), zod (TypeScript) with --slice
package --min-structure 0.5, verbose+timeout, results saved for later.

After _count_concat memoization fix: RAGSAK full run 54.9s -> 6.7s,
no tail stalls. RAGSAK: 121 packages (28 with grammar). fastapi/zod
complete in ~25s (dominated by arg-extraction on 2000+ method test
groups, not grammar explosion). Includes SUMMARY.md with before/after.
2026-07-13 01:13:48 +02:00
tobjend
f8dda557d2 chore: update experiment scripts for AST representation 2026-07-13 01:13:48 +02:00
tobjend
9d206f586f docs: Round 19 evaluation plan + golden config
- Plan: match rate audit, decomposition A/B, distributional A/B, fragment quality
- Golden config: best-known values for all heuristic parameters
- Single source of truth in bex/golden_config.py
2026-07-12 20:18:33 +02:00
tobjend
44dd34a46f docs: handover document for project continuity 2026-07-12 19:54:10 +02:00
tobjend
9ca56e2c69 MCP server: add decomposition + quality filtering params
- analyze_directory tool: add decompose, max_seq_length, cluster_method,
  crx_method params for Crucio-inspired improvements
- min_structure default bumped to 0.5 for MCP (only high-structure
  grammars returned to agents)
- _build_yaml_output: filter entries below min_structure threshold
- README: update source code analysis section, fix kORE/iDRegEx mentions
- 269 tests pass

Co-authored-by: OpenCode <opencode@corentic.eu>
2026-07-12 18:56:35 +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
2da3a7161f docs: achievement summary and experiment outputs (Round 14-15)
- ACHIEVEMENT_SUMMARY.md: what we built and learned
- Round 14: Full pipeline run on 4 codebases (clean symbols)
- Round 15: kORE/iDRegEx vs CRX comparison

Next: Crucio-inspired clustering for better grouping
2026-07-12 17:25:15 +02:00
tobjend
242f00a0da docs: research positioning and decision matrix
- RESEARCH_POSITIONING.md: where we fit in the science
- DECISION_MATRIX.md: when to use CRX vs refined CRX
- Updated AGENTS.md with research context and updated CLI flags
2026-07-12 17:14:56 +02:00
tobjend
b2c1263838 docs: ASCII diagrams for pipeline, parameters, and decision matrix 2026-07-12 17:09:40 +02:00
tobjend
1d94c09344 experiment: CRX vs refined CRX across 3 codebases (Round 17)
Refined wins 7/9 when producing useful grammars (model_cost >= 2).
Trivial output (single symbol) in 5/13 cases on large groups.
CRX wins only once (FastAPI tests, 3618 methods).

Key finding: refined CRX is better ~78% of the time but needs
triviality check (model_cost >= 2) to avoid single-symbol grammars.
2026-07-12 17:08:15 +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
e9f672cba4 experiment: kORE/iDRegEx vs CRX on flat bags (Round 15)
Key finding: iDRegEx/kORE return None on genuinely diverse groups (flat bags).
CRX is the only algorithm that produces anything for these groups.
For structured groups, CRX already captures ordering well.

Conclusion: kORE/iDRegEx are not better fallbacks for flat bags.
The pipeline's existing filtering (min_structure, split_mixed) is the right approach.
2026-07-12 16:20:01 +02:00
tobjend
93d53f164a fix: byte/char offset mismatch in tree-sitter text extraction
Root cause: parser.parse(code.encode()) returns byte offsets, but
code[node.start_byte:node.end_byte] indexed into a Python string
(character offsets). Non-ASCII chars caused cumulative drift → truncated symbols.

Fix: store code_bytes = code.encode(), index into that, decode only final text.

Impact:
- Zod: 653 truncated symbols → 0
- RAGSAK: 653 truncated symbols → 0
- RAGSAK grammars: 8 → 27 (3.4×)
- FastAPI grammars: 33 → 111 (3.4×)
- Malformed: 6 → 2 (RAGSAK), 0 (FastAPI/Flask)

Also removed sanitize_symbol() (dead code after fix) and call_only parameter.
2026-07-12 15:57:27 +02:00
tobjend
fe3261b9de docs: add Round 13 to experiment log (recursive split results) 2026-07-12 13:54:03 +02:00
tobjend
483526cb6a docs: Round 12 results — grammar structure scoring 2026-07-12 03:03:16 +02:00
tobjend
e62fffc6e0 feat: grammar_structure_score + min_structure filter
Quantifies how structured a SORE is (0.0=flat bag, 1.0=fully structured).
Flat bags are CRX over-approximations — they list symbols without ordering.

With min_structure=0.2:
  Flask:   2 kept (was 5),  9 dropped
  RAGSAK: 10 kept (was 19), 114 dropped
  FastAPI: 47 kept (was 106), 95 dropped
  Total: 59 useful grammars, 218 noise removed

CLI: --min-structure 0.2 (default: 0, keep all)
2026-07-12 03:02:50 +02:00
tobjend
92af932e9d docs: Round 11 results — pipeline speed + GBNF conversion
- iDRegEx opt-in: Flask 55s→2.8s, RAGSAK 74s→13s, FastAPI 30s→30s
- GBNF validation: 130/130 OK, 0 FAIL (17 malformed skipped)
- Grammar quality: 43% structured, rest flat/trivial
- Logged to experiments/EXPERIMENT_LOG.md
2026-07-12 02:57:40 +02:00
tobjend
3468813ec8 fix: validate SORE before returning, skip malformed grammars
- Add validate_sore() to gbnf.py — checks parseability without converting
- _infer_group now validates grammar and returns skip_reason='malformed_grammar'
  for SOREs containing raw code (e.g. w_body=, sult=, (+,+:N+...)
- Results: 130 grammars, 130 GBNF OK, 0 GBNF FAIL
  - Flask: 5 OK, 0 FAIL, 3.4s
  - RAGSAK: 19 OK, 0 FAIL, 11 malformed, 12.9s
  - FastAPI: 106 OK, 0 FAIL, 6 malformed, 30.5s
2026-07-12 02:56:13 +02:00
tobjend
bc7d3b6ca1 perf: iDRegEx opt-in, GBNF newline fix, OverflowError fix
- iDRegEx now opt-in via --idregex flag (was running on every group,
  causing 55s+ on Flask alone — src/flask/json took 55s in iDRegEx)
- GBNF tokenizer strips newlines from literals (multi-line symbols)
- Fix OverflowError: lang_size_score produces huge ints for large
  disjunctions, format as string not float
- Flask: 2.7s (was 55s+), RAGSAK: 13s (was 74s)
2026-07-12 02:52:05 +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
8028570ceb feat: frequency threshold sweep — 0.01-0.20 across 4 codebases
Sweet spot: 0.01-0.05. At 0.01 RAGSAK gets 61 SOREs (26.1% cov) with
real conventions like warn.status.body.ErrorResponse. At 0.05 coverage
jumps to 45.4% but that pattern disappears. Flask dies at 0.15+.

Current default min_coverage=0.2 is too aggressive for most codebases.
2026-07-12 01:26:45 +02:00
tobjend
dd183f6241 feat: 4-codebase evaluation — conventions vs completions tradeoff
Added kotlinx.coroutines (1040 .kt files) and FastAPI (1129 .py files).

Key findings across 4 codebases:
- Coarsening trades per-package coverage for cross-package reach
- FastAPI: coverage IMPROVES (12.4% -> 20.7%), cross-pkg +15
- Coroutines: cross-pkg +15, real exception-handling patterns
- RAGSAK: cross-pkg +18, null-check conventions across 8 packages
- Flask: slight cross-pkg loss, rendering conventions still visible

The conventions vs completions tradeoff is real and measurable.
2026-07-12 01:14:09 +02:00
tobjend
8540947eec docs: Round 6b results — Kotlin capture fix + minimal coarsening 2026-07-12 01:05:19 +02:00
tobjend
d65b78bdf1 fix: bare Kotlin captures + minimal coarsening (RETURN/IF/EXCEPTION/LOOP only)
- Added bare Kotlin captures to BEHAVIORAL_PREFIXES: conditional, exception, repeat, property, type
- Dropped variable (too noisy), kept only 4 high-signal categories in coarsen_token
- RAGSAK: 87 cross-package contexts (up from 69), real null-check patterns
- Flask: k=2 coverage 4.5% -> 15.8%, cross-package rendering conventions
2026-07-12 01:04:51 +02:00
tobjend
592974f039 feat: structural coarsening experiment — keeps function names raw, coarsens keywords
- coarsen_token() maps tree-sitter captures to categories (RETURN, IF, LOOP, etc.)
- Function calls kept as raw text (they ARE the behavioral content)
- Only ~5% structural tokens coarsened
- Results: Flask coverage 17.5% -> 28.8% (+11.3%), RAGSAK unchanged (95% calls)
- Cross-package shapes emerge: ('IF', 'KW', 'RETURN') in 4 Flask packages
2026-07-12 00:56:09 +02:00
tobjend
8e1c7f3767 docs: experiment log + cross-package analysis
- Full experiment history: context strategies, Reduce, scoring, GBNF, cross-package
- Documented failures: per-package sparsity, Reduce at wrong level, exact match rarity
- Designed next experiment: structural coarsening via tree-sitter categories
- Updated RESULTS.md with Round 5 findings and summary table
2026-07-12 00:45:21 +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
bbdfe93679 experiments: test all context strategies on RAGSAK — behavioral grouping wins
Key findings:
- File path grouping (structural) = baseline (0.6% coverage) — no improvement
- First-k-symbols grouping (behavioral) = 20× improvement (12% coverage at k=3)
- Two-dimensional (path + symbols) = worse than behavioral alone
- Winner: Option B k=3 — 47 SOREs, 12% coverage

Smart filters make experiments fast (<1s vs minutes):
- max_unique_ratio=0.85
- max_alphabet=20
- max_soa_edges=100

Preserved in experiments/results/ for future reference.
2026-07-11 23:40:21 +02:00