Skip to content

Add test_campaign_dispatch_capture_value_type_checked#3392

Merged
Trecek merged 6 commits into
developfrom
fleet-pr-url-capture-value-type-defaulting-rejects-empty-sid/3334
May 31, 2026
Merged

Add test_campaign_dispatch_capture_value_type_checked#3392
Trecek merged 6 commits into
developfrom
fleet-pr-url-capture-value-type-defaulting-rejects-empty-sid/3334

Conversation

@Trecek
Copy link
Copy Markdown
Collaborator

@Trecek Trecek commented May 31, 2026

Summary

Add the missing test function test_campaign_dispatch_capture_value_type_checked to tests/recipe/test_campaign_loader.py. This test exercises the dispatch-capture-type-matches-contract-optionality semantic rule with two assertions:

  1. A campaign dispatch with value_type="string" on an optional output field → ERROR finding.
  2. The fixed promote-to-main.yaml (which uses optional_string) → no ERROR finding.

Closes #3334

Implementation Plan

Plan file: /home/talon/projects/autoskillit-runs/remediation-20260530-204907-415625/.autoskillit/temp/make-plan/remediation_capture_value_type_test_plan_2026-05-30_214500.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 95 32.2k 2.3M 134.6k 314 123.6k 24m 34s
review_approach* sonnet 1 8.1k 8.3k 194.4k 67.2k 173 43.0k 6m 41s
dry_walkthrough* opus 2 107 32.4k 3.1M 133.4k 354 164.4k 17m 23s
implement* sonnet 2 4.0k 51.1k 8.3M 129.8k 277 265.0k 19m 44s
audit_impl* sonnet 2 2.8k 19.6k 596.4k 60.2k 129 94.4k 11m 4s
make_plan* sonnet 1 183 16.4k 1.4M 84.4k 56 69.2k 4m 45s
prepare_pr* sonnet 1 142.8k 5.0k 358.4k 27.8k 27 15.8k 1m 44s
compose_pr* sonnet 1 51.7k 1.4k 191.7k 27.8k 17 15.5k 46s
review_pr* sonnet 1 110 31.5k 596.0k 82.5k 77 70.8k 9m 25s
resolve_review* opus 1 75 16.2k 3.0M 97.8k 111 82.0k 11m 58s
Total 210.0k 214.0k 20.0M 134.6k 943.9k 1h 48m

* 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 474 17490.4 559.1 107.9
audit_impl 0
make_plan 0
prepare_pr 0
compose_pr 0
review_pr 0
resolve_review 57 52770.7 1438.3 283.8
Total 531 37750.4 1777.6 403.0

Model Usage Breakdown

Model steps uncached output cache_read cache_write time
opus[1m] 1 95 32.2k 2.3M 123.6k 24m 34s
sonnet 7 209.7k 133.2k 11.6M 573.9k 54m 11s
opus 2 182 48.6k 6.1M 246.4k 29m 22s

Trecek and others added 6 commits May 30, 2026 23:33
…changes

Phases 1 and 2 of fix for shorthand capture specs defaulting to
value_type='string', which rejects empty values from optional-output
skills.

Tests (Phase 1):
- test_string_type_rejects_empty_value: asserts string rejects empty
- test_normalize_capture_spec_shorthand_defaults_to_string: regression guard
- test_shorthand_capture_with_empty_value_from_optional_contract_raises: end-to-end
- test_optional_string_explicitly_accepted: explicit branch guard
- test_optional_output_with_string_capture_type_flagged: bundled recipe scan
- test_campaign_dispatch_capture_value_type_checked: value_type assertion on research-campaign
- test_identify_optional_output_fields_extracts_from_contract: unit test for new helper

Architectural changes (Phase 2):
- _validate_capture_value: explicit optional_string branch (2b)
- _normalize_capture_spec: widen to handle dict values with from+type (2c)
- execute_dispatch: widen capture param to dict[str, str | dict[str, str]] (2c)
- dispatch_food_truck: widen capture param to dict[str, str | dict[str, str]] (2c)
- _identify_optional_output_fields: new helper cross-referencing contract outputs (2a)
- capture-type-matches-contract-optionality: new ERROR rule for recipe steps (2a)
- dispatch-capture-type-matches-contract-optionality: new ERROR rule for campaign dispatches (2a)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Converts all 8 shorthand capture specs that reference optional-output
fields to long-form with type: optional_string. Prevents
CaptureValueTypeError at runtime when a skill returns an empty value
for fields the contract explicitly allows to be empty (e.g. pr_url
when dry_run or preflight_failed, category_summary on preflight_failed).

Files updated:
- campaigns/promote-to-main.yaml: pr_url
- promote-to-main-wrapper.yaml: pr_url, category_summary
- implementation.yaml: compose_pr step pr_url
- remediation.yaml: compose_pr step pr_url
- implementation-groups.yaml: compose_pr step pr_url
- research.yaml: compose_research_pr step pr_url
- research-review.yaml: compose_research_pr step pr_url

Compiled JSON files updated to match. Docstring for
test_recipe_step_shorthand_capture_parses_to_capture_entry_spec
updated to document that shorthand string captures remain valid for
mandatory output fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tests that dispatch-capture-type-matches-contract-optionality emits an
ERROR when pr_url uses value_type='string' on an optional output field,
and that the fixed promote-to-main.yaml (using optional_string) passes clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The dispatch-capture-type-matches-contract-optionality rule requires an
expected_output_pattern with an optional capture group to identify pr_url
as optional. Without it, _identify_optional_output_fields returns empty
and the rule never fires for pr_url captures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Eliminates cross-import between rule modules (rules_optional_capture →
campaign/rules_campaign_capture) by moving the shared helper to the
canonical _rule_helpers.py module. Re-exports from the original location
for backward compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…in _normalize_capture_spec

Add explicit check for missing/empty 'from' key in dict-form capture
entries — logs warning and skips instead of crashing in CaptureEntrySpec
constructor. Add warning log before silently coercing invalid value_type
to 'string', matching the established pattern in recipe/io.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Trecek Trecek force-pushed the fleet-pr-url-capture-value-type-defaulting-rejects-empty-sid/3334 branch from b6ac427 to 43be18a Compare May 31, 2026 06:33
@Trecek Trecek added this pull request to the merge queue May 31, 2026
Merged via the queue into develop with commit 3b9ab04 May 31, 2026
3 checks passed
@Trecek Trecek deleted the fleet-pr-url-capture-value-type-defaulting-rejects-empty-sid/3334 branch May 31, 2026 06:46
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