Repository navigation
feat(parser): index generic YAML structure - #816
2 commits merged into
Conversation
Partially addresses tirth8205#436 with value-free, bounded YAML path indexing.
|
Solid implementation and genuinely good coverage. Two things before I take it.
Minor, fine to leave: anchors under unsupported complex keys mislabel the first alias site as anchor_definition and shift later REFERENCES line attribution. Sanitization, ansible/spring precedence, and the dangling-edge guarantees all held up under adversarial testing. No DB migration needed since kind is unconstrained TEXT. |
|
Thanks, I fixed both items and merged the latest main in 76e8352. Generic YAML now stops at a 1 MiB byte limit before decoding or calling PyYAML. pnpm-lock.yaml is also ignored by default. Files without an ampersand skip the second event parse, while the existing anchor tests still cover the event path. Verification:
|
|
Outside this sweep's mission of demonstrated coding-session token savings without context loss: generic YAML indexing adds a new node contract and changes parsing, diagnostics and visualisation across 20 files. The improved bounds are useful, but a representative coding-task comparison is still needed to justify that new surface in this work. |
|
This no longer merges into git fetch origin && git merge origin/staging
# resolve, then
uv run pytest tests/ -q
uv run ruff check code_review_graph/
uv run mypy code_review_graph/ --ignore-missing-imports --no-strict-optional
git pushWhen resolving:
A large integration branch landed on PRs now target |
|
This no longer merges into
Worth knowing before you resolve:
git fetch origin
git merge origin/staging
# resolve, then
uv run pytest tests/ -q
uv run ruff check code_review_graph/
uv run mypy code_review_graph/ --ignore-missing-imports --no-strict-optional
git pushI have not reviewed the change itself yet. That comes once it merges and the checks run against the merged state, since staging has moved a long way and the result is what matters. |
|
Thank you for this PR. Your generic YAML work is very useful. This change is already in #1092. That PR has both of your commits on top of the latest staging. Your name stays on those commits, so the credit is yours. I ran the YAML tests on both branches. I also parsed the same YAML files on both. The results were the same. #1092 merges cleanly. This branch now has conflicts with staging. So I will not merge this one. I will use #1092 instead. #1092 needs two small fixes first. I asked for them there. You do not need to do anything more here. Thank you again for your help. |
There was a problem hiding this comment.
🟡 Changes recommended
Shared-alias traversal can grow exponentially and stall graph builds despite emission limits, while additional defects affect alias source tracking, key semantics, and YAML search metadata.
6 open issues
Track shared alias targets to prevent exponential traversal · New Include YAML metadata in semantic search results · New Advance alias-line accounting when skipping long keys · New Canonicalize scalar keys before duplicate detection · New Detect merge keys by YAML tag, not key text · New Use source marks for aliased mapping keys · New
What changed in this PR
Adds value-free generic YAML indexing to the code graph, partially addressing #436 while leaving JSON support out of scope.
Changes:
- Introduces aggregated
YamlPathnodes, duplicate-key diagnostics, and alias references while preserving Ansible and Spring precedence. - Adds YAML-aware change analysis, serialization, CLI filtering, and visualization.
- Expands regression coverage and documents YAML indexing behavior.
| File | Description |
|---|---|
| tests/test_yaml_parser.py | Tests structural indexing, bounds, aliases, persistence, and queries. |
| tests/test_visualization.py | Checks YAML node and reference-edge visuals. |
| tests/test_spring_config.py | Verifies generic YAML fallback outside Spring configuration. |
| tests/test_incremental.py | Checks the pnpm lockfile ignore pattern. |
| tests/test_changes.py | Tests YAML occurrence-range change mapping. |
| tests/test_ansible_parser.py | Verifies generic fallback for non-Ansible YAML. |
| README.md | Adds YAML indexing to the feature overview. |
| docs/USAGE.md | Documents YAML support and node kinds. |
| docs/schema.md | Defines YAML metadata and graph identities. |
| docs/FEATURES.md | Updates parser and change-analysis capabilities. |
| docs/COMMANDS.md | Documents YAML filters and change output. |
| code_review_graph/visualization.py | Adds YAML styling and reference-edge controls. |
| code_review_graph/tools/review.py | Exposes YAML change results and minimal-output counts. |
| code_review_graph/parser.py | Implements generic YAML extraction and specialized fallbacks. |
| code_review_graph/main.py | Updates tool docstrings for YAML support. |
| code_review_graph/incremental.py | Excludes pnpm lockfiles by default. |
| code_review_graph/graph.py | Adds sanitized nested YAML metadata serialization. |
| code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md | Updates the bundled language-support reference. |
| code_review_graph/cli.py | Allows filtering searches by YamlPath. |
| code_review_graph/changes.py | Maps changed YAML ranges and returns bounded path results. |
Review effort: Balanced
| elif isinstance(skipped_node, _YamlSequence): | ||
| for child in skipped_node.value: | ||
| consume_skipped_aliases(child, skipped_ancestors) |
| if n.kind == "YamlPath": | ||
| yaml_metadata: dict[str, Any] = {} |
| if not can_emit(schema_path, depth, exact_path, identity_path): | ||
| return |
| signature = (str(getattr(key_node, "tag", "")), raw_key) | ||
| key_counts[signature] = key_counts.get(signature, 0) + 1 |
| "path": bounded_exact_path, | ||
| **duplicate_group, | ||
| }) | ||
| is_merge = raw_key == "<<" |
| parent_qualified, | ||
| document_index, | ||
| depth, | ||
| _yaml_line(key_node), |
0160eb0


Partially addresses #436. JSON support remains out of scope for this PR.
What changed
Generic
.yml/.yamlfiles now produce value-free, path-addressable graphstructure:
YamlPathnodes for mappings and repeated sequence shapesCONTAINSedges andREFERENCESedges for aliases/merge keyschanged_yaml_pathsin change/review outputScalar values are deliberately discarded. The graph stores structural key paths
and YAML types, not configuration values. Query, search, and change-analysis
responses share the same nested
yamlmetadata contract.Safety and compatibility
This incorporates the earlier YAML review feedback from #539, #577, and #462:
regression coverage
length, and diagnostic samples
[*]pathsHow this differs from earlier attempts
[*]schema paths with bounded occurrence samplesVerification
Verification uses only synthetic fixtures and this public project's test suite:
git diff --check: cleanThe synthetic coverage includes persisted graph queries, zero dangling YAML
edges, scalar-value absence, malformed and recursive input, oversized paths,
duplicate keys, aliases, merges, multi-document YAML, and Spring/Ansible
precedence.
Deliberate non-goals
This first phase does not add JSON indexing, scalar-value indexing,
duplicate-value detection, cross-file business-rule validation, business-owner
inference, or Helm values-to-template resolution (#199). Those require explicit
policy and privacy semantics on top of structural indexing.