fix(wix-manage): correct the Create Discount Rule discounts wire shape - #842
Open
danshw wants to merge 3 commits into
Open
fix(wix-manage): correct the Create Discount Rule discounts wire shape#842danshw wants to merge 3 commits into
danshw wants to merge 3 commits into
Conversation
danshw
force-pushed
the
fix/discount-rule-discounts-wire-shape
branch
2 times, most recently
from
August 4, 2026 17:06
50fa20d to
ba90f44
Compare
The discount-rule recipe documented `discounts` as a bare array whose entries
nest the value in a `discount` object. The Discount Rules API accepts neither,
and each mistake returns a 400 that does not name the real problem:
discounts: [ ... ]
-> 400 {"message":"Expected an object"}
discounts: { values: [ { ..., discount: { discountType, percentage } } ] }
-> 400 Validation failed: discount_rule.customer_gets.specific_items_discount
Discount value type does not match discount value
(DISCOUNT_TYPE_AND_DISCOUNT_VALUE_MISMATCH)
`discounts` is an object wrapping a `values` array, and `discountType` sits at
the discount entry root alongside exactly one of `percentage`, `fixedAmount` or
`fixedPrice`:
discounts: { values: [ { targetType, specificItemsInfo, discountType,
percentage } ] }
Corrects the six request/response examples, the key-field table, the
find-by-name update pattern and the recommendation mapping table, maps both 400s
in the existing Error Handling table, and adds a covering eval scenario.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
danshw
force-pushed
the
fix/discount-rule-discounts-wire-shape
branch
from
August 4, 2026 17:09
ba90f44 to
f73c2ef
Compare
Contributor
Author
❌ EvalForge YAML Gate: Scenario Locked by Another PRThese scenarios are draft-tagged for other PRs. Wait for those PRs to merge/close, or coordinate with their authors:
|
…t responses The Critical section described only what the API returns, and closed with "do not reconstruct from scratch unless creating a new rule" — which leaves a create request unconstrained. A paired eval run showed the agent still sending discounts as a bare array with this recipe loaded, taking the same 400 "Expected an object" as production. State the send-side requirement first, and name both rejections.
… not just responses" This reverts commit b0d130e.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Defect
The
pricing-create-discount-rulerecipe documented a Create Discount Rule body that the APIrejects, in two independent ways. Both were in the recipe's own
Critical: discounts structuresection, so an agent following the page verbatim could not succeed on its first call.
1.
discountswas documented as a bare array. It is an object wrapping avaluesarray.2. Discount entries nested the type and value in a
discountobject.discountTypeand thevalue field sit at the entry root.
The shape the API accepts:
Evidence
From a recorded agent run on the request "Set up an automatic discount: 10% off any order over
$50." The agent read this recipe, then spent four rejected
POST /ecom/v1/discount-rulesattempts brute-forcing the payload before succeeding on the fifth:
discountsarray, nesteddiscount(exactly as documented)400 Expected an objectdiscounts.values, nesteddiscount400 DISCOUNT_TYPE_AND_DISCOUNT_VALUE_MISMATCHdiscountsarray,discountTypeat root400 Expected an objectdiscounts.values,discountTypeat root,percentagestill nested400 DISCOUNT_TYPE_AND_DISCOUNT_VALUE_MISMATCHdiscounts.values,discountTypeandpercentageat rootBetween attempts it issued six further schema-probing calls purely to work out the shape. The task
still completed — the outcome judge scored it 10/10 — so this defect is invisible to a
correctness-only assertion and shows up only as cost: the path judge scored 4/10 on two
consecutive daily runs, and the run took ~97 s against a ~50 s median for its batch.
Both corrections were verified against the Discount Rules API schema, which declares
discountsas a message wrapping
repeated Discount values, and declares the value field as aoneof(
percentage/fixed_amount/fixed_price) withdiscount_typeas its sibling — aoneofisflattened in JSON, so its name is not a wire field. That is why the documented
discountwrappercould never have worked.
Why this surface
The recipe is the file the failing agent actually loaded (its first action after the README was
ReadFullDocsArticleon this recipe's URL), and the recipe is where the wrong shape was written.The API schema and reference are already correct — the agent's own schema lookups returned the
right structure, which is how it eventually recovered. So this is not a rendering or publishing
gap upstream; it is a recipe contradicting the API it documents, and correcting the recipe is the
whole fix.
Change
Deliberately scoped to the wrong shape and nothing else — every changed line is one of the two
defects above. No reformatting, and the wrapper is added as
"discounts": { "values": [on one lineso the entries keep their existing indentation and the diff stays reviewable.
skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md— corrects the six request/response examples, the
Critical: discounts structureentry example,the key-field table, the find-by-name update pattern, and the recommendation mapping table. The
two 400s go in the existing
Error Handlingtable as two rows, mapping each message to its cause,rather than as new prose: the corrected examples already carry the shape, so the only thing worth
adding is what an example cannot say. In the recorded run the agent received both 400s and still
needed four attempts, because nothing connected the message to the cause.
yaml/wix-manage-evals/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule-discounts-shape.yml— new covering scenario. It keeps the original request wording, so nothing in the prompt reveals
the payload shape; the discrimination is in the rubrics. Three assertions per
docs/eval-scenarios.md: coverage on this recipe's URL, a correctness judge on the created rule,and a path judge that fails a run which takes either 400 on the way.
On "Orchestration, not API shape"
CONTRIBUTING.mdsays request/response shapes belong in the Wix docs, because restating them"creates a second source of truth that drifts as the API evolves." This recipe already restates seven
full request bodies, and the defect is exactly the drift that rule warns about — so this PR corrects
the restated shapes rather than adding new ones, and adds no new prose restating field names or enum
values. That rule is also why the two 400s became
Error Handlingrows instead of a shapedescription at the top of the file.
Removing the restated bodies altogether, in favour of pointing at the Create Discount Rule reference,
would follow the rule more closely and would delete the drift risk at the source. That is a larger
change to a recipe several other recipes and scenarios lean on, so I have kept it out of this fix and
am flagging it as worth doing separately.
Verification
ruby -e 'require "yaml"; YAML.load_file(…)'on the new scenario — parses.jsonblock that parsed before still parses. Two do not, and both are pre-existing anduntouched: a
"<scopes unchanged from query response>"placeholder, and a trigger example with anintentional
/* same scope */comment.git diff --check— clean.The eval gate has not run on this PR
No workflow has run on this PR, so nothing here is gate-verified. GitHub Actions appears to be
disabled on the repository right now: the repo's Actions permissions report
enabled: false, and noworkflow of any kind has started repo-wide since 16:09 UTC, while this PR was opened at 16:52 UTC.
Every PR opened earlier today has runs; this one has zero, for every workflow, not just the gate.
That is a repository-level condition rather than anything about this diff, and I have not changed the
setting. Once Actions is re-enabled, a push or a reopen will trigger
EvalForge YAML Gateand thenew scenario will run. Please do not read the absence of a red check as a pass.
Please note before merging
This PR edits the same recipe as #666, which is open. The two changes do not overlap in
content — #666 adds Stores collection-ID lookup guidance and touches a different section — and
they do not conflict textually. But both PRs edit the recipe, so both pull in the pre-existing
ecommerce/pricing-promotions/create-discount-rulescenario, and the eval gate treats a scenarioclaimed by two open PRs as held. If this gate reports scenarios held by another PR, that is the
cause rather than anything in this diff, and landing or closing #666 first clears it. I have not
described this PR's gate as passing.