@uipath/skills 1.204.0 → 1.204.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.cursor-plugin/plugin.json +1 -1
  4. package/CODEOWNERS +12 -14
  5. package/package.json +1 -1
  6. package/skills/uipath-agents/references/coded/embedding-in-flows.md +1 -3
  7. package/skills/uipath-agents/references/coded/quickstart.md +0 -2
  8. package/skills/uipath-agents/references/lowcode/capabilities/inline-in-flow/inline-in-flow.md +10 -8
  9. package/skills/uipath-agents/references/lowcode/prompting/autonomous-agent-prompting-guide.md +1 -1
  10. package/skills/uipath-human-in-the-loop/SKILL.md +1 -3
  11. package/skills/uipath-human-in-the-loop/references/hitl-node-apptask.md +0 -2
  12. package/skills/uipath-human-in-the-loop/references/hitl-node-coded-action-app.md +0 -2
  13. package/skills/uipath-human-in-the-loop/references/hitl-node-quickform.md +2 -2
  14. package/skills/uipath-maestro-flow/.maintenance/README.md +265 -0
  15. package/skills/uipath-maestro-flow/.maintenance/check-all.sh +40 -0
  16. package/skills/uipath-maestro-flow/.maintenance/check-anchors.sh +101 -0
  17. package/skills/uipath-maestro-flow/.maintenance/check-depth.sh +132 -0
  18. package/skills/uipath-maestro-flow/.maintenance/check-link-text.sh +123 -0
  19. package/skills/uipath-maestro-flow/.maintenance/check-links.sh +73 -0
  20. package/skills/uipath-maestro-flow/.maintenance/check-orphans.sh +93 -0
  21. package/skills/uipath-maestro-flow/.maintenance/check-plugin-pairs.sh +39 -0
  22. package/skills/uipath-maestro-flow/.maintenance/check-template.sh +42 -0
  23. package/skills/uipath-maestro-flow/.maintenance/check-uip-commands.sh +270 -0
  24. package/skills/uipath-maestro-flow/.maintenance/check-versions.sh +160 -0
  25. package/skills/uipath-maestro-flow/SKILL.md +69 -886
  26. package/skills/uipath-maestro-flow/references/author/CAPABILITY.md +207 -0
  27. package/skills/uipath-maestro-flow/references/author/brownfield.md +91 -0
  28. package/skills/uipath-maestro-flow/references/author/editing-operations-cli.md +190 -0
  29. package/skills/uipath-maestro-flow/references/author/editing-operations-json.md +374 -0
  30. package/skills/uipath-maestro-flow/references/author/editing-operations.md +104 -0
  31. package/skills/uipath-maestro-flow/references/author/greenfield.md +420 -0
  32. package/skills/uipath-maestro-flow/references/author/planning-arch.md +364 -0
  33. package/skills/uipath-maestro-flow/references/author/planning-impl.md +291 -0
  34. package/skills/uipath-maestro-flow/references/author/plugins/agent/impl.md +237 -0
  35. package/skills/uipath-maestro-flow/references/author/plugins/agent/planning.md +97 -0
  36. package/skills/uipath-maestro-flow/references/author/plugins/agentic-process/impl.md +107 -0
  37. package/skills/uipath-maestro-flow/references/author/plugins/agentic-process/planning.md +61 -0
  38. package/skills/uipath-maestro-flow/references/author/plugins/api-workflow/impl.md +108 -0
  39. package/skills/uipath-maestro-flow/references/author/plugins/api-workflow/planning.md +60 -0
  40. package/skills/uipath-maestro-flow/references/author/plugins/batch-transform/impl.md +171 -0
  41. package/skills/uipath-maestro-flow/references/author/plugins/batch-transform/planning.md +72 -0
  42. package/skills/uipath-maestro-flow/references/author/plugins/connector/impl-inline.md +120 -0
  43. package/skills/uipath-maestro-flow/references/author/plugins/connector/impl.md +463 -0
  44. package/skills/uipath-maestro-flow/references/author/plugins/connector/planning.md +186 -0
  45. package/skills/uipath-maestro-flow/references/author/plugins/connector-trigger/impl.md +517 -0
  46. package/skills/uipath-maestro-flow/references/author/plugins/connector-trigger/planning.md +115 -0
  47. package/skills/uipath-maestro-flow/references/author/plugins/conversational-agent/impl.md +309 -0
  48. package/skills/uipath-maestro-flow/references/author/plugins/conversational-agent/planning.md +133 -0
  49. package/skills/uipath-maestro-flow/references/author/plugins/data-fabric/impl.md +428 -0
  50. package/skills/uipath-maestro-flow/references/author/plugins/data-fabric/planning.md +188 -0
  51. package/skills/uipath-maestro-flow/references/author/plugins/decision/impl.md +83 -0
  52. package/skills/uipath-maestro-flow/references/author/plugins/decision/planning.md +38 -0
  53. package/skills/uipath-maestro-flow/references/author/plugins/delay/impl.md +38 -0
  54. package/skills/uipath-maestro-flow/references/author/plugins/delay/planning.md +53 -0
  55. package/skills/uipath-maestro-flow/references/author/plugins/end/impl.md +56 -0
  56. package/skills/uipath-maestro-flow/references/author/plugins/end/planning.md +28 -0
  57. package/skills/uipath-maestro-flow/references/author/plugins/flow/impl.md +107 -0
  58. package/skills/uipath-maestro-flow/references/author/plugins/flow/planning.md +58 -0
  59. package/skills/uipath-maestro-flow/references/author/plugins/hitl/impl.md +181 -0
  60. package/skills/uipath-maestro-flow/references/author/plugins/hitl/planning.md +166 -0
  61. package/skills/uipath-maestro-flow/references/author/plugins/http/impl-connector.md +86 -0
  62. package/skills/uipath-maestro-flow/references/author/plugins/http/impl-manual.md +68 -0
  63. package/skills/uipath-maestro-flow/references/author/plugins/http/impl.md +173 -0
  64. package/skills/uipath-maestro-flow/references/author/plugins/http/planning.md +107 -0
  65. package/skills/uipath-maestro-flow/references/author/plugins/inline-agent/impl.md +540 -0
  66. package/skills/uipath-maestro-flow/references/author/plugins/inline-agent/planning.md +115 -0
  67. package/skills/uipath-maestro-flow/references/author/plugins/inline-voice-agent/impl.md +269 -0
  68. package/skills/uipath-maestro-flow/references/author/plugins/inline-voice-agent/planning.md +128 -0
  69. package/skills/uipath-maestro-flow/references/author/plugins/ixp/impl.md +424 -0
  70. package/skills/uipath-maestro-flow/references/author/plugins/ixp/planning.md +95 -0
  71. package/skills/uipath-maestro-flow/references/author/plugins/loop/impl.md +403 -0
  72. package/skills/uipath-maestro-flow/references/author/plugins/loop/planning.md +60 -0
  73. package/skills/uipath-maestro-flow/references/author/plugins/merge/impl.md +43 -0
  74. package/skills/uipath-maestro-flow/references/author/plugins/merge/planning.md +24 -0
  75. package/skills/uipath-maestro-flow/references/author/plugins/queue/impl.md +82 -0
  76. package/skills/uipath-maestro-flow/references/author/plugins/queue/planning.md +44 -0
  77. package/skills/uipath-maestro-flow/references/author/plugins/rpa/impl.md +117 -0
  78. package/skills/uipath-maestro-flow/references/author/plugins/rpa/planning.md +61 -0
  79. package/skills/uipath-maestro-flow/references/author/plugins/scheduled-trigger/impl.md +56 -0
  80. package/skills/uipath-maestro-flow/references/author/plugins/scheduled-trigger/planning.md +93 -0
  81. package/skills/uipath-maestro-flow/references/author/plugins/script/impl.md +98 -0
  82. package/skills/uipath-maestro-flow/references/author/plugins/script/planning.md +42 -0
  83. package/skills/uipath-maestro-flow/references/author/plugins/subflow/impl.md +164 -0
  84. package/skills/uipath-maestro-flow/references/author/plugins/subflow/planning.md +35 -0
  85. package/skills/uipath-maestro-flow/references/author/plugins/summarize/impl.md +189 -0
  86. package/skills/uipath-maestro-flow/references/author/plugins/summarize/planning.md +66 -0
  87. package/skills/uipath-maestro-flow/references/author/plugins/switch/impl.md +72 -0
  88. package/skills/uipath-maestro-flow/references/author/plugins/switch/planning.md +34 -0
  89. package/skills/uipath-maestro-flow/references/author/plugins/terminate/impl.md +48 -0
  90. package/skills/uipath-maestro-flow/references/author/plugins/terminate/planning.md +29 -0
  91. package/skills/uipath-maestro-flow/references/author/plugins/transform/impl.md +252 -0
  92. package/skills/uipath-maestro-flow/references/author/plugins/transform/planning.md +47 -0
  93. package/skills/uipath-maestro-flow/references/diagnose/CAPABILITY.md +73 -0
  94. package/skills/uipath-maestro-flow/references/diagnose/failure-modes.md +353 -0
  95. package/skills/uipath-maestro-flow/references/diagnose/troubleshooting-guide.md +174 -0
  96. package/skills/uipath-maestro-flow/references/evaluate/CAPABILITY.md +134 -0
  97. package/skills/uipath-maestro-flow/references/evaluate/commands-reference.md +376 -0
  98. package/skills/uipath-maestro-flow/references/evaluate/eval-sets-guide.md +227 -0
  99. package/skills/uipath-maestro-flow/references/evaluate/evaluators-guide.md +143 -0
  100. package/skills/uipath-maestro-flow/references/evaluate/running-guide.md +215 -0
  101. package/skills/uipath-maestro-flow/references/evaluate/upload-safety.md +94 -0
  102. package/skills/uipath-maestro-flow/references/operate/CAPABILITY.md +77 -0
  103. package/skills/uipath-maestro-flow/references/operate/manage.md +39 -0
  104. package/skills/uipath-maestro-flow/references/operate/run.md +121 -0
  105. package/skills/uipath-maestro-flow/references/operate/ship.md +57 -0
  106. package/skills/uipath-maestro-flow/references/shared/action-nodes.md +100 -0
  107. package/skills/uipath-maestro-flow/references/shared/cli-commands.md +269 -0
  108. package/skills/uipath-maestro-flow/references/shared/cli-conventions.md +178 -0
  109. package/skills/uipath-maestro-flow/references/shared/file-format.md +582 -0
  110. package/skills/uipath-maestro-flow/references/shared/node-output-wiring.md +86 -0
  111. package/skills/uipath-maestro-flow/references/shared/ux-narration-and-todos.md +113 -0
  112. package/skills/uipath-maestro-flow/references/shared/variables-and-expressions.md +787 -0
  113. package/skills/uipath-platform/references/integration-service/activities.md +2 -2
  114. package/skills/uipath-platform/references/integration-service/activity-generation.md +8 -1
  115. package/skills/uipath-platform/references/integration-service/triggers.md +1 -3
  116. package/version-manifest.json +1 -1
  117. package/skills/uipath-maestro-flow/examples/AquariumSafetyStop.flow.ts +0 -26
  118. package/skills/uipath-maestro-flow/examples/ArchiveCardExtract.flow.ts +0 -38
  119. package/skills/uipath-maestro-flow/examples/BakeOffEntryForm.flow.ts +0 -27
  120. package/skills/uipath-maestro-flow/examples/BeeHiveLedger.flow.ts +0 -61
  121. package/skills/uipath-maestro-flow/examples/BeltProgression.flow.ts +0 -53
  122. package/skills/uipath-maestro-flow/examples/BirdCountLookup.flow.ts +0 -24
  123. package/skills/uipath-maestro-flow/examples/ClubDirectory.flow.ts +0 -56
  124. package/skills/uipath-maestro-flow/examples/ConcertSoundcheck.flow.ts +0 -59
  125. package/skills/uipath-maestro-flow/examples/DoorbellLog.flow.ts +0 -45
  126. package/skills/uipath-maestro-flow/examples/FestivalMapScaffold.flow.ts +0 -22
  127. package/skills/uipath-maestro-flow/examples/FieldTripQuickForm.flow.ts +0 -45
  128. package/skills/uipath-maestro-flow/examples/FossilCatalogEnrich.flow.ts +0 -26
  129. package/skills/uipath-maestro-flow/examples/GallerySubmission.flow.ts +0 -67
  130. package/skills/uipath-maestro-flow/examples/GreenhouseWatering.flow.ts +0 -39
  131. package/skills/uipath-maestro-flow/examples/HarbourRadioLine.flow.ts +0 -31
  132. package/skills/uipath-maestro-flow/examples/HerbariumDispatch.flow.ts +0 -34
  133. package/skills/uipath-maestro-flow/examples/KilnReview.flow.ts +0 -38
  134. package/skills/uipath-maestro-flow/examples/LibraryDeskChat.flow.ts +0 -39
  135. package/skills/uipath-maestro-flow/examples/LighthouseSignal.flow.ts +0 -30
  136. package/skills/uipath-maestro-flow/examples/MeteorShowerPages.flow.ts +0 -39
  137. package/skills/uipath-maestro-flow/examples/NeighborhoodWalkPlanner.flow.ts +0 -27
  138. package/skills/uipath-maestro-flow/examples/ObservatorySeeing.flow.ts +0 -51
  139. package/skills/uipath-maestro-flow/examples/OralHistoryDigest.flow.ts +0 -31
  140. package/skills/uipath-maestro-flow/examples/PlanetariumConfirmation.flow.ts +0 -34
  141. package/skills/uipath-maestro-flow/examples/PlantNameAdvisor.flow.ts +0 -28
  142. package/skills/uipath-maestro-flow/examples/PostcardCaption.flow.ts +0 -44
  143. package/skills/uipath-maestro-flow/examples/PotteryStudioCallback.flow.ts +0 -41
  144. package/skills/uipath-maestro-flow/examples/RecipeScaler.flow.ts +0 -62
  145. package/skills/uipath-maestro-flow/examples/SeedPacketReader.flow.ts +0 -49
  146. package/skills/uipath-maestro-flow/examples/TideTableConverter.flow.ts +0 -35
  147. package/skills/uipath-maestro-flow/examples/TrailLogSummary.flow.ts +0 -75
  148. package/skills/uipath-maestro-flow/examples/WorkshopInventory.flow.ts +0 -27
  149. package/skills/uipath-maestro-flow/examples/bindings.json +0 -85
  150. package/skills/uipath-maestro-flow/references/CLI-LOOP.md +0 -309
  151. package/skills/uipath-maestro-flow/references/agent-resources.md +0 -74
  152. package/skills/uipath-maestro-flow/references/agent.md +0 -175
  153. package/skills/uipath-maestro-flow/references/agentic-process.md +0 -41
  154. package/skills/uipath-maestro-flow/references/api-workflow.md +0 -29
  155. package/skills/uipath-maestro-flow/references/author.md +0 -178
  156. package/skills/uipath-maestro-flow/references/batch-transform.md +0 -23
  157. package/skills/uipath-maestro-flow/references/bindings.md +0 -178
  158. package/skills/uipath-maestro-flow/references/branch.md +0 -18
  159. package/skills/uipath-maestro-flow/references/brownfield.md +0 -152
  160. package/skills/uipath-maestro-flow/references/connector-params.md +0 -624
  161. package/skills/uipath-maestro-flow/references/conversational.md +0 -77
  162. package/skills/uipath-maestro-flow/references/data-fabric.md +0 -268
  163. package/skills/uipath-maestro-flow/references/delay.md +0 -26
  164. package/skills/uipath-maestro-flow/references/diagnose.md +0 -141
  165. package/skills/uipath-maestro-flow/references/document-pipeline.md +0 -47
  166. package/skills/uipath-maestro-flow/references/error-handling.md +0 -75
  167. package/skills/uipath-maestro-flow/references/evaluate.md +0 -168
  168. package/skills/uipath-maestro-flow/references/event-trigger.md +0 -155
  169. package/skills/uipath-maestro-flow/references/form-trigger.md +0 -41
  170. package/skills/uipath-maestro-flow/references/hitl.md +0 -169
  171. package/skills/uipath-maestro-flow/references/http.md +0 -105
  172. package/skills/uipath-maestro-flow/references/inline-agent.md +0 -132
  173. package/skills/uipath-maestro-flow/references/ixp.md +0 -167
  174. package/skills/uipath-maestro-flow/references/loops.md +0 -77
  175. package/skills/uipath-maestro-flow/references/manual-trigger.md +0 -39
  176. package/skills/uipath-maestro-flow/references/operate.md +0 -204
  177. package/skills/uipath-maestro-flow/references/or-processes.md +0 -91
  178. package/skills/uipath-maestro-flow/references/parallel-merge.md +0 -21
  179. package/skills/uipath-maestro-flow/references/placeholder.md +0 -70
  180. package/skills/uipath-maestro-flow/references/published-function.md +0 -66
  181. package/skills/uipath-maestro-flow/references/queue.md +0 -53
  182. package/skills/uipath-maestro-flow/references/return.md +0 -20
  183. package/skills/uipath-maestro-flow/references/rpa-workflow.md +0 -27
  184. package/skills/uipath-maestro-flow/references/scheduled-trigger.md +0 -34
  185. package/skills/uipath-maestro-flow/references/script.md +0 -52
  186. package/skills/uipath-maestro-flow/references/subflow.md +0 -33
  187. package/skills/uipath-maestro-flow/references/summarize.md +0 -20
  188. package/skills/uipath-maestro-flow/references/switch.md +0 -20
  189. package/skills/uipath-maestro-flow/references/terminate.md +0 -22
  190. package/skills/uipath-maestro-flow/references/transform.md +0 -32
  191. package/skills/uipath-maestro-flow/references/voice.md +0 -70
