Skip to content

feat(schemas): column-node anti-pattern validator — Track G G1#187

Open
ronsse wants to merge 1 commit into
mainfrom
worktree-agent-ae856e78e5976bef0
Open

feat(schemas): column-node anti-pattern validator — Track G G1#187
ronsse wants to merge 1 commit into
mainfrom
worktree-agent-ae856e78e5976bef0

Conversation

@ronsse

@ronsse ronsse commented May 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds ENTITY_TYPE_ANTI_PATTERNS frozenset + validate_entity_type_not_anti_pattern() helper to src/trellis/schemas/well_known.py (+92 LOC).
  • Adds allow_structural_leaf: bool = False field to EntityDraft (in src/trellis/schemas/extraction.py) and EntityRule (in src/trellis/extract/json_rules.py). Both wire a Pydantic model_validator(mode="after") that calls the helper at construction time.
  • Soft enforcement: structlog WARNING on entity_type in {"Column", "column", "TableColumn", "table_column"} when allow_structural_leaf=False; INFO when the operator opts in. Never raises; never rejects.
  • Updates 3 existing column-rule tests in tests/unit/extract/test_json_rules.py to set allow_structural_leaf=True (regulated-column exception scenario from a test perspective).
  • Adds tests/unit/schemas/test_anti_pattern_validator.py (+174 LOC, 22 tests) covering WARNING / INFO / silent paths, parametrized over the blocklist + drift pin.

Test plan

  • pytest tests/unit/extract/ tests/unit/schemas/ -v615 passed, 0 failed
  • pytest tests/ (full unit suite) → 3572 passed, 41 skipped, 319 deselected
  • ruff check src/ tests/ eval/ → All checks passed
  • mypy src/ → no issues in 241 source files
  • Cross-check sibling PR for ADR consistency (adr-source-modeling-discipline.md)
  • Wire-layer EntityDraft deliberately NOT modified — see Deferred Findings in agent report; G2/follow-up may revisit

Deferred follow-ups

  • 4 other column-typed tests in test_json_rules.py (test_node_role_preserved, test_field_reference_scalar, test_unknown_target_skipped, test_no_source_matches_yields_no_edges) emit spurious WARNING in test runs (validator is advisory; tests still pass). Add allow_structural_leaf=True in a hygiene follow-up.
  • Wire-layer EntityDraft in src/trellis_wire/extract.py doesn't carry the flag. Today, wire-submitted column drafts trigger server-side WARNING — arguably correct default but worth an explicit ADR call.

🤖 Generated with Claude Code

…ntities

Adds the structural-leaf anti-pattern blocklist (Column / column /
TableColumn / table_column) plus a structlog-based advisory validator.
The validator is wired into EntityRule (extract/json_rules.py) and the
core EntityDraft (schemas/extraction.py) via model_validators that fire
at construction time. With allow_structural_leaf=False (default),
constructing one of these emits a WARNING with a recommendation
pointing at the properties.columns shape; with allow_structural_leaf=
True the regulated-column opt-in is acknowledged via an INFO event for
audit purposes. Soft enforcement only — never raises, never rejects.
Open-string contract preserved (CLAUDE.md, adr-graph-ontology.md).

Updates the 3 existing EntityRule(entity_type="column", ...) cases in
tests/unit/extract/test_json_rules.py (test_nested_path,
test_column_to_enclosing_table, test_missing_ancestor_skips) to set the
opt-in flag so they no longer emit spurious warnings during the test
run; test_closest_ancestor_wins uses entity_type="group"/"item" and is
not on the blocklist, so it needs no update (see Deferred Findings).

Adds tests/unit/schemas/test_anti_pattern_validator.py with parametrised
coverage of all four blocklist values across the WARNING / INFO /
silent paths plus a blocklist-membership pin so drift is caught.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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