changedInput schema / properties / UUID / description
Previous value: -"The UUID of the Riddle to edit (as returned by riddle_list / riddle_get)"New value: +"The UUID of the Riddle to edit, as returned by riddle_list or riddle_get (e.g. \"6FA740EW\") - the Riddle itself, never a block id or a project id."
changedInput schema / properties / build / description
Previous value: -"The changes to apply, as a partial build configuration in the engine's own key names - the same shape riddle_get returns under \"build\" and the riddle_builder_<type> tools take. Only the fields you send are touched; send at least one. A field only exists for the Riddle types that have it, and unknown keys are rejected rather than ignored."New value: +"The changes to apply, as a partial build configuration in the engine's own key names - the same shape riddle_get returns under \"build\" and riddle_builder_create takes. Only the fields you send are touched; send at least one. A field only exists for the Riddle types that have it, and unknown keys are rejected rather than ignored."
changedInput schema / properties / build / properties / $blocksOrder / description
Previous value: -"The new order of the Riddle's blocks, as the complete list of their IDs - [3, 1, 2] puts block 3 first. Complete means every ID the Riddle has after this edit, exactly once: a partial list is rejected, because where the blocks you left out belong is exactly what it does not say. It is applied after everything else in the same call, so a block you delete here must NOT be listed and a block you add here MUST be - give a \"$create\" entry an explicit \"id\" to name it, taken from \"nextBlockId\" in the riddle_get response (count up from it for several new blocks) and never derived from the ids in \"build\", which are shared with the Riddle's results and personalities; claiming a taken id is rejected with an error naming the free one. The same marker works inside a block, next to the collection it orders: {\"id\": 3, \"$itemsOrder\": [2, 1]} reorders that block's items, \"$fieldsOrder\" a Form's fields, and it reaches one level deeper through a merged \"fields\" edit - {\"id\": 3, \"fields\": [{\"id\": 5, \"$itemsOrder\": [2, 1]}]} reorders the items of that one Dropdown field. Only a collection whose entries have ids of their own can be ordered at all, and a few that do still reject the marker because an entry's position carries meaning of its own - riddle://reference/concepts/merge-semantics says which collection is which, and the error says so too if you try."New value: +"The new order of the Riddle's blocks, as the complete list of their IDs - [3, 1, 2] puts block 3 first. Complete means every ID the Riddle has AFTER this edit, exactly once; a partial list is rejected. It runs last, so a deleted block must NOT be listed and an added one MUST be - give the \"$create\" entry an explicit \"id\" from riddle_get's \"nextBlockId\". The same marker orders a collection inside a block (\"$itemsOrder\", \"$fieldsOrder\"). Rules: riddle://reference/concepts/merge-semantics."
changedInput schema / properties / build / properties / blocks / description
Previous value: -"The blocks to change, add or remove - only the ones you touch, everything else stays as it is. To EDIT, pass the block's \"id\" (riddle_get reports it) plus only the properties that change - {\"id\": 3, \"title\": \"New question title\"}. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new block needs, the same shape the riddle_builder_<type> tool of this Riddle's type takes - {\"$create\": true, \"type\": \"SingleChoice\", \"title\": \"New question\", \"items\": [...]}. To REMOVE, pass \"id\" plus \"$delete\": true. A block cannot change its \"type\" in an edit (delete it and add a new one instead), and an unknown \"id\" is rejected with the list of IDs that do exist. The collections INSIDE a block work the same way wherever their entries have ids - {\"id\": 3, \"items\": [{\"id\": 2, \"title\": \"Bonn\"}]} renames one answer and leaves the others alone - and are replaced wholesale where they do not. Which collection is which, what an entry id is scoped to, why an entry without an \"id\" or \"$create\" is rejected, which deletes are refused for still being referenced (custom logic, a hotspot's \"goToImage:\"), and which rules are checked against the merge result rather than against what you sent: riddle://reference/concepts/merge-semantics, with the marker rules themselves in riddle://reference/concepts/editing."New value: +"The blocks to change, add or remove - only the ones you touch, everything else stays as it is. EDIT: the block's \"id\" (riddle_get reports it) plus only the properties that change - {\"id\": 3, \"title\": \"New question title\"}. ADD: \"$create\": true instead of an \"id\", plus everything a new block needs in the shape riddle_builder_create takes - {\"$create\": true, \"type\": \"SingleChoice\", \"title\": \"New question\", \"items\": [...]}. REMOVE: \"id\" plus \"$delete\": true. A block cannot change its \"type\"; an unknown \"id\" is rejected naming the ids that exist. A collection inside a block merges by \"id\" the same way - {\"id\": 3, \"items\": [{\"id\": 2, \"title\": \"Bonn\"}]} renames one answer and leaves the others alone. Which collections merge, which are replaced wholesale, and which deletes are refused for still being referenced: riddle://reference/concepts/merge-semantics (markers: riddle://reference/concepts/editing)."
changedInput schema / properties / build / properties / conditions / description
Previous value: -"Prioritized (first match wins), time-windowed list of routing rules evaluated before the fallback \"riddleId\" (max 100 conditions). Each condition targets either another Riddle or a tag - exactly one of \"riddleId\" (UUID of an existing, non-Placeholder, published Riddle) or \"tag\" (name or numeric id of an EXISTING tag in this Riddle's own scope - a typo'd name is rejected, never auto-created; sending a numeric id reads back as the tag NAME, which is ambiguous if two tags in this scope share a name) is required, never both. No other key is accepted on a condition: unknown keys and \"$create\"/\"$delete\" markers are rejected - \"conditions\" always replaces the whole list, there is no per-entry merge (see \"resend\" below). A \"tag\" condition additionally requires \"tagMode\": \"lastPublished\" (the most recently published Riddle carrying that tag) or \"random\" (a random one, optionally re-picked every \"randomRefreshIntervalSeconds\", a positive integer of seconds, only accepted together with tagMode \"random\"; defaults to 86400 when omitted and that default is written into the read-back, so echo it back on a resend for a byte-identical round-trip). Each condition may also carry a time window, either a date range (\"from\", required; \"to\", optional - open-ended) or a daily time-of-day range (\"dailyFrom\" and \"dailyTo\", both required together) - never both kinds on the same condition, and a condition with neither always matches whenever it is reached. Dates accept \"YYYY-MM-DD\" (midnight UTC) or full ISO 8601 (a trailing \"Z\" allowed) and are canonicalized to \"YYYY-MM-DDTHH:MM:SS+00:00\"; daily times accept \"HH:MM\" or \"HH:MM:SS\" and always come back as \"HH:MM:SS\"; a non-string date/time value (a unix int, a bool) is rejected. A date \"to\" before \"from\" is rejected; an out-of-range daily component (\"25:00:00\", \"12:60\") is rejected too, NOT wrapped - \"dailyTo\" before \"dailyFrom\" is the one legitimate exception, meaning an overnight window (e.g. 22:00-02:00). Normalization: the list is NOT stored or returned in the order you send it. It is sorted into three tiers - date-windowed conditions first, then daily-windowed, then windowless (so a daily window can never outrank a date window) - ascending within a tier by \"from\"/\"dailyFrom\" (windowless entries keep your send order); date and daily windows are never compared against each other, and duplicates are kept, not deduplicated. When two windows of the SAME kind overlap, the earlier condition's \"to\"/\"dailyTo\" is silently rewritten to the later condition's start (the later condition wins the contested interval - this is lossy and unannounced); a \"to\"-less condition that is not last in its tier gets a \"to\" synthesized as the next condition's start, so only the last condition of a tier may stay open-ended. Applying this to an already-normalized list changes nothing (idempotent). Resend safety: because \"conditions\" replaces the whole list, a condition (or the fallback) whose target Riddle was deleted/unpublished, or whose tag was removed, is DROPPED from riddle_get with a warning (reason \"PROPERTY_NOT_SERIALIZABLE\" for a condition, path \"conditions[<target>] (<why>)\"; reason \"RIDDLE_DATA_NOT_EXPRESSIBLE\" for the fallback, path \"riddleId\") while still being RETAINED in storage - it reappears once the target becomes valid again. Sending that damaged read-back straight back to riddle_builder_update therefore PERMANENTLY deletes the hidden dangling condition(s); the fallback is not affected the same way, because an omitted \"riddleId\" means \"don't touch it\" rather than \"clear it\" (see that field)."New value: +"Placeholder only. Prioritized (first match wins), time-windowed routing rules evaluated before the fallback \"riddleId\"; at most 100. Each targets exactly one of \"riddleId\" (UUID of an existing, non-Placeholder, published Riddle) or \"tag\" (name or numeric id of an EXISTING tag in this Riddle's scope - a typo'd name is rejected, never auto-created), never both; a \"tag\" also requires \"tagMode\": \"lastPublished\" or \"random\" (with optional \"randomRefreshIntervalSeconds\", \"random\" only). ONE kind of time window per condition - a date range (\"from\" required, \"to\" optional) or a daily one (\"dailyFrom\" plus \"dailyTo\") - with neither it always matches. No other key is accepted. This REPLACES the whole list, and the stored list is re-sorted into tiers with overlapping windows trimmed, so a read-back is not what you sent. Normalization, and why resending a read-back can delete a condition: riddle://reference/riddle-builder/riddle-types with riddleType [\"Placeholder\"]."
changedInput schema / properties / build / properties / leaderboard / description
Previous value: -"Quiz/Predictor/Minigame only. New leaderboard connection, same shape as in the riddle_builder_<type> tools. Omit to leave the Riddle's leaderboard connections exactly as they are - unlike \"riddleConnections\", this is not resolved into a scalar leaf that could be silently reset: the underlying block only runs, and only ever appends a connection, when you actually send this field, so there is nothing to merge per key."New value: +"Quiz/Predictor/Minigame only. New leaderboard connection: \"connections\" (leaderboard UUIDs), \"identifier\", \"nickname\", as in riddle_builder_create. Omit to leave the Riddle's connections exactly as they are - sending this only ever appends a connection, so there is nothing to merge per key."
changedInput schema / properties / build / properties / logic / description
Previous value: -"New branching logic tree, same shape as in the riddle_builder_<type> tools. Replaces the current logic; omit to keep it. Deleting a block (see \"blocks\") that is still referenced by the Riddle's existing CUSTOM logic is rejected unless the same request resolves it: either send a full replacement tree here that no longer references the deleted block(s), or send \"logic\": {\"$reset\": true} to discard the custom logic and fall back to the default linear flow - mutually exclusive, \"$reset\": true alongside any other key in \"logic\" is rejected. The error names exactly which deleted block(s) are still referenced and by which logic node(s). This guard never fires when the logic is already the default linear one: deleting a block always works there, the linear order is simply regenerated."New value: +"New branching logic tree, same shape as in riddle_builder_create. Replaces the current logic; omit to keep it. Deleting a block the stored CUSTOM logic still references is rejected unless the same call sends a replacement tree without it, or \"logic\": {\"$reset\": true} to fall back to the default linear flow (\"$reset\" with any other key is rejected). Node shapes: riddle://reference/concepts/logic."
changedInput schema / properties / build / properties / personalities / description
Previous value: -"Personality Test only. The personalities to change, add or remove - only the ones you touch, everything else stays as it is, merged entry-by-entry by \"id\" exactly like the Riddle's own \"blocks\" (see EDIT_BLOCKS). To EDIT, pass the personality's \"id\" (riddle_get reports it) plus only the properties that change. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new personality needs (the same shape riddle_builder_personality takes). To REMOVE, pass \"id\" plus \"$delete\": true. An entry with no \"id\" and no \"$create\" is rejected the same way a block is - it has no \"id\"; add \"$create\": true to add it as a new one instead. The order of the personalities is NOT editable: there is no \"$personalitiesOrder\" (sending one is rejected) and, because this collection is merged by id, the order the entries are sent in has no meaning either - a \"$create\" is appended at the end and everything else keeps the place it has. Reorder them in the Creator if the order matters. The minimum of 2 personalities is checked against the result AFTER the merge, so a \"$delete\" that would leave fewer than 2 is rejected. The scores already stored on every answer item follow their personality BY IDENTITY, not by position: a personality that stays keeps its score, a deleted personality takes its scores with it, and a newly created personality starts at 0 on every existing answer item until you say otherwise - resend the affected blocks' \"items\" with their full \"scores\" arrays in the same call to set them yourself (that is applied after this and simply wins)."New value: +"Personality Test only. The personalities to change, add or remove, merged by \"id\" exactly like \"blocks\" - \"id\" plus the changed properties, \"$create\": true plus a full new personality, or \"id\" plus \"$delete\": true. There is no \"$personalitiesOrder\": the order is not editable, and the order you send carries no meaning. The minimum of 2 is checked against the merge result. Answer \"scores\" follow a personality by identity, not position - a new one starts at 0 on every existing answer item, so resend the affected blocks' \"items\" with their full \"scores\" arrays in the same call."
changedInput schema / properties / build / properties / preset / description
Previous value: -"Design and riddle-level behaviour settings to change, same shape as in the riddle_builder_<type> tools. Only the keys you send are applied. A Leaderboard's own display settings are part of this too, the podium colours (color1st/color2nd/color3rd) and isEmailVerificationEnabled among them."New value: +"Design and riddle-level behaviour settings to change, same shape as in riddle_builder_create; only the keys you send are applied. A Leaderboard's podium colours (\"color1st\"/\"color2nd\"/\"color3rd\") and \"isEmailVerificationEnabled\" live here too."
changedInput schema / properties / build / properties / publish / description
Previous value: -"Publish-configuration settings to change, same shape as in the riddle_builder_<type> tools. Only the keys you send are applied. Distinct from this tool's top-level \"publish\" boolean, which publishes the Riddle right away."New value: +"Publish-configuration settings to change, same shape as in riddle_builder_create; only the keys you send are applied. Distinct from this tool's top-level \"publish\" boolean, which publishes right away."
changedInput schema / properties / build / properties / result / description
Previous value: -"New single result page (Poll / Form / Predictor / Personality / Minigame / Story), same shape as in the riddle_builder_<type> tools. Replaces the current result page as a whole - a result page cannot be edited property-by-property or merged by id the way \"blocks\" can; send it complete, exactly as you would when creating the Riddle. Omit to keep the current one untouched."New value: +"New single result page (Poll / Form / Predictor / Personality / Minigame / Story), same shape as in riddle_builder_create. Replaces the current one as a whole - a result page is neither editable property-by-property nor mergeable by \"id\", so send it complete. Omit to keep it untouched."
changedInput schema / properties / build / properties / results / description
Previous value: -"New result pages (Quiz), same shape as in riddle_builder_quiz. Replaces ALL current result pages with what you send, in the order you send it: result pages are deliberately neither editable per entry nor reorderable, so read them with riddle_get first and resend every page you want to keep, including its \"id\", which is honored to keep the page stable across the resend. Omit the field to keep all result pages untouched. Why, and which markers are rejected on a page: riddle://reference/concepts/result-pages."New value: +"New result pages (Quiz), same shape as in riddle_builder_create. Replaces ALL current pages with what you send, in the order you send it - pages are neither editable per entry nor reorderable, so read them with riddle_get first and resend every page you want to keep, including its \"id\", which is honored to keep the page stable. Omit to keep them all untouched. riddle://reference/concepts/result-pages."
changedInput schema / properties / build / properties / riddleConnections / description
Previous value: -"Leaderboard only. The complete list of connected Riddle UUIDs - it REPLACES the stored set wholesale rather than appending (the property has no \"append\" flag and buildRiddleConnections() rebuilds the array from scratch), so to add or drop a single connection, call riddle_get first and resend every UUID you want to keep. Max 10; each target Riddle must already be published and must have Name and Email form fields."New value: +"Leaderboard only. The complete list of connected Riddle UUIDs - it REPLACES the stored set rather than appending, so read the Riddle with riddle_get first and resend every UUID you want to keep. Max 10; each target must already be published and have Name and Email form fields."
changedInput schema / properties / build / properties / riddleId / description
Previous value: -"The fallback target: the UUID of the Riddle to show when no condition matches (or there are none). Must be an existing, non-Placeholder, published Riddle, and cannot be this Placeholder itself. Having no fallback at all is meaningful on its own - a Placeholder with no fallback and no matching condition resolves to nothing, which is a decision the Embed side makes, not this repo. On an EDIT, omitting this field means \"don't touch it\"; send \"riddleId\": null to actually clear the fallback back to none - which is rejected when it would leave the Placeholder with no fallback AND no conditions at all (it could then never display any Riddle), so clear it only while at least one condition remains, or send a replacement \"conditions\" list in the same call. The same rule rejects \"conditions\": [] on a Placeholder that has no fallback. If the target is later deleted/unpublished, the fallback is dropped from riddle_get with a warning (reason \"RIDDLE_DATA_NOT_EXPRESSIBLE\", path \"riddleId\") but stays in storage and reappears once the target is valid again."New value: +"Placeholder only. The fallback target: the UUID of the Riddle to show when no condition matches. Must be an existing, non-Placeholder, published Riddle, and not this Placeholder itself. Having none is meaningful - the Placeholder then resolves to nothing. On an EDIT, omitting it leaves it as it is; \"riddleId\": null clears it, and is rejected if that would leave the Placeholder with no fallback and no conditions at all - as is \"conditions\": [] while this is empty. riddle://reference/riddle-builder/riddle-types with riddleType [\"Placeholder\"]."
changedInput schema / properties / build / properties / scoring / description
Previous value: -"Predictor only. New scoring rules, same shape as in riddle_builder_predictor - only the keys you send are changed, the rest of the stored rules are kept. Applied the same way \"preset\"/\"publish\" are: a merge into the existing nested config, not a wholesale replacement, so e.g. sending only {\"correct\": 50} leaves tendency/difference/wrong exactly as they were."New value: +"Predictor only. New scoring rules, same shape as in riddle_builder_create - only the keys you send are changed, so {\"correct\": 50} leaves \"tendency\"/\"difference\"/\"wrong\" as they were. Omit to keep them."
changedInput schema / properties / omit / description
Previous value: -"Leaves parts of the returned envelope out. Values: \"build\", \"warnings\", \"nextBlockId\", \"published\", \"context\" (whole sections) and \"build.omittedDefaults\" (the per-block maps of properties left at their default, inside every build config in the response). Omit for the whole envelope. \"uuid\"/\"type\"/\"modifiedAt\" are always returned. Reach for omit: [\"build.omittedDefaults\"] on almost every build - it drops ~85-90% of the read-back and loses nothing, since riddle://reference/block-defaults/<block type> states the same defaults; what you must not do either way is resend those values. When you leave anything out the response names it under \"omittedFields\", so a missing key never means the Riddle has none of it. Same parameter as riddle_get's."New value: +"Sections of the returned envelope to leave out; omit the parameter for the whole envelope. \"uuid\"/\"type\"/\"modifiedAt\" are always returned, and whatever you leave out is echoed back under \"omittedFields\", so a missing key never means the Riddle has none of it. Details: riddle://reference/concepts/warnings."
changedInput schema / properties / omit / items / enum
Previous value: -[
- "build",
- "warnings",
- "nextBlockId",
- "published",
- "context",
- "build.omittedDefaults"
-]New value: +[
+ "build",
+ "warnings",
+ "nextBlockId",
+ "published",
+ "context"
+]
changedInput schema / properties / publish / description
Previous value: -"Whether to publish the Riddle after the edit; default is false, which leaves the changes in the draft. It rides along with an edit, it is not one: this tool with publish: true and an empty \"build\" is rejected with \"Nothing to edit: send at least one of ...\". To publish what is already in the draft, call riddle_publish."New value: +"Whether to publish the Riddle after the edit; default false, which leaves the changes in the draft. It rides along with an edit, it is not one: publish: true with an empty \"build\" is rejected. To publish what is already in the draft, call riddle_publish."