@@ -0,0 +1,270 @@
1
+ #!/bin/bash
2
+ # Verify every `uip` command referenced in this skill's markdown actually exists.
3
+ # Usage: bash .maintenance/check-uip-commands.sh [--strict] [file1.md ...]
4
+ # Output: BAD lines per unknown command, then "commands_checked=N unknown=M" summary.
5
+ #
6
+ # Scans fenced code blocks (```bash, ```sh, ```shell, ```zsh, ```console, or
7
+ # unlabelled ```) under this skill for lines that begin with `uip `, extracts
8
+ # the command path (tokens before the first flag, placeholder, or shell
9
+ # metachar), and verifies it against `uip <path> --help`. Help output only —
10
+ # no command is ever executed for real.
11
+ #
12
+ # How verification works: `uip <bogus> --help` silently falls back to the
13
+ # parent's help, so exit code is not a reliable signal. Instead, we walk the
14
+ # path level by level and confirm each next segment appears in the parent's
15
+ # `Subcommands[].Name` list. Help responses are cached per prefix.
16
+ #
17
+ # Skips:
18
+ # - Inline backtick references like `uip ...` (only fenced blocks are scanned)
19
+ # - Files matching --skip-glob
20
+ #
21
+ # --strict: exit 2 if `uip` is not on PATH (CI mode). Default: warn and exit 0.
22
+ #
23
+ # Exits non-zero if any unknown command is referenced.
24
+
25
+ set -e
26
+
27
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
28
+ cd "$ROOT" || exit 1
29
+
30
+ STRICT=0
31
+ FILES=()
32
+ for arg in "$@"; do
33
+ case "$arg" in
34
+ --strict) STRICT=1 ;;
35
+ *) FILES+=("$arg") ;;
36
+ esac
37
+ done
38
+
39
+ if ! command -v uip >/dev/null 2>&1; then
40
+ if [ "$STRICT" -eq 1 ]; then
41
+ echo "uip not found on PATH (--strict)" >&2
42
+ exit 2
43
+ fi
44
+ echo "uip not found on PATH; skipping (use --strict to fail)" >&2
45
+ echo ""
46
+ echo "commands_checked=0 unknown=0"
47
+ exit 0
48
+ fi
49
+
50
+ if ! command -v python3 >/dev/null 2>&1; then
51
+ echo "python3 not found on PATH" >&2
52
+ exit 2
53
+ fi
54
+
55
+ if [ "${#FILES[@]}" -eq 0 ]; then
56
+ # Scan the skill's published surface only: SKILL.md + references/.
57
+ # Skips .maintenance/, scratch files at the skill root (PLAN.md, PR_BODY.md),
58
+ # and anything else that isn't part of what agents load.
59
+ while IFS= read -r f; do
60
+ FILES+=("$f")
61
+ done < <({ [ -f SKILL.md ] && echo "./SKILL.md"; /usr/bin/find ./references -type f -name '*.md' 2>/dev/null; } | /usr/bin/sort)
62
+ fi
63
+
64
+ if [ "${#FILES[@]}" -eq 0 ]; then
65
+ echo ""
66
+ echo "commands_checked=0 unknown=0"
67
+ exit 0
68
+ fi
69
+
70
+ export UIP_BIN="$(command -v uip)"
71
+ export SKILL_ROOT="$ROOT"
72
+
73
+ python3 - "${FILES[@]}" <<'PYEOF'
74
+ import json
75
+ import os
76
+ import re
77
+ import subprocess
78
+ import sys
79
+ from pathlib import Path
80
+
81
+ UIP = os.environ["UIP_BIN"]
82
+ SKILL_ROOT = Path(os.environ["SKILL_ROOT"])
83
+ files = [Path(p) for p in sys.argv[1:]]
84
+
85
+ # Cache value: (subcommands_set, takes_positional_args) or None for invalid prefix
86
+ _help_cache: dict[tuple, tuple[set, bool] | None] = {}
87
+
88
+
89
+ def get_help(prefix):
90
+ if prefix in _help_cache:
91
+ return _help_cache[prefix]
92
+ # `--output json` is required: top-level `uip --help` defaults to plain
93
+ # text; other levels default to JSON but accept the flag too. Forcing it
94
+ # makes parsing deterministic.
95
+ cmd = [UIP, *prefix, "--help", "--output", "json"]
96
+ try:
97
+ proc = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
98
+ except Exception:
99
+ _help_cache[prefix] = None
100
+ return None
101
+ # uip prints non-JSON noise around the help payload — sometimes a banner
102
+ # before (e.g. `Tool factory already registered ...`), sometimes a human
103
+ # usage block after. Use raw_decode to grab the first complete JSON object.
104
+ out = proc.stdout
105
+ brace = out.find("{")
106
+ if brace < 0:
107
+ _help_cache[prefix] = None
108
+ return None
109
+ try:
110
+ data, _ = json.JSONDecoder().raw_decode(out[brace:])
111
+ except json.JSONDecodeError:
112
+ _help_cache[prefix] = None
113
+ return None
114
+ inner = data.get("Data", {})
115
+ resolved = inner.get("Command", "")
116
+ expected = prefix[-1] if prefix else "uip"
117
+ if resolved != expected:
118
+ _help_cache[prefix] = None
119
+ return None
120
+ subs = set()
121
+ for entry in inner.get("Subcommands", []) or []:
122
+ name = entry.get("Name", "")
123
+ leaf = name.split(None, 1)[0]
124
+ if leaf:
125
+ # Subcommand names may be pipe-aliased (e.g. `or|orchestrator`).
126
+ # Register each alias separately so either form is accepted.
127
+ for alias in leaf.split("|"):
128
+ if alias:
129
+ subs.add(alias)
130
+ takes_args = bool(inner.get("Arguments"))
131
+ _help_cache[prefix] = (subs, takes_args)
132
+ return _help_cache[prefix]
133
+
134
+
135
+ def verify_path(path):
136
+ prefix = ()
137
+ for seg in path:
138
+ info = get_help(prefix)
139
+ if info is None:
140
+ return False, prefix[-1] if prefix else seg, []
141
+ subs, takes_args = info
142
+ if seg not in subs:
143
+ # If the parent is a leaf (no subcommands) and accepts positional
144
+ # args, this token is an arg — path is valid up to here.
145
+ if not subs and takes_args:
146
+ return True, "", []
147
+ import difflib
148
+ return False, seg, difflib.get_close_matches(seg, sorted(subs), n=3, cutoff=0.5)
149
+ prefix = prefix + (seg,)
150
+ return True, "", []
151
+
152
+
153
+ FENCE_RE = re.compile(r"^```([a-zA-Z0-9_+-]*)\s*$")
154
+ ACCEPTED_LANGS = {"", "bash", "sh", "shell", "zsh", "console"}
155
+ # Inline single-backtick spans. Greedy is fine: ` cannot appear inside a
156
+ # single-backtick span by definition (use double-backtick spans for that, which
157
+ # we deliberately don't scan — they're rare and usually contain code samples).
158
+ INLINE_RE = re.compile(r"`([^`\n]+)`")
159
+ # Per-line opt-out marker: `<!-- uip-check-skip -->` anywhere on the line
160
+ # suppresses checking for that line. Used for intentional historical references
161
+ # (e.g. CLI version-comparison tables that document a removed prefix). For
162
+ # table rows, place the marker inside a cell (e.g. `| ... | ... <!-- uip-check-skip --> |`)
163
+ # so it doesn't break table structure — HTML comments render as nothing.
164
+ SKIP_MARKER = "<!-- uip-check-skip -->"
165
+
166
+
167
+ SUBCOMMAND_RE = re.compile(r"^[a-z][a-z0-9-]*$")
168
+
169
+
170
+ def is_terminator(tok):
171
+ # A real uip subcommand is a lowercase kebab-case identifier. Anything else
172
+ # (flags, placeholders, paths, comments, quoted strings, shell metachars,
173
+ # positional args) ends the path.
174
+ if not tok:
175
+ return True
176
+ if tok.startswith("#"):
177
+ return True
178
+ if tok in {"|", ">", ">>", "<", "&&", "||", ";", "&", "$(", "`"}:
179
+ return True
180
+ return not SUBCOMMAND_RE.match(tok)
181
+
182
+
183
+ def extract_path_from_uip_line(content):
184
+ """Tokenize a uip line and walk to extract the command path.
185
+
186
+ Returns the path list (possibly empty for bare `uip`).
187
+ Returns None if the line doesn't start with `uip`.
188
+ """
189
+ if content.startswith("$ "):
190
+ content = content[2:]
191
+ if not (content.startswith("uip ") or content.rstrip() == "uip"):
192
+ return None
193
+ tokens = content.split()
194
+ path = []
195
+ for tok in tokens[1:]:
196
+ if is_terminator(tok):
197
+ break
198
+ path.append(tok)
199
+ return path
200
+
201
+
202
+ def extract_uip_commands(md_path):
203
+ try:
204
+ text = md_path.read_text(encoding="utf-8")
205
+ except Exception:
206
+ return
207
+ lines = text.splitlines()
208
+ in_fence = False
209
+ fence_lang = ""
210
+ i = 0
211
+ while i < len(lines):
212
+ line = lines[i]
213
+ m = FENCE_RE.match(line.strip())
214
+ if m:
215
+ if not in_fence:
216
+ in_fence = True
217
+ fence_lang = m.group(1).lower()
218
+ else:
219
+ in_fence = False
220
+ fence_lang = ""
221
+ i += 1
222
+ continue
223
+ if SKIP_MARKER in line:
224
+ i += 1
225
+ continue
226
+ if in_fence:
227
+ if fence_lang in ACCEPTED_LANGS:
228
+ start = i
229
+ joined = line
230
+ while joined.rstrip().endswith("\\") and i + 1 < len(lines):
231
+ joined = joined.rstrip()[:-1] + " " + lines[i + 1]
232
+ i += 1
233
+ path = extract_path_from_uip_line(joined.lstrip())
234
+ if path:
235
+ yield (start + 1, path)
236
+ else:
237
+ # Inline backtick spans outside fenced blocks.
238
+ for match in INLINE_RE.finditer(line):
239
+ path = extract_path_from_uip_line(match.group(1).strip())
240
+ if path:
241
+ yield (i + 1, path)
242
+ i += 1
243
+
244
+
245
+ references = {}
246
+ for md in files:
247
+ for line_no, path in extract_uip_commands(md):
248
+ references.setdefault(tuple(path), []).append((md, line_no))
249
+
250
+ unknown = 0
251
+ for path_tuple, locs in sorted(references.items()):
252
+ ok, bad, suggestions = verify_path(list(path_tuple))
253
+ if ok:
254
+ continue
255
+ idx = list(path_tuple).index(bad) if bad in path_tuple else 0
256
+ parent = "uip" + ("" if idx == 0 else " " + " ".join(path_tuple[:idx]))
257
+ cmd_str = "uip " + " ".join(path_tuple)
258
+ sug = f" (did you mean: {', '.join(suggestions)}?)" if suggestions else ""
259
+ for f, ln in locs:
260
+ try:
261
+ rel = f.relative_to(SKILL_ROOT).as_posix()
262
+ except ValueError:
263
+ rel = str(f)
264
+ print(f'BAD {rel}:{ln} {cmd_str} — "{bad}" not a subcommand of "{parent}"{sug}')
265
+ unknown += 1
266
+
267
+ print()
268
+ print(f"commands_checked={len(references)} unknown={unknown}")
269
+ sys.exit(1 if unknown else 0)
270
+ PYEOF
@@ -0,0 +1,160 @@
1
+ #!/bin/bash
2
+ # Verify this skill never pins a .flow version as authoritative in prose, and
3
+ # never hardcodes the top-level .flow `version` literal.
4
+ # Usage: bash .maintenance/check-versions.sh [file1.md ...]
5
+ # Output: BAD lines per violation, then "lines_checked=N violations=M" summary.
6
+ #
7
+ # Rationale: the .flow top-level `version` and node `typeVersion` are owned by
8
+ # `uip maestro flow init` / `uip maestro flow registry get`. Hardcoding them in
9
+ # docs rots silently when the CLI/registry advances (e.g. core.action.http.v2
10
+ # 2.0 -> 2.1, core.trigger.scheduled 1.0 -> 1.1, top-level 1.1 -> 1.2). The rule
11
+ # is: reference the live command, never pin the number as "current"/"required".
12
+ #
13
+ # Two violation classes (both high-confidence — chosen to NOT re-flag the many
14
+ # legitimate illustrative `"typeVersion": "1.0"` JSON examples that are governed
15
+ # by an adjacent registry-sourcing note):
16
+ #
17
+ # 1. PROSE-PIN — prose that states a version as current or mandatory, e.g.
18
+ # `currently "1.1"`, `the registry currently emits "1.0"`, `must be "2.0"`,
19
+ # `use version "1.0"`. These claims go stale.
20
+ # 2. TOPLEVEL — a hardcoded top-level `.flow` `"version": "x.y"` literal.
21
+ # Top-level version must always be the `uip maestro flow init` placeholder
22
+ # (e.g. `"<version from \`uip maestro flow init\`>"`), never a number.
23
+ #
24
+ # Explicitly NOT flagged:
25
+ # - `"typeVersion": "x.y"` literals in node JSON examples (legitimate when
26
+ # paired with a sourcing note; too many true-illustrative cases to flag).
27
+ # - `bindings_v2.json` `"version": "2.0"` — a fixed schema constant, not a
28
+ # .flow version. Distinguished by the surrounding `"resources"` key.
29
+ #
30
+ # Skipping: add `<!-- version-check-skip -->` anywhere on a line to suppress it
31
+ # (e.g. a historical/version-comparison note that documents an old literal on
32
+ # purpose). For table rows, place the marker inside a cell.
33
+ #
34
+ # Scans SKILL.md + references/**/*.md. Skips .maintenance/ and root scratch
35
+ # files (PLAN.md, PR_BODY.md). Exits non-zero if any violation is found.
36
+
37
+ set -e
38
+
39
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
40
+ cd "$ROOT" || exit 1
41
+
42
+ if ! command -v python3 >/dev/null 2>&1; then
43
+ echo "python3 not found on PATH" >&2
44
+ exit 2
45
+ fi
46
+
47
+ FILES=("$@")
48
+ if [ "${#FILES[@]}" -eq 0 ]; then
49
+ while IFS= read -r f; do
50
+ FILES+=("$f")
51
+ done < <({ [ -f SKILL.md ] && echo "./SKILL.md"; /usr/bin/find ./references -type f -name '*.md' 2>/dev/null; } | /usr/bin/sort)
52
+ fi
53
+
54
+ if [ "${#FILES[@]}" -eq 0 ]; then
55
+ echo ""
56
+ echo "lines_checked=0 violations=0"
57
+ exit 0
58
+ fi
59
+
60
+ python3 - "${FILES[@]}" <<'PY'
61
+ import re, sys
62
+
63
+ files = sys.argv[1:]
64
+
65
+ SKIP_MARKER = "<!-- version-check-skip -->"
66
+
67
+ # A quoted version literal: "1.0", "1.1", "2.0", "1.0.0", etc.
68
+ VER = r'"\d+\.\d+(?:\.\d+)?"'
69
+
70
+ # Class 1 — PROSE-PIN: a version literal stated as current / mandatory.
71
+ # Two sub-patterns (note: docs wrap versions in backticks, e.g. `"1.1"`, so the
72
+ # gap class must NOT exclude backticks):
73
+ # (a) a pinning verb followed within a short window by a version literal —
74
+ # `currently "1.1"`, `the registry currently emits "1.0"`, `must be "2.0"`.
75
+ # (b) an inline assignment of a version field to a literal in prose —
76
+ # `typeVersion: "2.0"`, `version: "1.1"` (the original http/impl.md:27 bug
77
+ # had no pin-verb — it just stated `typeVersion: "2.0"`).
78
+ PROSE_PIN_VERB = re.compile(
79
+ r'(currently|current\b|must be|use version|emits|emit|is currently|as of)'
80
+ r'[^\n]{0,40}?' + VER,
81
+ re.IGNORECASE,
82
+ )
83
+ PROSE_PIN_ASSIGN = re.compile(
84
+ r'(typeVersion|version)\s*[:=]\s*' + VER,
85
+ re.IGNORECASE,
86
+ )
87
+
88
+ def prose_pin(line):
89
+ return PROSE_PIN_VERB.search(line) or PROSE_PIN_ASSIGN.search(line)
90
+
91
+ # Class 2 — TOPLEVEL: a hardcoded top-level `.flow` `"version": "x.y"`.
92
+ # Only the .flow document's OWN top-level version is in scope — NOT
93
+ # `definitions[].version` (node manifest versions), NOT eval-file `version`,
94
+ # NOT `bindings_v2.json` `version`, NOT `connectorDetail.configuration.version`.
95
+ # We identify a true top-level .flow version by its sibling keys: a real .flow
96
+ # object has `"nodes"` and `"edges"` (and usually `"name"`) within a few lines.
97
+ # Definitions entries instead carry `"nodeType"`; bindings_v2 carries
98
+ # `"resources"`; eval files carry `"evaluatorRefs"` / `"evaluatorTypeId"` /
99
+ # `"evaluations"`. Presence of any of those disqualifies the match.
100
+ TOPLEVEL = re.compile(r'"version"\s*:\s*' + VER)
101
+
102
+ _FLOW_SIBLINGS = ('"nodes"', '"edges"')
103
+ _DISQUALIFY = ('"nodeType"', '"resources"', '"evaluatorRefs"',
104
+ '"evaluatorTypeId"', '"evaluations"', '"connectorDetail"')
105
+
106
+ def is_flow_toplevel_version(lines, idx):
107
+ # Look at a window around the `"version"` line for the discriminating keys,
108
+ # bounded to the current fenced block so it never bleeds into an adjacent
109
+ # JSON example (e.g. a following `definitions` entry with `"nodeType"`).
110
+ lo = idx - 1
111
+ while lo >= 0 and not lines[lo].strip().startswith("```"):
112
+ lo -= 1
113
+ lo += 1
114
+ hi = idx + 1
115
+ while hi < len(lines) and not lines[hi].strip().startswith("```"):
116
+ hi += 1
117
+ window = "\n".join(lines[lo:hi])
118
+ if any(k in window for k in _DISQUALIFY):
119
+ return False
120
+ return all(k in window for k in _FLOW_SIBLINGS)
121
+
122
+ lines_checked = 0
123
+ violations = 0
124
+
125
+ for path in files:
126
+ try:
127
+ with open(path, encoding="utf-8") as fh:
128
+ lines = fh.read().splitlines()
129
+ except OSError:
130
+ continue
131
+
132
+ in_fence = False
133
+ for i, line in enumerate(lines):
134
+ stripped = line.strip()
135
+ # Track fenced code blocks so PROSE-PIN only fires on real prose.
136
+ if stripped.startswith("```"):
137
+ in_fence = not in_fence
138
+ continue
139
+ lines_checked += 1
140
+ if SKIP_MARKER in line:
141
+ continue
142
+
143
+ # Class 1: prose only (outside fences).
144
+ if not in_fence and prose_pin(line):
145
+ print(f"BAD {path}:{i+1} PROSE-PIN — version stated as current/required; reference `registry get`/`flow init` instead")
146
+ print(f" {stripped[:140]}")
147
+ violations += 1
148
+ continue
149
+
150
+ # Class 2: top-level `.flow` "version" literal — JSON examples only,
151
+ # and only when the surrounding object is a genuine .flow document.
152
+ if in_fence and TOPLEVEL.search(line) and is_flow_toplevel_version(lines, i):
153
+ print(f"BAD {path}:{i+1} TOPLEVEL — hardcoded top-level `.flow` `version` literal; use the `uip maestro flow init` placeholder")
154
+ print(f" {stripped[:140]}")
155
+ violations += 1
156
+
157
+ print()
158
+ print(f"lines_checked={lines_checked} violations={violations}")
159
+ sys.exit(1 if violations else 0)
160
+ PY