refactor: reconcile discovery tickets and deduplicate CLI tag helpers - #195
Conversation
… completion in sprint state The koru-scan 'Split large module: inspect_helpers' finding (discovery 2026-09-19T12:42Z, evidence artifact sha256 28f5e52d) was captured against the pre-split snapshot (121L, 6 methods, CC=17) and is stale per its own staleness_check: the regenerated project/analysis.toon.yaml (sha256 85dcab30) LAYERS entry now reads inspect_helpers 25L 0C 0m CC=0.0 <-0. The requested split was already delivered by PLF-130 (commit d598aee, merged 6562be8): tag-based change filtering moved to tagi.utils.change_filter (120L, CC=5) and statistics aggregation/rendering to tagi.utils.change_stats (42L, CC=1), with inspect_helpers.py retained as a 25-line compatibility facade re-exporting all six public names. Focused regression tests shipped with that split: tests/test_change_filter.py (16 tests) and tests/test_change_stats.py (5 tests) pin filtering modes, tag normalization and stats rendering through the facade. Verified: a fresh code2llm scan of src (-f all --no-chunk --toon-yaml, temp output) reproduces the post-split rows (change_filter 120L CC=5, change_stats 42L CC=1, inspect_helpers 25L CC=0.0) with no large/hot flag on any of the three modules; 127/127 pytest pass (venv); ruff findings on the split modules are the pre-existing baseline (no files modified in this ticket). No source change is required. Marked PLF-157 done via planfile and staged only its ticket-block removal, leaving unrelated queue churn uncommitted. Co-authored-by: Koru Agent <agent@coru.dev>
…letion in sprint state The code2llm 'Shotgun Surgery: path_lower' finding (src/tagi/heuristics/metrics.py:33, dedupe key code2llm:smell:shotgun_surgery:src/tagi/heuristics/metrics.py:33) was captured against the pre-fix metrics.py, before the refactor landed. The path_lower shotgun surgery (8 functions) was already removed by d122d74 (PLF-146), which centralized lowercased-path matching in tagi.utils.paths (path_key/path_matches/path_endswith) and routed config, heuristics tags and metrics call sites through it. Current src/ contains no path_lower binding (only a docstring reference to the removed smell in utils/paths.py). No source change is required; this mirrors the identical already-satisfied PLF-155 finding (tags.py:57). Verified: rg finds zero path_lower bindings in src/; a fresh code2llm run with the documented discovery flags (-f all --no-chunk --exclude '*.md' --exclude plugins, temp output) reports zero shotgun-surgery findings and its generated planfile tickets contain no path_lower smell; 127/127 pytest pass (venv); ruff on metrics.py/utils/paths.py/tags.py/config.py reports only the pre-existing baseline (I001, UP035, UP006, F401, BLE001, UP045) identical at HEAD. Marked PLF-158 done via planfile and staged only its ticket-block removal, leaving unrelated queue churn uncommitted. Co-authored-by: Koru Agent <agent@coru.dev>
… in sprint state The code2llm 'Shotgun Surgery: tags' finding (src/tagi/heuristics/tags.py:48, dedupe key code2llm:smell:shotgun_surgery:src/tagi/heuristics/tags.py:48) was captured by the 17:29Z koru-scan against the pre-fix tree, before the refactor landed. The tags shotgun surgery (5 functions: _tag_change, _custom_config_tags, summary_tag, generate_conventional_message, get_heuristics_for_path) was already removed by fc4e93d (PLF-147), which gave each tags binding a distinct name (valid_tags, unique_tags, tag_set, comprehension) leaving _tag_change the single owner of the canonical 'tags' accumulation (span 5 -> 1). No source change is required. Verified: rg finds tags bindings/mutations only inside _tag_change in src/tagi; fresh code2llm runs with the documented discovery flags (-f all --no-chunk --exclude '*.md', temp output) and with --data-flow report zero shotgun-surgery findings; 127/127 pytest pass (venv); ruff on tags.py/_tags.py/formats.py/config.py reports only the pre-existing baseline (I001, UP035, UP006, UP045, BLE001, F401), identical at HEAD. Marked PLF-159 done via planfile and staged only its ticket-block removal, leaving unrelated queue churn uncommitted. Co-authored-by: Koru Agent <agent@coru.dev>
… tickets Whole-project discovery pass: - regenerate code2llm artifacts (analysis, calls, flow, context, map, evolution, project-yaml, prompt, index) plus fresh src-scoped redup duplication report in project/ - koru scan --apply --semcod-artifacts --source koru-scan: no automated suggestions (repo clean by scan thresholds) - IDE analysis of fresh artifacts created focused planfile tickets: PLF-177 dedupe cli tag helpers (4x _ensure_tag_prefix, 2x _resolve_send_target/_is_known_tag), PLF-178 unit tests for analyzer/dependency_graph.py, PLF-179 unit tests for providers/koru.py - record new tickets and PLF-175 completion in sprint state Gates: pytest 127 passed; regix gates all passed. Co-authored-by: Koru Agent <agent@coru.dev>
… in sprint state The code2llm 'Shotgun Surgery: tags' finding (src/tagi/composer/_tags.py:20, dedupe key code2llm:smell:shotgun_surgery:src/tagi/composer/_tags.py:20) was captured by the 18:29Z koru-scan against the pre-fix tree (evidence _tags.py sha 84f953c3...), before fc4e93d (PLF-147) landed at 20:24Z. HEAD's src/tagi/composer/_tags.py is byte-identical to the PLF-147 result (sha 37211f09...): it contains no mutated 'tags' binding, and the canonical 'tags' accumulation now lives only in the single _tag_change function in src/tagi/heuristics/tags.py (span 5 -> 1). No source change is required. Verified: fresh code2llm runs with the documented discovery flags (src/tagi -f all --no-chunk --exclude '*.md') and with --data-flow report zero shotgun-surgery findings (only pre-existing fan-out notes for unrelated modules); 127/127 pytest pass; ruff on composer/_tags.py and heuristics/tags.py reports only the pre-existing baseline (I001, UP035, UP006, UP045, BLE001, F401), identical at HEAD with src/ unmodified. Marked PLF-176 done via planfile and staged only its ticket-block removal, leaving unrelated queue churn uncommitted. Co-authored-by: Koru Agent <agent@coru.dev>
… (PLF-177) Extract _ensure_tag_prefix (4 copies), _is_known_tag and _resolve_send_target (2 copies each, with comment drift) from main.py, git_operations.py, publishing_commands.py and utility_commands.py into src/tagi/cli/tag_targets.py. The tagi.cli package namespace keeps re-exporting all three helpers for backward compatibility with the test suite. Behavior unchanged: redup dup groups 7 -> 4, no EXAC groups remain for these helpers; pytest 127 passed. Co-authored-by: Koru Agent <agent@coru.dev>
Co-authored-by: Koru Agent <agent@coru.dev>
There was a problem hiding this comment.
Validator approval after policy checks for exact head 6688ef7b743760325aa19a0c2af31b24290d3183.
Ticket: PLF-175
Correlation ID: local-semcod-tagi-pr-195-PLF-175
Model: gemini/gemini-3.8-flash
Advisory LLM review: LLM_UNAVAILABLE
Reason: complete review progress requires a bound subject and authenticated App signer
This approval rests on the deterministic checks alone; no advisory opinion was recorded for this head.
Semantic review prerequisite: not_required; policy 676cb4516bbfed2a000e40b9b1b6e4a430ecc761ec546aeb53d721a1905cfdd7.
Actual PR impact radar
Exact range: e87f2423fa85a12136c529b43ccf6f056c4c53f8...6688ef7b743760325aa19a0c2af31b24290d3183
Change digest: dad5c74e88b08b14436b76e2b6844d88892ac76274fd9c36f56285fb6204be32
Score: 56/100 (L), estimated 128 min, split recommended: true
Affected services/components: repository-wide/unclassified
Machine-readable radar JSONL and SVG
{"actual_change":{"additions":2390,"base_sha":"e87f2423fa85a12136c529b43ccf6f056c4c53f8","binary_files":0,"categories":{"code":12,"configuration":10,"docs":1},"change_digest":"dad5c74e88b08b14436b76e2b6844d88892ac76274fd9c36f56285fb6204be32","comparison":"e87f2423fa85a12136c529b43ccf6f056c4c53f8...6688ef7b743760325aa19a0c2af31b24290d3183","deletions":1937,"file_count":23,"files":["planfile/sprints/current.yaml","planfile/sprints/current.yaml.fast.json","project/README.md","project/analysis.toon.yaml","project/calls.mmd","project/calls.toon.yaml","project/calls.yaml","project/compact_flow.mmd","project/duplication.toon.yaml","project/evolution.toon.yaml","project/flow.mmd","project/index.html","project/map.toon.yaml","project/mermaid.export","project/planfile-tickets.yaml","project/project.toon.yaml","project/prompt.txt","src/tagi/cli/__init__.py","src/tagi/cli/git_operations.py","src/tagi/cli/main.py","src/tagi/cli/publishing_commands.py","src/tagi/cli/tag_targets.py","src/tagi/cli/utility_commands.py"],"head_sha":"6688ef7b743760325aa19a0c2af31b24290d3183","service_count":0,"services":[]},"assessment_mode":"observed-pr","axes":{"coupling":3,"delivery":2,"scope":5,"uncertainty":3,"validation":1},"complexity":"L","confidence":0.9,"diagnostics":["RADAR-ACCEPTANCE-MISSING","RADAR-BUDGET-EXCEEDED"],"estimate":{"budget_minutes":30,"minutes":128,"within_budget":false},"impact":{"components":["planfile","project","src/tagi"],"files":["planfile/sprints/current.yaml","planfile/sprints/current.yaml.fast.json","project/README.md","project/analysis.toon.yaml","project/calls.mmd","project/calls.toon.yaml","project/calls.yaml","project/compact_flow.mmd","project/duplication.toon.yaml","project/evolution.toon.yaml","project/flow.mmd","project/index.html","project/map.toon.yaml","project/mermaid.export","project/planfile-tickets.yaml","project/project.toon.yaml","project/prompt.txt","src/tagi/cli/__init__.py","src/tagi/cli/git_operations.py","src/tagi/cli/main.py","src/tagi/cli/publishing_commands.py","src/tagi/cli/tag_targets.py","src/tagi/cli/utility_commands.py"],"public_interfaces":[],"runtime_dependencies":0},"schema":"subactor.ticket-radar/v1","score":56,"split":{"parts":[{"estimated_minutes":30,"name":"Implement planfile","scope":["planfile"]},{"estimated_minutes":30,"name":"Implement project","scope":["project"]},{"estimated_minutes":30,"name":"Implement src/tagi","scope":["src/tagi"]},{"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":"PLF-175"}<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" role="img"><title>PLF-175: refactor: reconcile discovery tickets and deduplicate CLI tag helpers</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 89,56 79,85 59,71 48,59" 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 · 128m</text></svg>DECISION D-175-2630
TICKET PLF-175
HEAD_SHA 6688ef7b743760325aa19a0c2af31b24290d3183
CORRELATION_ID local-semcod-tagi-pr-195-PLF-175
ACTOR agent:ifuri-validator-agent[bot]
APPLIED_RULE P-CORE-015
INPUT author_login = "tom-sapletta-com"
INPUT observed_checks = ["test (3.10)=PASS","test (3.13)=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/tagi","pull_request":195,"head_sha":"6688ef7b743760325aa19a0c2af31b24290d3183","base_sha":"e87f2423fa85a12136c529b43ccf6f056c4c53f8","diff_sha256":"72aeb2218440082364b19472a6e9de3d283cfeef6c2e49b19cd3b9a99d23654a"},"policy":{"policy_schema":"subactor.validator/semantic-review-policy/v1","policy_version":1,"policy_sha256":"676cb4516bbfed2a000e40b9b1b6e4a430ecc761ec546aeb53d721a1905cfdd7","required":false,"critical_paths":[],"observed_paths":[".planfile/sprints/current.yaml",".planfile/sprints/current.yaml.fast.json","project/README.md","project/analysis.toon.yaml","project/calls.mmd","project/calls.toon.yaml","project/calls.yaml","project/compact_flow.mmd","project/duplication.toon.yaml","project/evolution.toon.yaml","project/flow.mmd","project/index.html","project/map.toon.yaml","project/mermaid.export","project/planfile-tickets.yaml","project/project.toon.yaml","project/prompt.txt","src/tagi/cli/__init__.py","src/tagi/cli/git_operations.py","src/tagi/cli/main.py","src/tagi/cli/publishing_commands.py","src/tagi/cli/tag_targets.py","src/tagi/cli/utility_commands.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":"e87f2423fa85a12136c529b43ccf6f056c4c53f8","head_sha":"6688ef7b743760325aa19a0c2af31b24290d3183","change_digest":"dad5c74e88b08b14436b76e2b6844d88892ac76274fd9c36f56285fb6204be32","score":56,"complexity":"L","estimated_minutes":128,"split_recommended":true,"services":[],"authority":"ADVISORY","promotion":"FORBIDDEN"}
VERDICT APPROVE AUTHORITY DETERMINISTIC
REJECTED REQUEST_CHANGES BECAUSE NO_UNSAFE_CHANGE_REASON_FOUND
ADVISORY llm_verdict = "" MODEL "gemini/gemini-3.8-flash"
ASSERT VERDICT_AUTHORITY != "ADVISORY"
Publishes post-merge PLF-157–159 and PLF-175–177 from an isolated worktree.\n\nValidation:
pytest -q— 127 passed.git diff --checkreports four trailing spaces in generated discovery artifacts underproject/; no source-code whitespace findings.