vortexa-claude-skills 1.0.0
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.
- package/CHANGELOG.md +28 -0
- package/VERSION +1 -0
- package/bin/.gitkeep +0 -0
- package/bin/setup.js +302 -0
- package/commands/vortexa/_check-setup.md +9 -0
- package/commands/vortexa/_skill-template.md +100 -0
- package/commands/vortexa/breakdown.md +294 -0
- package/commands/vortexa/cargo-flows.md +247 -0
- package/commands/vortexa/compare.md +315 -0
- package/commands/vortexa/custom.md +214 -0
- package/commands/vortexa/explain.md +124 -0
- package/commands/vortexa/init.md +133 -0
- package/commands/vortexa/oow.md +189 -0
- package/commands/vortexa/seasonal.md +185 -0
- package/commands/vortexa/voyages.md +285 -0
- package/context/.gitkeep +0 -0
- package/context/cargo-movements.md +738 -0
- package/context/date-units.md +188 -0
- package/context/endpoint-template.md +176 -0
- package/context/entity-resolution.md +217 -0
- package/context/guardrails.md +161 -0
- package/context/reference-endpoints.md +651 -0
- package/context/voyages.md +636 -0
- package/lib/__init__.py +4 -0
- package/lib/aliases.json +52 -0
- package/lib/api.py +20 -0
- package/lib/entities.py +254 -0
- package/lib/inventory.py +140 -0
- package/lib/movements.py +242 -0
- package/lib/requirements.txt +6 -0
- package/lib/seasonal.py +200 -0
- package/lib/timeseries.py +271 -0
- package/lib/utils.py +120 -0
- package/lib/vessels.py +192 -0
- package/lib/visualization.py +164 -0
- package/lib/voyages.py +236 -0
- package/package.json +28 -0
- package/templates/.env.template +3 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vortexa:compare
|
|
3
|
+
description: "Compare cargo flows period-over-period or region-over-region with overlay charts and metrics"
|
|
4
|
+
argument-hint: "compare crude exports from Saudi Arabia 2025 vs 2024, monthly"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Edit
|
|
8
|
+
- Write
|
|
9
|
+
- Bash
|
|
10
|
+
- Glob
|
|
11
|
+
- Grep
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<objective>
|
|
15
|
+
Run comparison analytics on cargo flows -- either period-over-period (e.g., 2025 vs 2024) or region-over-region (e.g., Europe vs Asia imports). Produces overlay line charts with computed metrics (absolute change, percentage change, averages, totals). Uses CargoTimeSeries for data and `comparison_overlay_chart()` from lib/visualization.py.
|
|
16
|
+
</objective>
|
|
17
|
+
|
|
18
|
+
<execution_context>
|
|
19
|
+
## Pre-loaded Context (via CLAUDE.md @imports)
|
|
20
|
+
The following are automatically available -- do NOT re-read them:
|
|
21
|
+
- context/guardrails.md -- NEVER/ALWAYS rules for all Vortexa API calls
|
|
22
|
+
- context/entity-resolution.md -- How to resolve entity names to hex IDs
|
|
23
|
+
- context/date-units.md -- Date parsing rules and unit defaults
|
|
24
|
+
|
|
25
|
+
## Required Context (Read on demand)
|
|
26
|
+
Read before processing the user's query:
|
|
27
|
+
- context/cargo-movements.md -- Full CTS parameters, activity filters, timeseries_property values
|
|
28
|
+
</execution_context>
|
|
29
|
+
|
|
30
|
+
## Setup Check
|
|
31
|
+
@commands/vortexa/_check-setup.md
|
|
32
|
+
|
|
33
|
+
<process>
|
|
34
|
+
|
|
35
|
+
## Step 1: Read Endpoint Context
|
|
36
|
+
|
|
37
|
+
Read `context/cargo-movements.md` for CTS parameters, activity filter rules, and frequency options.
|
|
38
|
+
|
|
39
|
+
## Step 2: Parse the Query and Determine Mode
|
|
40
|
+
|
|
41
|
+
Analyze $ARGUMENTS using signal word routing to determine the comparison mode:
|
|
42
|
+
|
|
43
|
+
### Signal Word Routing
|
|
44
|
+
|
|
45
|
+
**Period mode** -- year or time-based comparison:
|
|
46
|
+
- Year references: 2025, 2024, "last year", "this year", "vs 2023"
|
|
47
|
+
- Explicit period phrases: "year over year", "YoY", "month over month", "MoM", "QoQ", "quarter over quarter"
|
|
48
|
+
- Multiple date ranges: "Q1 2025 vs Q1 2024", "Jan-Jun 2025 vs Jan-Jun 2024"
|
|
49
|
+
|
|
50
|
+
**Region mode** -- geographic comparison:
|
|
51
|
+
- Geographic references used as comparison items: "Europe vs Asia", "Middle East vs West Africa"
|
|
52
|
+
- Multiple origins or destinations being compared: "Saudi vs Iraq exports", "China vs India imports"
|
|
53
|
+
|
|
54
|
+
**Both present** -- ambiguous, ask:
|
|
55
|
+
"I see both year and region references. Are you comparing time periods or geographies?"
|
|
56
|
+
|
|
57
|
+
**Neither clear** -- ask:
|
|
58
|
+
"What would you like to compare? Time periods (e.g., 2025 vs 2024) or regions (e.g., Europe vs Asia)?"
|
|
59
|
+
|
|
60
|
+
### Extract Parameters
|
|
61
|
+
|
|
62
|
+
- **Comparison items**: 2-5 items. If more than 5: "That's a lot of comparisons. Try /vortexa:breakdown for dimension analysis instead."
|
|
63
|
+
- **Product**: commodity (crude, LNG, etc.)
|
|
64
|
+
- **Activity**: same rules as cargo-flows (exports=loading_end, imports=unloading_start, etc.)
|
|
65
|
+
- **Base query parameters**: origin, destination, time range, unit, frequency
|
|
66
|
+
|
|
67
|
+
**For period mode:**
|
|
68
|
+
- Each comparison item is a time period (year, quarter, month range)
|
|
69
|
+
- Normalize x-axis to common reference: month names (Jan, Feb, ...) for year comparisons, week numbers for quarter comparisons
|
|
70
|
+
- Default frequency: monthly for year comparisons, weekly for quarter comparisons, daily for month comparisons
|
|
71
|
+
|
|
72
|
+
**For region mode:**
|
|
73
|
+
- Each comparison item is a geography (country, region, shipping region)
|
|
74
|
+
- Use the same time range for all items
|
|
75
|
+
- x-axis is the shared date range (no normalization needed)
|
|
76
|
+
|
|
77
|
+
## Step 3: Check for Missing Parameters
|
|
78
|
+
|
|
79
|
+
Ask targeted questions BEFORE the confirmation step. Never default silently.
|
|
80
|
+
|
|
81
|
+
**Required (ask if missing):**
|
|
82
|
+
- **Comparison items** -- MUST have at least 2 items. Ask: "What periods/regions are you comparing?"
|
|
83
|
+
- **Product** -- MUST be specified. Ask if missing.
|
|
84
|
+
- **Activity** -- MUST be specified. If direction ambiguous, ask: "exports from origin or imports to destination?"
|
|
85
|
+
|
|
86
|
+
**Mode-specific required:**
|
|
87
|
+
- **Period mode**: frequency (default monthly for year comparisons, but confirm)
|
|
88
|
+
- **Region mode**: time range (MUST be specified)
|
|
89
|
+
|
|
90
|
+
**Ask if not specified:**
|
|
91
|
+
- **Unit** -- Apply commodity defaults (oil=bpd, LNG=t, LPG=t). Ask if ambiguous.
|
|
92
|
+
- **Geography filters** -- optional but commonly specified (e.g., "from Saudi Arabia" applies to all periods)
|
|
93
|
+
|
|
94
|
+
Ask one parameter at a time. Do NOT ask all missing params in a bulk dump.
|
|
95
|
+
|
|
96
|
+
## Step 4: Resolve Entity IDs
|
|
97
|
+
|
|
98
|
+
For each entity mentioned (product, geography filters, region comparison items):
|
|
99
|
+
1. Check `lib/aliases.json` for common shorthands (ME, AG, USG, ARA, etc.)
|
|
100
|
+
2. Call `lib/entities.py` resolve functions with the correct entity type and layer:
|
|
101
|
+
- `resolve_geography(term, layer)` for origins/destinations and region comparison items
|
|
102
|
+
- `resolve_product(term, layer)` for products
|
|
103
|
+
- `resolve(term, entity_type, layer, cache)` for the unified resolver with caching
|
|
104
|
+
3. If multiple matches: present top 3 candidates. Ask user to pick. NEVER auto-correct.
|
|
105
|
+
4. If zero matches: tell user the term wasn't found, suggest checking spelling or trying a broader term.
|
|
106
|
+
|
|
107
|
+
Use `EntityCache()` from `lib/entities.py` for the session to avoid re-resolving the same entities.
|
|
108
|
+
|
|
109
|
+
## Step 5: Confirm Before Executing (MANDATORY)
|
|
110
|
+
|
|
111
|
+
**Period mode confirmation:**
|
|
112
|
+
```
|
|
113
|
+
Query: [restate]
|
|
114
|
+
Analysis: Period comparison
|
|
115
|
+
Endpoint: CargoTimeSeries
|
|
116
|
+
Comparing: [period1] vs [period2] (vs ...)
|
|
117
|
+
Activity: [filter_activity] ([user's term])
|
|
118
|
+
Origin: [name (layer)] or "not specified"
|
|
119
|
+
Destination: [name (layer)] or "not specified"
|
|
120
|
+
Product: [name (layer)]
|
|
121
|
+
Unit: [unit] ([reason])
|
|
122
|
+
Frequency: [value]
|
|
123
|
+
Chart: Overlay lines + difference table
|
|
124
|
+
|
|
125
|
+
Confirm or adjust?
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Region mode confirmation:**
|
|
129
|
+
```
|
|
130
|
+
Query: [restate]
|
|
131
|
+
Analysis: Region comparison
|
|
132
|
+
Endpoint: CargoTimeSeries
|
|
133
|
+
Comparing: [region1] vs [region2] (vs ...)
|
|
134
|
+
Activity: [filter_activity] ([user's term])
|
|
135
|
+
Product: [name (layer)]
|
|
136
|
+
Time: [start] -> [end]
|
|
137
|
+
Unit: [unit] ([reason])
|
|
138
|
+
Frequency: [value]
|
|
139
|
+
Chart: Overlay lines + metrics table
|
|
140
|
+
|
|
141
|
+
Confirm or adjust?
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
NEVER execute without confirmation. Wait for user response.
|
|
145
|
+
|
|
146
|
+
## Step 6: Generate & Execute Code Artifact
|
|
147
|
+
|
|
148
|
+
### Period Mode Code
|
|
149
|
+
|
|
150
|
+
Generate code that:
|
|
151
|
+
1. Runs a separate CTS query per period using `CargoTimeSeries` directly (no split needed)
|
|
152
|
+
2. Normalizes x-axis: for year comparisons, map dates to month labels (Jan, Feb, ...) so lines overlay correctly
|
|
153
|
+
3. Builds `series_dict` mapping period names to value lists
|
|
154
|
+
4. Computes metrics inline (see metrics section below)
|
|
155
|
+
5. Calls `comparison_overlay_chart(series_dict, x_labels, title, y_label)`
|
|
156
|
+
6. Prints metrics table and saves chart
|
|
157
|
+
|
|
158
|
+
### Region Mode Code
|
|
159
|
+
|
|
160
|
+
Generate code that:
|
|
161
|
+
1. Runs a separate CTS query per region (filtering by the region geography) with same time range
|
|
162
|
+
2. x-axis is the shared date range (no normalization needed)
|
|
163
|
+
3. Builds `series_dict` mapping region names to value lists
|
|
164
|
+
4. Same metrics computation and chart generation
|
|
165
|
+
|
|
166
|
+
### Metrics Computation
|
|
167
|
+
|
|
168
|
+
Compute comparison metrics inline in generated code (NOT a lib/ function -- keep it clean with a small inline helper):
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
# Compute comparison metrics
|
|
172
|
+
metrics = {}
|
|
173
|
+
for name, values in series_dict.items():
|
|
174
|
+
metrics[name] = {
|
|
175
|
+
"Total": sum(v for v in values if v),
|
|
176
|
+
"Average": sum(v for v in values if v) / len([v for v in values if v]) if any(values) else 0,
|
|
177
|
+
}
|
|
178
|
+
# Difference table (pairwise from first comparison item)
|
|
179
|
+
base = list(series_dict.keys())[0]
|
|
180
|
+
for name in list(series_dict.keys())[1:]:
|
|
181
|
+
diff = metrics[name]["Total"] - metrics[base]["Total"]
|
|
182
|
+
pct = (diff / metrics[base]["Total"] * 100) if metrics[base]["Total"] else 0
|
|
183
|
+
print(f"{name} vs {base}: {diff:+,.0f} ({pct:+.1f}%)")
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Code Artifact Template
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
"""Vortexa Compare: {description}
|
|
190
|
+
Generated by /vortexa:compare
|
|
191
|
+
Date: {date}
|
|
192
|
+
"""
|
|
193
|
+
from datetime import datetime
|
|
194
|
+
import os
|
|
195
|
+
import sys; sys.path.insert(0, "lib")
|
|
196
|
+
from entities import resolve_geography, resolve_product, EntityCache
|
|
197
|
+
from visualization import comparison_overlay_chart
|
|
198
|
+
|
|
199
|
+
cache = EntityCache()
|
|
200
|
+
{entity_resolution}
|
|
201
|
+
|
|
202
|
+
# Query each comparison item
|
|
203
|
+
from vortexasdk import CargoTimeSeries
|
|
204
|
+
series_dict = {}
|
|
205
|
+
{per_item_queries}
|
|
206
|
+
|
|
207
|
+
# X-axis labels
|
|
208
|
+
x_labels = {x_labels}
|
|
209
|
+
|
|
210
|
+
# Metrics
|
|
211
|
+
{metrics_computation}
|
|
212
|
+
|
|
213
|
+
# Chart
|
|
214
|
+
fig = comparison_overlay_chart(series_dict, x_labels=x_labels, title="{title}", y_label="{unit_label}")
|
|
215
|
+
|
|
216
|
+
os.makedirs("output", exist_ok=True)
|
|
217
|
+
filepath = f"output/{slug}_compare_{datetime.now().strftime('%Y-%m-%d')}.html"
|
|
218
|
+
fig.write_html(filepath, auto_open=True)
|
|
219
|
+
print(f"Chart saved: {filepath}")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Period mode per-item query pattern:**
|
|
223
|
+
```python
|
|
224
|
+
# Example: 2025 vs 2024
|
|
225
|
+
for year in [2025, 2024]:
|
|
226
|
+
df = CargoTimeSeries().search(
|
|
227
|
+
filter_activity=...,
|
|
228
|
+
filter_time_min=datetime(year, 1, 1),
|
|
229
|
+
filter_time_max=datetime(year, 12, 31, 23, 59, 59),
|
|
230
|
+
filter_products=[product_id],
|
|
231
|
+
filter_origins=[...], # if specified
|
|
232
|
+
filter_destinations=[...], # if specified
|
|
233
|
+
timeseries_unit=...,
|
|
234
|
+
timeseries_frequency=...,
|
|
235
|
+
).to_df()
|
|
236
|
+
series_dict[str(year)] = df["value"].tolist()
|
|
237
|
+
|
|
238
|
+
x_labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
239
|
+
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Region mode per-item query pattern:**
|
|
243
|
+
```python
|
|
244
|
+
# Example: Europe vs Asia
|
|
245
|
+
for region_name, region_id in [("Europe", europe_id), ("Asia", asia_id)]:
|
|
246
|
+
df = CargoTimeSeries().search(
|
|
247
|
+
filter_activity=...,
|
|
248
|
+
filter_time_min=...,
|
|
249
|
+
filter_time_max=...,
|
|
250
|
+
filter_products=[product_id],
|
|
251
|
+
filter_destinations=[region_id], # or filter_origins depending on activity
|
|
252
|
+
timeseries_unit=...,
|
|
253
|
+
timeseries_frequency=...,
|
|
254
|
+
).to_df()
|
|
255
|
+
series_dict[region_name] = df["value"].tolist()
|
|
256
|
+
|
|
257
|
+
x_labels = df["key"].tolist() # shared date buckets
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
After generating:
|
|
261
|
+
- Ask user: "Save as new file, or add to an existing notebook/script?" Default: new file.
|
|
262
|
+
- If new file: create `vortexa_compare_{slug}.py` in project directory.
|
|
263
|
+
- Run the generated code to get results.
|
|
264
|
+
|
|
265
|
+
## Step 7: Present Results
|
|
266
|
+
|
|
267
|
+
- Show metrics summary table:
|
|
268
|
+
- Total and Average per comparison item
|
|
269
|
+
- Absolute change and percentage change (pairwise from first item)
|
|
270
|
+
- Show overlay chart HTML path: "Chart saved: output/{slug}_compare_{date}.html"
|
|
271
|
+
- Methodology footnote using confirmed parameters:
|
|
272
|
+
```
|
|
273
|
+
Methodology: CargoTimeSeries (comparison) | {mode} | {items} | {activity} | {filters} | {frequency} | {unit}
|
|
274
|
+
```
|
|
275
|
+
Example: `Methodology: CargoTimeSeries (comparison) | period | 2025 vs 2024 | loading_end | filter_origins=[Saudi Arabia] | monthly | bpd`
|
|
276
|
+
- Offer: "Export to CSV?" and "Want a detailed summary?"
|
|
277
|
+
|
|
278
|
+
## Step 8: Summary (if triggered)
|
|
279
|
+
|
|
280
|
+
**Smart trigger:** If the user's query contains "analyze", "summarize", "explain results", "what does this show", or "key findings" -- generate the summary automatically.
|
|
281
|
+
|
|
282
|
+
**Post-query offer:** After showing results, always offer: "Want a detailed summary?"
|
|
283
|
+
|
|
284
|
+
**Summary content** -- comparison-specific insights:
|
|
285
|
+
- Which comparison item has the highest total volume
|
|
286
|
+
- Growth/decline trends: percentage change between items
|
|
287
|
+
- Notable crossover points: where one item overtakes another on the chart
|
|
288
|
+
- Seasonal patterns: months where differences are largest/smallest
|
|
289
|
+
- Peak and trough identification per item
|
|
290
|
+
|
|
291
|
+
**Brief summary (default):** 3-5 bullet points with specific numbers.
|
|
292
|
+
|
|
293
|
+
**Extended summary (if user requests "detailed summary" or "full analysis"):**
|
|
294
|
+
- 100-200 word narrative in market commentary style
|
|
295
|
+
- Covers all the above plus broader context
|
|
296
|
+
|
|
297
|
+
After showing the summary, offer: "Save this summary to a .md file?"
|
|
298
|
+
If yes: create `output/{description}_summary_{date}.md`
|
|
299
|
+
|
|
300
|
+
## Error Handling
|
|
301
|
+
|
|
302
|
+
Report immediately in plain English, no auto-retry:
|
|
303
|
+
|
|
304
|
+
- **401 Unauthorized**: "API key is invalid or expired. Run /vortexa:init to check your setup."
|
|
305
|
+
- **500 Server Error**: "Vortexa API returned a server error. Try again in a few minutes."
|
|
306
|
+
- **Timeout**: "Query timed out. Try narrowing the date range or reducing filters."
|
|
307
|
+
- **Empty results**: "No data found for this query. Check that the entity names, date range, and filters are correct."
|
|
308
|
+
- **Entity not found**: "The term '{term}' returned no matches. Check spelling or try a broader term."
|
|
309
|
+
- **Multiple entity matches**: "{n} matches found for '{term}': [list]. Which did you mean?"
|
|
310
|
+
- **Too many items**: "More than 5 comparison items requested. Try /vortexa:breakdown for dimension analysis instead."
|
|
311
|
+
- **Mismatched data lengths**: "The comparison periods returned different numbers of data points. Check that all periods have complete data coverage."
|
|
312
|
+
|
|
313
|
+
Never auto-retry. Never self-correct. Report the error and let the user decide.
|
|
314
|
+
|
|
315
|
+
</process>
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vortexa:custom
|
|
3
|
+
description: "Run any Vortexa API query or improve existing Vortexa Python code"
|
|
4
|
+
argument-hint: "Average waiting time at Fujairah for VLCCs"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Edit
|
|
8
|
+
- Write
|
|
9
|
+
- Bash
|
|
10
|
+
- Glob
|
|
11
|
+
- Grep
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<objective>
|
|
15
|
+
Handle any Vortexa API query by loading all endpoint context docs and writing custom SDK code. Also read, validate, fix, or extend existing user Vortexa Python code. This is the open-ended skill for queries that don't fit the focused /vortexa:cargo-flows or /vortexa:voyages workflows.
|
|
16
|
+
</objective>
|
|
17
|
+
|
|
18
|
+
<execution_context>
|
|
19
|
+
## Pre-loaded Context (via CLAUDE.md @imports)
|
|
20
|
+
The following are automatically available -- do NOT re-read them:
|
|
21
|
+
- context/guardrails.md -- NEVER/ALWAYS rules for all Vortexa API calls
|
|
22
|
+
- context/entity-resolution.md -- How to resolve entity names to hex IDs
|
|
23
|
+
- context/date-units.md -- Date parsing rules and unit defaults
|
|
24
|
+
|
|
25
|
+
## Required Context (Read ALL on demand)
|
|
26
|
+
Read all three endpoint context docs before processing -- the custom skill needs the full API surface:
|
|
27
|
+
- context/cargo-movements.md -- CTS/CM parameters, activity filters, column names
|
|
28
|
+
- context/voyages.md -- VSE/VTS parameters, voyage definitions, V1/V2 differences
|
|
29
|
+
- context/reference-endpoints.md -- Entity lookups, product hierarchy, geography layers
|
|
30
|
+
</execution_context>
|
|
31
|
+
|
|
32
|
+
## Setup Check
|
|
33
|
+
@commands/vortexa/_check-setup.md
|
|
34
|
+
|
|
35
|
+
<process>
|
|
36
|
+
|
|
37
|
+
## Step 1: Read ALL Endpoint Context
|
|
38
|
+
|
|
39
|
+
Read all three endpoint context docs:
|
|
40
|
+
- `context/cargo-movements.md`
|
|
41
|
+
- `context/voyages.md`
|
|
42
|
+
- `context/reference-endpoints.md`
|
|
43
|
+
|
|
44
|
+
The custom skill operates across the full API surface. All three docs are needed regardless of query type.
|
|
45
|
+
|
|
46
|
+
## Step 2: Determine Intent
|
|
47
|
+
|
|
48
|
+
Analyze $ARGUMENTS to classify the request:
|
|
49
|
+
|
|
50
|
+
**A. New data query** -- user wants data the API can provide
|
|
51
|
+
- Could involve any endpoint: CTS, CM, VSE, VTS, Congestion, Reference
|
|
52
|
+
- Could combine multiple endpoints in a single query (e.g., CM + VSE for OOW enrichment)
|
|
53
|
+
- Proceed to Steps 3-9 (standard query workflow)
|
|
54
|
+
|
|
55
|
+
**B. Code improvement** -- user references existing code
|
|
56
|
+
- User mentions a .py file, notebook, or pastes code
|
|
57
|
+
- Read the referenced file(s) first
|
|
58
|
+
- Use context docs to validate, fix, or extend the code
|
|
59
|
+
- Check for common mistakes against guardrails.md rules (wrong activity filter, missing entity resolution, midnight end dates, deprecated oil_on_water_state, etc.)
|
|
60
|
+
- Explain what was wrong and why the fix is correct, citing specific guardrails rules
|
|
61
|
+
- Skip the confirmation step (user already has code)
|
|
62
|
+
|
|
63
|
+
**C. Redirect** -- query fits a focused skill better
|
|
64
|
+
- Straightforward CTS/CM query: suggest "This looks like a cargo flow query -- try `/vortexa:cargo-flows {query}` for a more focused workflow."
|
|
65
|
+
- Straightforward VSE/VTS query: suggest "This looks like a voyage query -- try `/vortexa:voyages {query}` for a more focused workflow."
|
|
66
|
+
- Still process the query if the user insists or if the query combines multiple endpoints
|
|
67
|
+
|
|
68
|
+
## Step 3: Parse the Query (New Data Queries)
|
|
69
|
+
|
|
70
|
+
Extract all relevant parameters from the natural language query:
|
|
71
|
+
- **Endpoint(s)**: Which API endpoint(s) are needed? May be multiple.
|
|
72
|
+
- **Product**: What commodity?
|
|
73
|
+
- **Geography**: Origins, destinations, storage locations -- what layers?
|
|
74
|
+
- **Activity**: What movement stage? (exports=loading_end, imports=unloading_start, etc.)
|
|
75
|
+
- **Vessel filters**: Class, flag, DWT, IMO, age, scrubber status
|
|
76
|
+
- **Corporate filters**: Owner, charterer, time charterer
|
|
77
|
+
- **Time range**: Apply date-units.md calendar/trailing convention
|
|
78
|
+
- **Unit**: Apply commodity defaults (oil=bpd, LNG=t, LPG=t)
|
|
79
|
+
- **Frequency**: For timeseries queries
|
|
80
|
+
- **Additional**: Intra movements, confidence, STS, waypoints, congestion breakdowns
|
|
81
|
+
|
|
82
|
+
## Step 4: Check for Missing Parameters
|
|
83
|
+
|
|
84
|
+
Same conservative policy as cargo-flows and voyages: always ask, never default silently.
|
|
85
|
+
Ask one parameter at a time. Do NOT bulk-dump all missing params.
|
|
86
|
+
|
|
87
|
+
Required for every query:
|
|
88
|
+
- Time range -- MUST be specified
|
|
89
|
+
- At least one meaningful filter (product, geography, vessel, or corporate)
|
|
90
|
+
|
|
91
|
+
For timeseries: frequency must be specified or asked.
|
|
92
|
+
For search endpoints: set `size=500`.
|
|
93
|
+
|
|
94
|
+
## Step 5: Resolve Entity IDs
|
|
95
|
+
|
|
96
|
+
Same entity resolution workflow as the other skills:
|
|
97
|
+
1. Check `lib/aliases.json` for common shorthands (ME, AG, USG, ARA, etc.)
|
|
98
|
+
2. Call `lib/entities.py` resolve functions: `resolve_geography(term, layer)`, `resolve_product(term, layer)`, `resolve(term, entity_type, layer, cache)`
|
|
99
|
+
3. Multiple matches: present top 3 candidates, ask user to pick. NEVER auto-correct.
|
|
100
|
+
4. Zero matches: tell the user, suggest alternatives.
|
|
101
|
+
5. Use `EntityCache()` for the session to avoid re-resolving.
|
|
102
|
+
|
|
103
|
+
## Step 6: Confirm Before Executing (MANDATORY for new queries)
|
|
104
|
+
|
|
105
|
+
Present the parsed query adapted to the specific endpoint(s):
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
Query: [restate the user's question]
|
|
109
|
+
Endpoint(s): [list all endpoints being used]
|
|
110
|
+
[endpoint-specific parameters -- activity, voyage status, metric, breakdown, etc.]
|
|
111
|
+
Origin: [name (layer)] or "not specified"
|
|
112
|
+
Destination: [name (layer)] or "not specified"
|
|
113
|
+
Product: [name (layer)] or "not specified"
|
|
114
|
+
Time: [start datetime] -> [end datetime] ([interpretation])
|
|
115
|
+
Unit: [unit] ([reason])
|
|
116
|
+
Frequency: [value] (timeseries only)
|
|
117
|
+
Additional: [any other filters]
|
|
118
|
+
|
|
119
|
+
Confirm or adjust?
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
NEVER execute without confirmation. Wait for user response.
|
|
123
|
+
Skip this step ONLY for code improvement (intent B) where the user already has code.
|
|
124
|
+
|
|
125
|
+
## Step 7: Generate & Execute Code Artifact
|
|
126
|
+
|
|
127
|
+
Code is ALWAYS custom SDK code (Mode 2) -- reference the relevant context doc for correct parameter names and syntax.
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
"""Vortexa Query: {description}
|
|
131
|
+
Generated by /vortexa:custom
|
|
132
|
+
Date: {date}
|
|
133
|
+
"""
|
|
134
|
+
from datetime import datetime
|
|
135
|
+
import sys; sys.path.insert(0, "lib")
|
|
136
|
+
from entities import resolve, EntityCache
|
|
137
|
+
|
|
138
|
+
# Custom query -- built from Vortexa API documentation
|
|
139
|
+
cache = EntityCache()
|
|
140
|
+
# {entity resolution}
|
|
141
|
+
# {SDK calls using vortexasdk}
|
|
142
|
+
# {result formatting}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Key rules:
|
|
146
|
+
- Write raw SDK calls using vortexasdk, referencing endpoint context docs for correct syntax
|
|
147
|
+
- Can combine multiple endpoints (e.g., CM + VSE for OOW enrichment, Reference + CTS for entity lookup then query)
|
|
148
|
+
- Use lib/ functions as building blocks where they fit (entity resolution, column rename, timeseries parsing)
|
|
149
|
+
- Add comment: `# Custom query -- built from Vortexa API documentation`
|
|
150
|
+
- Code must be self-contained and re-runnable
|
|
151
|
+
|
|
152
|
+
For code improvement (intent B):
|
|
153
|
+
- Read the user's existing file
|
|
154
|
+
- Identify issues using context docs and guardrails.md
|
|
155
|
+
- Fix or extend in-place, or create a corrected version
|
|
156
|
+
- Explain each change with references to specific guardrails rules
|
|
157
|
+
|
|
158
|
+
Ask user: "Save as new file, or add to existing script/notebook?" Default: new file.
|
|
159
|
+
|
|
160
|
+
## Step 8: Present Results
|
|
161
|
+
|
|
162
|
+
Terminal summary (same pattern as cargo-flows and voyages):
|
|
163
|
+
- Brief natural language description of what was queried
|
|
164
|
+
- Row count and date range covered
|
|
165
|
+
- DataFrame preview with row cap (daily=30, weekly=52, monthly=24, yearly=all)
|
|
166
|
+
- File path to generated code artifact
|
|
167
|
+
- Offer: "Export to CSV?"
|
|
168
|
+
|
|
169
|
+
For code improvement: show a diff summary of what changed and why.
|
|
170
|
+
|
|
171
|
+
After the DataFrame preview and before the export offer, show a one-line methodology footnote using the CONFIRMED parameters from Step 6:
|
|
172
|
+
```
|
|
173
|
+
Methodology: {Endpoint(s)} | {activity} | {key filters} | {frequency} | {unit} | {other relevant params}
|
|
174
|
+
```
|
|
175
|
+
Example: `Methodology: CargoMovements.search | loading_end | filter_origins=[Saudi Arabia] | filter_products=[Crude & Condensates] | size=500`
|
|
176
|
+
|
|
177
|
+
Use human-readable names for entity filters (not hex IDs). Skip for code improvement (intent B).
|
|
178
|
+
|
|
179
|
+
## Step 9: Summary (if triggered)
|
|
180
|
+
|
|
181
|
+
**Smart trigger:** If the user's query contains "analyze", "summarize", "explain results", "what does this show", or "key findings" -- generate the summary automatically.
|
|
182
|
+
|
|
183
|
+
**Post-query offer:** After showing results, always offer: "Want a summary of these results?"
|
|
184
|
+
|
|
185
|
+
**Brief summary (default):**
|
|
186
|
+
Analyze the DataFrame and produce 3-5 bullet points:
|
|
187
|
+
- Top 3-5 contributors by volume with percentages of total
|
|
188
|
+
- Period-over-period change if comparable time periods exist
|
|
189
|
+
- Notable outliers: spikes, drops, record values, trend reversals
|
|
190
|
+
- Each bullet includes specific numbers, not vague descriptions
|
|
191
|
+
|
|
192
|
+
**Extended summary (if user requests "detailed summary" or "full analysis"):**
|
|
193
|
+
- 100-200 word narrative paragraph in market commentary style
|
|
194
|
+
- Includes everything from brief plus trend descriptions and broader context
|
|
195
|
+
|
|
196
|
+
After showing the summary, offer: "Save this summary to a .md file?"
|
|
197
|
+
If yes: create `output/{description}_summary_{date}.md`
|
|
198
|
+
|
|
199
|
+
Skip for code improvement (intent B) -- summaries are for query results, not code reviews.
|
|
200
|
+
|
|
201
|
+
## Error Handling
|
|
202
|
+
|
|
203
|
+
Same patterns as cargo-flows and voyages -- report immediately in plain English, no auto-retry:
|
|
204
|
+
|
|
205
|
+
- **401 Unauthorized**: "API key is invalid or expired. Run /vortexa:init to check your setup."
|
|
206
|
+
- **500 Server Error**: "Vortexa API returned a server error. Try again in a few minutes."
|
|
207
|
+
- **Timeout**: "Query timed out. Try narrowing the date range or reducing filters."
|
|
208
|
+
- **Empty results**: "No data found. Check entity names, date range, and filters."
|
|
209
|
+
- **Entity not found**: "The term '{term}' returned no matches. Check spelling or try a broader term."
|
|
210
|
+
- **Multiple entity matches**: Present top candidates with name, layer, and first 8 chars of ID. Ask user to pick.
|
|
211
|
+
|
|
212
|
+
Never auto-retry. Never self-correct. Report the error and let the user decide.
|
|
213
|
+
|
|
214
|
+
</process>
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vortexa:explain
|
|
3
|
+
description: "Get plain-English explanations of Vortexa data model, filters, entity hierarchies, and methodology"
|
|
4
|
+
argument-hint: "What is loading_end vs loading_state?"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<objective>
|
|
10
|
+
Answer any question about the Vortexa data model, API methodology, entity hierarchies, filter options, activity types, and endpoint behavior using ONLY the information in the context documentation. Support conversational follow-ups for guided exploration.
|
|
11
|
+
|
|
12
|
+
This is a Knowledge Variant skill -- it generates no code, makes no API calls, and produces no DataFrames. It reads documentation and explains concepts.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
<execution_context>
|
|
16
|
+
## Pre-loaded Context (via CLAUDE.md @imports)
|
|
17
|
+
The following are automatically available -- do NOT re-read them:
|
|
18
|
+
- context/guardrails.md -- Activity filters, entity resolution rules, date ranges, API defaults, voyages rules, confirmation step, quick decision table
|
|
19
|
+
- context/entity-resolution.md -- Resolution workflow, SDK methods, geography/product/vessel/corporate hierarchies, disambiguation protocol
|
|
20
|
+
- context/date-units.md -- Calendar vs trailing date parsing, frequency selection, unit defaults by commodity
|
|
21
|
+
|
|
22
|
+
## Required Context (Read on demand)
|
|
23
|
+
Read ALL three endpoint context docs at the start of the conversation:
|
|
24
|
+
- context/cargo-movements.md -- CTS and CM parameters, activity filters, column names, breakdown/split properties, worked examples
|
|
25
|
+
- context/voyages.md -- VSE and VTS parameters, voyage definitions, events, V1/V2 differences, freight metrics
|
|
26
|
+
- context/reference-endpoints.md -- Entity hierarchies, SDK methods, product/geography/vessel/corporate layers, search patterns
|
|
27
|
+
</execution_context>
|
|
28
|
+
|
|
29
|
+
<process>
|
|
30
|
+
|
|
31
|
+
## Step 1: Read All Context Documentation
|
|
32
|
+
|
|
33
|
+
Read all three endpoint context docs:
|
|
34
|
+
- `context/cargo-movements.md`
|
|
35
|
+
- `context/voyages.md`
|
|
36
|
+
- `context/reference-endpoints.md`
|
|
37
|
+
|
|
38
|
+
Combined with the pre-loaded guardrails, entity-resolution, and date-units docs, this gives access to the full Vortexa knowledge base (~4,000 lines across 6 docs). This is a one-time read at the start of the conversation -- no need to re-read for follow-up questions.
|
|
39
|
+
|
|
40
|
+
## Step 2: Identify the Topic
|
|
41
|
+
|
|
42
|
+
Analyze $ARGUMENTS to determine what the user is asking about. Common topic categories:
|
|
43
|
+
|
|
44
|
+
**Entity hierarchies** -- "What products are there?", "How are geographies organized?", "What vessel classes exist?"
|
|
45
|
+
- Answer from: reference-endpoints.md (full hierarchy tables), entity-resolution.md (resolution workflow)
|
|
46
|
+
|
|
47
|
+
**Filter behavior** -- "What is loading_end?", "Difference between loading_state and loading_end?", "When should I use exclude_intra_country?"
|
|
48
|
+
- Answer from: guardrails.md (activity filter table, geography logic table), cargo-movements.md (parameter details)
|
|
49
|
+
|
|
50
|
+
**Activity types** -- "What activities can I filter on?", "What does storing_state mean?", "What's cargo_on_water_state?"
|
|
51
|
+
- Answer from: guardrails.md (activity table with correct/wrong choices), cargo-movements.md (activity definitions)
|
|
52
|
+
|
|
53
|
+
**Methodology** -- "How does CTS differ from CM?", "What's the CM-Authoritative OOW pattern?", "How does quantity_at_time_of work?"
|
|
54
|
+
- Answer from: cargo-movements.md (endpoint comparison, OOW pattern), voyages.md (methodology sections)
|
|
55
|
+
|
|
56
|
+
**API mechanics** -- "V1 vs V2 voyages timeseries?", "What units are available?", "How do date ranges work?"
|
|
57
|
+
- Answer from: voyages.md (V1/V2 differences), date-units.md (units table), guardrails.md (API defaults)
|
|
58
|
+
|
|
59
|
+
**Endpoint guidance** -- "When should I use Voyages vs CargoMovements?", "What is VoyagesSearchEnriched?", "What breakdown properties does CTS support?"
|
|
60
|
+
- Answer from: voyages.md (endpoint selection), cargo-movements.md (split properties), guardrails.md (quick decision table)
|
|
61
|
+
|
|
62
|
+
## Step 3: Search Context Docs and Synthesize Answer
|
|
63
|
+
|
|
64
|
+
Find the relevant information across the loaded context docs and synthesize a plain-English explanation.
|
|
65
|
+
|
|
66
|
+
### Accuracy Constraint
|
|
67
|
+
|
|
68
|
+
**ONLY use information from the context docs.** Do NOT supplement with training knowledge or assumptions about the Vortexa API. If it is not written in the 6 context docs, do not state it as fact. This ensures the explanation matches exactly what the query skills (/vortexa:cargo-flows, /vortexa:voyages, /vortexa:breakdown, /vortexa:custom) actually use.
|
|
69
|
+
|
|
70
|
+
### Synthesis Rules
|
|
71
|
+
|
|
72
|
+
1. **If the topic IS covered:** Explain it clearly using the doc content. Include specific rules, tables, and examples from the docs. Cite which doc the information comes from (e.g., "Per guardrails.md, loading_end is the correct activity for exports").
|
|
73
|
+
|
|
74
|
+
2. **If the topic is NOT covered:** Say "This concept isn't documented in the current context. The context docs cover: entity hierarchies, activity filters, date conventions, cargo movements (CTS/CM), voyages (VSE/VTS), and reference endpoints (products, geographies, vessels, corporations)."
|
|
75
|
+
|
|
76
|
+
3. **If the topic spans multiple docs:** Cross-reference them. For example, "How do I query crude exports?" touches guardrails.md (activity=loading_end), entity-resolution.md (resolve product ID), cargo-movements.md (CTS parameters), and date-units.md (time range format).
|
|
77
|
+
|
|
78
|
+
### Formatting Guidelines
|
|
79
|
+
|
|
80
|
+
- Structure answers with clear headers or bullet points for readability
|
|
81
|
+
- For hierarchy questions, show the hierarchy visually:
|
|
82
|
+
```
|
|
83
|
+
group > group_product > category > grade
|
|
84
|
+
```
|
|
85
|
+
- For "which should I use" questions, reference the decision tables in guardrails.md and the endpoint context docs
|
|
86
|
+
- For filter comparison questions, use side-by-side tables showing the differences
|
|
87
|
+
- For "what options are there" questions, list all options with brief descriptions from the docs
|
|
88
|
+
- For common-mistake questions, highlight the NEVER/ALWAYS rules from guardrails.md
|
|
89
|
+
- Keep explanations concise -- the user can always ask follow-ups for more detail
|
|
90
|
+
|
|
91
|
+
## Step 4: Offer Drill-Down
|
|
92
|
+
|
|
93
|
+
After answering, offer follow-up exploration with 2-3 specific related topics the user might want to explore next:
|
|
94
|
+
|
|
95
|
+
"Want to explore deeper into any of these? For example:
|
|
96
|
+
- [related topic 1 based on what was just explained]
|
|
97
|
+
- [related topic 2 that naturally follows]
|
|
98
|
+
- [related topic 3 for broader context]"
|
|
99
|
+
|
|
100
|
+
### Drill-Down Topic Selection
|
|
101
|
+
|
|
102
|
+
Choose follow-up suggestions that naturally extend the current explanation:
|
|
103
|
+
- If explaining an entity hierarchy -> suggest exploring a specific branch, or how to resolve IDs
|
|
104
|
+
- If explaining a filter -> suggest comparing it with a commonly confused alternative
|
|
105
|
+
- If explaining methodology -> suggest the related endpoint parameters or worked examples
|
|
106
|
+
- If explaining an endpoint -> suggest when to use it vs alternatives, or its key parameters
|
|
107
|
+
|
|
108
|
+
### Example Drill-Down Flows
|
|
109
|
+
|
|
110
|
+
- "What products are there?" -> hierarchy shown -> "Tell me about Clean Products" -> sub-groups listed -> "What's the difference between category and grade?" -> explanation with examples
|
|
111
|
+
- "What activities are there?" -> list with descriptions -> "What's the difference between cargo_on_water_state and storing_state?" -> detailed comparison with use cases
|
|
112
|
+
- "How does entity resolution work?" -> workflow explained -> "Show me the geography layers" -> hierarchy with examples from each layer
|
|
113
|
+
- "When should I use CTS vs CM?" -> decision criteria -> "How does the CM-Authoritative OOW pattern work?" -> step-by-step explanation
|
|
114
|
+
- "What units are available?" -> full unit table -> "What's the default for LNG?" -> commodity defaults explained -> "How do rate units differ from absolute?" -> bpd vs b comparison
|
|
115
|
+
|
|
116
|
+
### Conversational Continuity
|
|
117
|
+
|
|
118
|
+
The skill is conversational -- it can answer multiple follow-up questions in the same session using the context docs already loaded in Step 1. Unlike the data query skills which are one-shot (parse, confirm, execute, present), this skill maintains a dialogue where each answer builds on previous context.
|
|
119
|
+
|
|
120
|
+
If a follow-up question shifts to a topic better served by a data query, suggest the appropriate skill:
|
|
121
|
+
- "Can you pull that data?" -> "Try `/vortexa:cargo-flows` or `/vortexa:voyages` for actual data queries"
|
|
122
|
+
- "Show me a breakdown by origin" -> "Try `/vortexa:breakdown crude exports by origin`"
|
|
123
|
+
|
|
124
|
+
</process>
|