diff --git a/skills/build-workflow/SKILL.md b/skills/build-workflow/SKILL.md index 9726701..1e6fe6d 100644 --- a/skills/build-workflow/SKILL.md +++ b/skills/build-workflow/SKILL.md @@ -114,10 +114,15 @@ more than one call, branching, or a schedule. - Prefer plain alphanumeric camelCase names for new blocks, such as `awsAlert`, `parseInput`, and `step1`. This keeps the stored name readable and the reference prefix predictable. Do not use the reserved normalized names `loop`, `parallel`, or `variable`, and do not create names that collide - after normalization. + after normalization. Punctuation in a name is a live hazard rather than a style preference: a + block renamed to `getP&L` left `` unresolved and passed through as literal text, + with the lint reporting nothing. - The field path after the prefix comes from the upstream block's effective output schema and is case-sensitive. Function block return values are under `result`, so use `` or `` only when the catalog declares that shape. +- A tag resolves anywhere in a Function block's `code`, comments and docstrings included, and one + that does not resolve fails the block. Describe a field in prose rather than writing tag-shaped + example text beside the code that uses it. - Before applying a batch, enumerate every `` reference in its inputs. Verify the normalized prefix against the exact upstream block name in workflow state, verify the field path against the catalog output schema, and verify the source is reachable upstream. A clean workflow @@ -140,6 +145,35 @@ more than one call, branching, or a schedule. - Select models, operations, and modes from the returned schema. Do not guess an id from a label or reuse an id from another integration. +## Bind a resource through its selector field + +A resource input is usually exposed twice under one `canonicalParamId`: a basic-mode selector such +as `tableSelector`, `writeFolderPath`, or `workflowId`, and an advanced-mode manual twin such as +`manualTableId`, `manualWriteFolderPath`, or `manualWorkflowId`. Only the active member of the pair +is read at execution; a value sitting on the other member is inert. + +- **Try the selector with the dynamic value first.** Advanced does not mean "the member that takes + a reference". On the File block's write operation the `writeFolderPath` selector resolves a folder + path, including its percent-encoded form, while `manualWriteFolderPath` fails for every value, so + a block-output reference belongs in the selector there. Read the pair out of + `blocks get ` instead of inferring which member is dynamic from its mode. +- **Naming a member selects the mode.** An edit sets the pair's mode from the input keys it names + rather than from their values, and an edit naming both members resolves to the advanced one. So + `{"manualTableId": null}` on a selector-bound block does not clear inert residue: it flips the + block to advanced with an empty id, and the next run fails on a missing required field. +- **Move a block off its manual member in two operations, never combined.** First + `{"manualTableId": ""}` to empty the manual value, then `{"tableSelector": ""}` to bind the + selector and return the pair to basic mode. That order leaves the manual member empty, so a later + flip back to advanced fails loudly instead of silently reading whatever id was left behind. +- **Leave the manual member empty in a graph that will be copied into another workspace.** A copy + remaps a bound selector but carries a manual id verbatim, silently repointing the copy at the + source workspace's resource. +- **An edit merges inputs rather than replacing them.** Fields an edit does not name keep their + previous values, so a block configured over several edits can still carry a stale value on the + member that is no longer active. Read state afterwards and confirm the active member holds the + value and its twin is empty. A value stranded on the inactive member is reported among the apply + lint's field issues while the apply itself still reports success. + ## Author one semantic batch Prefer `workflows operations apply` over full-state replacement. One batch can create several