Skip to content

feat(ticket-035): versioned bounded projections for intent retrieval - #34

Merged
ifuri-validator-agent[bot] merged 1 commit into
mainfrom
ticket/035-projections-intent-retrieval
Oct 23, 2026
Merged

ifuri-validator-agent[bot] merged 1 commit into
mainfrom
ticket/035-projections-intent-retrieval

Conversation

@tom-sapletta-com

Copy link
Copy Markdown
Contributor

Part of #25 (PLF-035) — strona producenta kontraktu.

Co

Nowy format eksportu -f projections → projections.json:

  • schema code2llm.projection/v1 + producer.version (pin wersji analizatora)
  • rekordy symboli (module/class/function) z proweniencją: symbol, file, line
  • digest sha256 per rekord i całego dokumentu → tania inwalidacja cache po stronie konsumenta
  • determinizm bajtowy: canonical JSON (sorted keys), sortowanie (file, line, kind, symbol), bez timestampów w rekordach (generated_at opcjonalne, poza digestem)
  • boundy kontraktu: MAX_RECORDS=2048 + stats.truncated, pola tnione do 200 znaków

Dlaczego artefakt, nie API

Issue #25: „Reuse … without copying analyzer implementation into search”. Reuse point = wersjonowany artefakt; konsument (canary w semcod/search) czyta JSON bez importów code2llm.

Pomiary (korpus: code2llm/, 180 plików)

artefakt rozmiar czas eksportu
projections.json 459 KB 0.02 s
analysis.json (pełny) 7 163 KB 0.40 s

1401 symboli (1125 funkcji / 96 klas / 180 modułów), bez truncation. Rebuild → byte-identical (cmp).

Testy

  • tests/test_projections_exporter.py (8): determinizm, proweniencja, boundy/truncation, wersjonowanie, registry, CLI help
  • pełny suite: 376 passed (+ test_analysis_cache_version zielony — inwalidacja po __version__ istnieje i jest testowana)

Inwalidacja cache

  • strona code2llm: PersistentCache/make_cache_key już bindują __version__ (test_analysis_cache_version)
  • strona konsumenta: zmiana producer.version lub digestów → reindex (fingerprint semcod/search)

Następny krok (osobny PR w semcod/search): adapter code2llm.projection/v1 w intent_adapters.adapt() + REPORT_PATHS + FORMATS — canary konsumpcji.

Add the projections export format: projections.json, a deterministic,
versioned catalog of source symbols (module/class/function) with
provenance (symbol, file, line), per-record and whole-document sha256
digests, producer version pinning and a hard 2048-record cap with a
truncated flag. Downstream consumers (semcod/search canary) reuse this
artifact instead of importing analyzer internals.

- code2llm/exporters/projections_exporter.py: build_projection() +
  ProjectionsExporter registered as 'projections'
- CLI: -f projections; FORMAT_FILENAMES/DRY_RUN/LABELS wiring
- tests/test_projections_exporter.py: determinism (byte-identical
  rebuilds), provenance, bounds, truncation, version stamping, registry
  and CLI help (8 tests; suite 376 passed)
- Measured on code2llm/ itself (180 files): 459 KB vs 7 163 KB
  analysis.json (15.6x smaller), export 0.02 s, 1401 symbols
  (1125 fn / 96 cls / 180 mod), byte-deterministic across runs

Cache invalidation: producer.version + record digests change on any
analyzer/version drift; PersistentCache keys already bind __version__.

Part of #25

Co-authored-by: Koru Agent <agent@coru.dev>

@ifuri-validator-agent ifuri-validator-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validator approval after policy checks for exact head 69c8d3f2a832497b836fb7542e40daa555ad41f4.

Ticket: ticket-035
Correlation ID: plf-035-pr34
Model: gemini/gemini-3.8-flash
Reviewed diff chunks: 2
Advisory LLM verdict: APPROVE
Advisory summary: Reviewed all 2 diff chunk(s). Implements the bounded symbol catalog exporter (projections.json, schema code2llm.projection/v1) for intent retrieval and external indexers. Determinism, bounds, provenance, CLI wiring, and test coverage are cleanly integrated. | Tests for the new projections exporter thoroughly verify determinism, digest stability, record sorting, bound enforcement (field and record caps), canonical JSON serialization, registry integration, and CLI help output. Required CI checks pass.
Advisory findings: none
The LLM output above is advisory and was not used as the approval trust root.
Semantic review prerequisite: not_required; policy 676cb4516bbfed2a000e40b9b1b6e4a430ecc761ec546aeb53d721a1905cfdd7.

