Skip to content

Rectify: Ingredient Key Normalization and Issue-URL Extraction Immunity#4117

Merged
Trecek merged 3 commits into
developfrom
ingredient-key-mismatch-api-py-reads-issue-urls-plural-but-i/4112
Jun 26, 2026
Merged

Rectify: Ingredient Key Normalization and Issue-URL Extraction Immunity#4117
Trecek merged 3 commits into
developfrom
ingredient-key-mismatch-api-py-reads-issue-urls-plural-but-i/4112

Conversation

@Trecek

@Trecek Trecek commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

The 7th occurrence of the label-orphaning bug class was caused by a singular/plural ingredient key mismatch: _api.py:656 reads only "issue_urls" (plural) but implementation/remediation recipes define "issue_url" (singular). This silently produces _issue_urls_raw = "", defeating the DispatchRecord.issue_url fallback (commit deb5d55) and all downstream label cleanup paths.

The fix applies three layers of architectural immunity:

  1. Canonical extraction function (extract_issue_urls()) in a new _issue_url_helpers.py module — the single dual-key accessor used by _api.py.
  2. AST guard (test_issue_url_extraction_guard.py) — bans raw .get("issue_url") / .get("issue_urls") calls in fleet/ (except the helper module and state_types.py), AND asserts positive dual-key completeness in fleet_claim_guard.py.
  3. Integration test that dispatches with singular-key ingredients and no sidecar, asserting label cleanup fires.

Closes #4112

Implementation Plan

Plan file: /home/talon/projects/autoskillit-runs/remediation-20260626-113727-764361/.autoskillit/temp/rectify/rectify_ingredient_key_normalization_2026-06-26_120000.md

🤖 Generated with Claude Code via AutoSkillit

Token Usage Summary

Step Model count uncached output cache_read peak_ctx turns cache_write time
rectify* opus[1m] 1 4.9k 16.0k 1.3M 109.9k 52 90.8k 13m 50s
review_approach* sonnet 1 60 8.3k 257.1k 51.2k 17 37.9k 6m 15s
dry_walkthrough* opus 1 46 9.5k 1.3M 86.7k 52 87.5k 9m 8s
implement* MiniMax-M3 1 108.6k 21.8k 3.0M 0 93 0 5m 48s
assess* opus[1m] 1 48 4.6k 1.0M 58.7k 43 39.6k 5m 9s
audit_impl* sonnet 1 539 11.2k 284.0k 47.9k 20 41.0k 6m 21s
prepare_pr* MiniMax-M3 1 43.4k 2.3k 152.5k 0 14 0 30s
compose_pr* MiniMax-M3 1 36.8k 1.4k 171.8k 0 11 0 31s
review_pr* sonnet 3 510 112.4k 4.0M 99.9k 152 225.2k 28m 58s
ci_conflict_fix* opus[1m] 1 26 2.1k 306.4k 45.6k 19 26.6k 1m 14s
diagnose_ci* MiniMax-M3 1 54.4k 2.3k 297.6k 0 20 0 53s
resolve_ci* opus[1m] 1 54 6.1k 1.7M 77.7k 49 58.5k 4m 29s
Total 249.4k 198.0k 13.8M 109.9k 607.0k 1h 23m

* Step used a non-Anthropic provider; caching behavior may differ.

Token Efficiency

Step LoC Changed cache_read/LoC cache_write/LoC output/LoC
rectify 0
review_approach 0
dry_walkthrough 0
implement 288 10507.4 0.0 75.7
assess 3 344689.7 13199.0 1535.7
audit_impl 0
prepare_pr 0
compose_pr 0
review_pr 0
ci_conflict_fix 381 804.2 69.8 5.5
diagnose_ci 0
resolve_ci 1 1706644.0 58532.0 6130.0
Total 673 20433.8 902.0 294.2

Model Usage Breakdown

Model steps uncached output cache_read cache_write time
opus[1m] 4 5.0k 28.8k 4.3M 215.5k 24m 43s
sonnet 3 1.1k 131.8k 4.5M 304.0k 41m 36s
opus 1 46 9.5k 1.3M 87.5k 9m 8s
MiniMax-M3 4 243.2k 27.8k 3.6M 0 7m 42s

@Trecek Trecek left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

AutoSkillit PR Review — Verdict: approved. No blocking issues found.

Trecek and others added 2 commits June 26, 2026 12:59
The 7th occurrence of the label-orphaning bug class was caused by a
singular/plural ingredient key mismatch: _api.py read only "issue_urls"
(plural) but implementation/remediation recipes define "issue_url"
(singular), silently producing _issue_urls_raw="" and defeating the
DispatchRecord.issue_url fallback (deb5d55) and downstream label cleanup.

Three-layer architectural immunity:

1. Canonical extraction function extract_issue_urls() in a new
   _issue_url_helpers.py module — single dual-key accessor (plural wins,
   singular fallback) used by _api.py:656.

2. AST guard (test_issue_url_extraction_guard.py):
   - BANS raw .get("issue_url") / .get("issue_urls") in fleet/ except in
     _issue_url_helpers.py (defines the canonical accessor) and state_types.py
     (deserializes DispatchRecord from its own JSON dict).
   - Asserts positive dual-key completeness in fleet_claim_guard.py — the
     stdlib-only hook cannot import the canonical helper and keeps its inline
     pattern; the test guarantees both key variants remain present.

3. Integration tests in test_dispatch_labels_cleaned.py dispatch with
   singular-key ingredients and no sidecar, asserting swap_labels fires via
   the issue_url fallback and DispatchRecord.issue_url is populated.

Registry updates:
- tests/arch/test_subpackage_isolation.py: fleet file-count ceiling 22 -> 23
- src/autoskillit/fleet/AGENTS.md: register _issue_url_helpers.py
- tests/fleet/AGENTS.md: register test_issue_url_extraction.py
- tests/arch/AGENTS.md: register test_issue_url_extraction_guard.py

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The test imports autoskillit.recipe.schema.RecipeIngredient but was
missing from LAYER_CASCADE_CONSERVATIVE["recipe"] file-level entries,
causing test_cascade_map_guard to fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Trecek Trecek force-pushed the ingredient-key-mismatch-api-py-reads-issue-urls-plural-but-i/4112 branch from 2b3bda2 to 4346239 Compare June 26, 2026 20:00
…int catalog

The new AST guard added in fa4e7a9 was not registered in the
Architectural Constraint Catalog in resolve-review/SKILL.md, causing
test_catalog_reverse_coverage to fail in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Trecek Trecek added this pull request to the merge queue Jun 26, 2026
Merged via the queue into develop with commit ab0fe25 Jun 26, 2026
3 checks passed
@Trecek Trecek deleted the ingredient-key-mismatch-api-py-reads-issue-urls-plural-but-i/4112 branch June 26, 2026 20:21
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