Actual PR impact radar

Exact range: e23613eaee5160c7450914e1f93f6b9329e1aa28...69c8d3f2a832497b836fb7542e40daa555ad41f4
Change digest: 13af8f2afd70cc2497e28685e28342bdefd7af467d3d3ca5c68fdb014cddae83
Score: 76/100 (L), estimated 92 min, split recommended: true
Affected services/components: repository-wide/unclassified

Machine-readable radar JSONL and SVG
{"actual_change":{"additions":293,"base_sha":"e23613eaee5160c7450914e1f93f6b9329e1aa28","binary_files":0,"categories":{"code":5,"docs":1,"tests":1},"change_digest":"13af8f2afd70cc2497e28685e28342bdefd7af467d3d3ca5c68fdb014cddae83","comparison":"e23613eaee5160c7450914e1f93f6b9329e1aa28...69c8d3f2a832497b836fb7542e40daa555ad41f4","deletions":1,"file_count":7,"files":["README.md","code2llm/cli_exports/formats.py","code2llm/cli_exports/orchestrator_constants.py","code2llm/cli_parser.py","code2llm/exporters/__init__.py","code2llm/exporters/projections_exporter.py","tests/test_projections_exporter.py"],"head_sha":"69c8d3f2a832497b836fb7542e40daa555ad41f4","service_count":0,"services":[]},"assessment_mode":"observed-pr","axes":{"coupling":5,"delivery":4,"scope":5,"uncertainty":3,"validation":2},"complexity":"L","confidence":0.9,"diagnostics":["RADAR-ACCEPTANCE-MISSING","RADAR-BUDGET-EXCEEDED"],"estimate":{"budget_minutes":30,"minutes":92,"within_budget":false},"impact":{"components":["boundy","code2llm","code2llm.projection","module","repository-root","semcod","tests"],"files":["README.md","boundy/truncation","code2llm.projection/v1","code2llm/cli_exports/formats.py","code2llm/cli_exports/orchestrator_constants.py","code2llm/cli_parser.py","code2llm/exporters/__init__.py","code2llm/exporters/projections_exporter.py","module/class/function","semcod/search","tests/test_projections_exporter.py"],"public_interfaces":[],"runtime_dependencies":0},"schema":"subactor.ticket-radar/v1","score":76,"split":{"parts":[{"estimated_minutes":12,"name":"Implement boundy","scope":["boundy"]},{"estimated_minutes":12,"name":"Implement code2llm","scope":["code2llm"]},{"estimated_minutes":12,"name":"Implement code2llm.projection","scope":["code2llm.projection"]},{"estimated_minutes":12,"name":"Implement module","scope":["module"]},{"estimated_minutes":12,"name":"Implement repository-root","scope":["repository-root"]},{"estimated_minutes":15,"name":"Validate and project to trackers","scope":["tests","planfile","github/gitlab/jira projections"]}],"reason":"estimated_minutes_exceed_budget","recommended":true},"standards":[{"id":"wellmanifest/dsl","revision":"6c60fc4e0dd1f1bb74f46a7745e28019908d1203","version":"0.1.0-dev"},{"id":"wellmanifest/ticket-lifecycle","revision":"5bf581907a87b46a13a73e6c033d3abe4d9a306f","version":"0.1.0-dev"},{"id":"wellmanifest/git-lifecycle","revision":"7d77d4b7af57e69bc75c3a0290b3a4805c5c4438","version":"0.2.0-dev"},{"id":"wellmanifest/logs","revision":"48c284ef7a069055c0bcb6b900147ce5e65f8b43","version":"0.3.0"}],"ticket_ref":"ticket-035"}
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" role="img"><title>ticket-035: feat(ticket-035): versioned bounded projections for intent retrieval</title><rect width="128" height="128" rx="12" fill="#f8fafc"/><g stroke-width="1"><polygon points="64,55 72,61 69,71 59,71 56,61" fill="none" stroke="#d7dde5"/><polygon points="64,47 80,59 74,78 54,78 48,59" fill="none" stroke="#d7dde5"/><polygon points="64,38 89,56 79,85 49,85 39,56" fill="none" stroke="#d7dde5"/><polygon points="64,30 97,53 84,92 44,92 31,53" fill="none" stroke="#d7dde5"/><polygon points="64,21 105,51 89,99 39,99 23,51" fill="none" stroke="#d7dde5"/><line x1="64" y1="64" x2="64" y2="21" stroke="#aab4c0"/><line x1="64" y1="64" x2="105" y2="51" stroke="#aab4c0"/><line x1="64" y1="64" x2="89" y2="99" stroke="#aab4c0"/><line x1="64" y1="64" x2="39" y2="99" stroke="#aab4c0"/><line x1="64" y1="64" x2="23" y2="51" stroke="#aab4c0"/></g><polygon points="64,21 105,51 79,85 54,78 31,53" fill="#fb923c" fill-opacity="0.45" stroke="#c2410c" stroke-width="2"/><circle cx="64" cy="64" r="3" fill="#c2410c"/><g font-family="sans-serif" font-size="7" fill="#334155"><text x="64" y="11" text-anchor="middle">SCO</text><text x="114" y="48" text-anchor="middle">COU</text><text x="95" y="107" text-anchor="middle">UNC</text><text x="33" y="107" text-anchor="middle">VAL</text><text x="14" y="48" text-anchor="middle">DEL</text></g><text x="64" y="124" text-anchor="middle" font-family="sans-serif" font-size="8" fill="#0f172a">L · 92m</text></svg>
Merge will be attempted after this approval when explicitly authorized. ## Decision record (recomputable)
DECISION D-035-5111
TICKET ticket-035
HEAD_SHA 69c8d3f2a832497b836fb7542e40daa555ad41f4
CORRELATION_ID plf-035-pr34
ACTOR agent:ifuri-validator-agent[bot]
APPLIED_RULE P-CORE-015
INPUT author_login = "tom-sapletta-com"
INPUT observed_checks = ["test (3.13)=PASS","test (3.10)=PASS"]
INPUT required_checks = ["test (3.10)","test (3.13)"]
INPUT required_checks_source = "protected registry (env/request)"
INPUT reviewer_login = "ifuri-validator-agent[bot]"
INPUT semantic_review_assessment = {"schema":"subactor.validator/semantic-review-assessment/v1","subject":{"repository":"semcod/code2llm","pull_request":34,"head_sha":"69c8d3f2a832497b836fb7542e40daa555ad41f4","base_sha":"e23613eaee5160c7450914e1f93f6b9329e1aa28","diff_sha256":"05fd793b1ca215be1e8de1385aaa7d160c6f56652eb059d8e7fff5a6a8cd341d"},"policy":{"policy_schema":"subactor.validator/semantic-review-policy/v1","policy_version":1,"policy_sha256":"676cb4516bbfed2a000e40b9b1b6e4a430ecc761ec546aeb53d721a1905cfdd7","required":false,"critical_paths":[],"observed_paths":["README.md","code2llm/cli_exports/formats.py","code2llm/cli_exports/orchestrator_constants.py","code2llm/cli_parser.py","code2llm/exporters/__init__.py","code2llm/exporters/projections_exporter.py","tests/test_projections_exporter.py"]},"grounding":"full-diff-not-per-finding-proof","execution_authority":false,"status":"not_required","reason":null,"review_sha256":null,"unresolved":[]}
INPUT superseded_checks = []
INPUT ticket_radar_receipt = {"schema":"subactor.ticket-radar/v1","base_sha":"e23613eaee5160c7450914e1f93f6b9329e1aa28","head_sha":"69c8d3f2a832497b836fb7542e40daa555ad41f4","change_digest":"13af8f2afd70cc2497e28685e28342bdefd7af467d3d3ca5c68fdb014cddae83","score":76,"complexity":"L","estimated_minutes":92,"split_recommended":true,"services":[],"authority":"ADVISORY","promotion":"FORBIDDEN"}
VERDICT APPROVE AUTHORITY DETERMINISTIC
REJECTED REQUEST_CHANGES BECAUSE NO_UNSAFE_CHANGE_REASON_FOUND
ADVISORY llm_verdict = "APPROVE" MODEL "gemini/gemini-3.8-flash"
ASSERT VERDICT_AUTHORITY != "ADVISORY"

@ifuri-validator-agent
ifuri-validator-agent Bot merged commit ebfa895 into main Oct 23, 2026
2 checks passed
@ifuri-validator-agent
ifuri-validator-agent Bot deleted the ticket/035-projections-intent-retrieval branch October 23, 2026 09:31
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