---
name: fluent-workflow
description: Manage Fluent Commerce workflows - list, download, merge fragments, and track modifications. Use for workflow operations, exporting workflow JSON, merging customizations, or viewing workflow logs. Triggers on "list workflows", "download workflow", "merge workflow", "workflow fragment".
user-invocable: true
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
argument-hint: <operation> [workflow-name]
cursor-tier: auto
---

# Workflow Management

List, download, merge, and manage Fluent Commerce workflows.

> **New to Fluent CLI?** Start with `/fluent-cli-index` for a complete command reference and routing guide.

## Pre-flight: Feedback Check

Before starting, check for past learnings from this skill:

1. Check if `accounts/<PROFILE>/feedback/fluent-workflow.jsonl` exists
2. If yes, read last 20 records
3. Filter to: FAILURE or USER_CORRECTED outcomes, confidence = CONFIRMED or PROMOTED
4. Extract top 3 relevant learnings — use as internal guidance during execution
5. Do NOT show raw feedback to the user — silently adjust approach based on past issues

## When to Use

- Listing deployed workflows
- Downloading/exporting workflow definitions
- Merging workflow fragments
- Tracking workflow modification history
- Debugging workflow issues

## Operations

### 1. List Workflows

```bash
fluent workflow list -p <profile-name> -r <retailer-ref>
```

**Output:**
```
TYPE                    SUBTYPE   NAME                      VERSION
ORDER                   HD        ORDER::HD                 1.0.0
ORDER                   CC        ORDER::CC                 1.0.0
INVENTORY_CATALOGUE     DEFAULT   INVENTORY_CATALOGUE::*    1.0.0
```

### 2. Download Workflows

**Recommended convention:** Store workflows under `accounts/<PROFILE>/workflows/<RETAILER_REF>/` to scope them by retailer. Workflows are retailer-specific in Fluent Commerce — a profile can serve multiple retailers, so scoping prevents mixing workflows from different retailers.

**Single workflow:**
```bash
mkdir -p accounts/<PROFILE>/workflows/<RETAILER_REF>
fluent workflow download \
  -p <profile-name> \
  -r <retailer-ref> \
  -w <workflow-name> \
  -o accounts/<PROFILE>/workflows/<RETAILER_REF>/
```

```powershell
# PowerShell
New-Item -ItemType Directory -Force -Path "accounts\<PROFILE>\workflows\<RETAILER_REF>"
fluent workflow download -p <profile-name> -r <retailer-ref> -w <workflow-name> -o "accounts\<PROFILE>\workflows\<RETAILER_REF>\"
```

**All workflows (recommended for initial setup):**
```bash
mkdir -p accounts/<PROFILE>/workflows/<RETAILER_REF>
fluent workflow download \
  -p <profile-name> \
  -r <retailer-ref> \
  -w all \
  -o accounts/<PROFILE>/workflows/<RETAILER_REF>/
```

**Example:**
```bash
fluent workflow download -p YOUR_PROFILE -r YOUR_RETAILER_REF -w all -o accounts/YOUR_PROFILE/workflows/YOUR_RETAILER_REF/
fluent workflow download -p YOUR_PROFILE -r YOUR_RETAILER_REF -w ORDER::HD -o accounts/YOUR_PROFILE/workflows/YOUR_RETAILER_REF/
```

Write/update workflow context in the same folder:

`accounts/<PROFILE>/workflows/<RETAILER_REF>/workflow-context.json`

```json
{
  "profile": "<PROFILE>",
  "retailerRef": "<RETAILER_REF>",
  "downloadedAt": "<ISO-8601>"
}
```

**Ownership:** `workflow-context.json` is created by `/fluent-connect` during workspace setup, or manually by the user when downloading workflows via `/fluent-workflow`. Any skill that downloads or re-downloads workflows should update this file. Skills that read workflows (e.g., `/fluent-workflow-analyzer`, `/fluent-workflow-builder`) should verify the context matches the active profile/retailer before proceeding.

Before merge/upload, verify your CLI target (`-p`, `-r`) matches this context.

**Resolving workflow path:** Read workflows from `accounts/<PROFILE>/workflows/<RETAILER_REF>/` only.

### Windows Filename Handling

Fluent workflow names use `::` as separator (e.g., `ORDER::HD`), but Windows does not allow `:` in filenames. The CLI automatically replaces `::` with `__` when saving (e.g., `ORDER__HD.json`).

Skills that read workflows should check for `workflow-file-map.json` to resolve the original workflow name from the filename.

### Auto-Generate Workflow File Map

After every workflow download (single or batch, CLI or MCP), automatically generate `workflow-file-map.json` in the target directory. This maps original workflow names (containing `::`) to sanitized filenames (using `__`):

```bash
# Generate workflow-file-map.json from downloaded files
cd accounts/<PROFILE>/workflows/<RETAILER_REF>/
node -e "
const fs = require('fs');
const files = fs.readdirSync('.').filter(f => f.endsWith('.json') && f !== 'workflow-context.json' && f !== 'workflow-file-map.json');
const map = {};
for (const f of files) {
  const original = f.replace('.json', '').replace(/__/g, '::');
  map[original] = f;
}
fs.writeFileSync('workflow-file-map.json', JSON.stringify(map, null, 2));
console.log('Generated workflow-file-map.json with ' + Object.keys(map).length + ' entries');
"
```

**Result:**
```json
{
  "ORDER::HD": "ORDER__HD.json",
  "FULFILMENT::CC": "FULFILMENT__CC.json"
}
```

This enables downstream skills to resolve `ORDER::HD` to `ORDER__HD.json` without manual tracking. The map is regenerated on each download. Always generate the map even on macOS/Linux for cross-platform portability.

### 3. Merge Workflow Fragment

Apply customizations to a base workflow:

```bash
fluent workflow merge \
  <fragment-file> \
  <workflow-name> \
  -p <profile-name> \
  -r <retailer-ref>
```

**Example:**
```bash
fluent workflow merge \
  ./fragments/order-hd-validation.json \
  ORDER::HD \
  -p cli-b2c \
  -r b2c
```

**Output:** `<workflow-name>.merged.json`

**Fragment structure:**
```json
{
  "name": "my-fragment",
  "description": "Add custom validation",
  "rulesets": [...],
  "states": [...]
}
```

### 4. Workflow Log Management

Track workflow modification history:

**List workflow logs:**
```bash
fluent workflowlog list -p <profile-name> -r <retailer-ref>
```

**Describe log (see applied fragments):**
```bash
fluent workflowlog describe <workflow-name> -p <profile-name> -r <retailer-ref>
```

**Output:**
```
POSITION  MODULE NAME        ASSET NAME                     RULESET COUNT
0         fluent/order       fc-workflow-order-hd.json      25
1         my-extensions      order-hd-validation.json       3
```

**Insert fragment at position:**
```bash
fluent workflowlog insert <workflow-path> <module-name> <position> \
  -p <profile-name> -r <retailer-ref>
```

**Delete fragment from log:**
```bash
fluent workflowlog delete <workflow-name> <position> \
  -p <profile-name> -r <retailer-ref>
```

## Common Workflows

| Workflow | Purpose |
|----------|---------|
| `ORDER::HD` | Home delivery orders |
| `ORDER::CC` | Click & collect orders |
| `INVENTORY_CATALOGUE::*` | Inventory management |
| `PRODUCT_CATALOGUE::*` | Product management |
| `VIRTUAL_CATALOGUE::*` | Virtual catalogue |
| `FULFILMENT::*` | Fulfilment processing |
| `LOCATION::STORE` | Store locations |
| `LOCATION::DC` | Distribution centers |

### 5. Upload Workflow via REST API

When `fluent workflow merge` fails to upload (known bug), or when uploading a manually edited workflow:

> **Cross-platform note:** The curl examples below use bash syntax and require bash, Git Bash, or WSL on Windows. The Fluent CLI and MCP tools (e.g., `graphql.query`) are the recommended cross-platform approach.

```bash
# Authenticate (use retailer-scoped credentials, not account-level)
# IMPORTANT: Use $FLUENT_USERNAME, not $USER — $USER resolves to the OS login name on Unix/macOS.
TOKEN=$(curl -s -X POST "$BASE_URL/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=$FLUENT_USERNAME&password=$PASS&client_id=$ACCOUNT&client_secret=$SECRET&grant_type=password&scope=api" \
  | python -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

# Upload workflow
curl -s -X PUT "$BASE_URL/api/v4.1/workflow" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -H "fluent.account: $ACCOUNT" \
  -d @my-workflow.json
```

```powershell
# PowerShell — Authenticate
# Use $FLUENT_USERNAME, not $USER (which resolves to OS login name)
$body = @{
  username = $FLUENT_USERNAME; password = $PASS; client_id = $ACCOUNT
  client_secret = $SECRET; grant_type = "password"; scope = "api"
}
$response = Invoke-RestMethod -Uri "$BASE_URL/oauth/token" -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
$TOKEN = $response.access_token

# Upload workflow
$headers = @{ "Authorization" = "Bearer $TOKEN"; "fluent.account" = $ACCOUNT }
$workflow = Get-Content "my-workflow.json" -Raw
Invoke-RestMethod -Uri "$BASE_URL/api/v4.1/workflow" -Method Put -Headers $headers -Body $workflow -ContentType "application/json"
```

The REST workflow API requires a **retailer-scoped token** (not account-level).

### 6. End-to-End Behavior Analysis (Workflow + Rules)

When asked "what does this workflow do end-to-end?", do this in sequence:

1. Map triggers, statuses, and transitions from workflow JSON.
2. Map each ruleset rule to its implementing class (`<ACCOUNT>.<MODULE>.<RuleName>`).
3. Confirm runtime behavior against event history (`event.list` / `event.get`) and live entity state.

If ruleset descriptions or rule names are too vague to infer intent confidently:

1. Ask for `module.json` and Java source for the mapped rule classes.
2. If source is unavailable, ask for module ZIP/JAR and decompile candidate classes.
3. Reconcile decompiled behavior with workflow props and observed event outcomes.
4. Mark confirmed behavior vs inferred behavior explicitly in the final analysis.

Use `/fluent-trace` for the runtime correlation and root-cause decision tree.

## Workflow Entity Types

| Entity Type | Workflow Naming | Example |
|-------------|-----------------|---------|
| `ORDER` | `ORDER::<subtype>` | `ORDER::HD`, `ORDER::CC`, `ORDER::MULTI` |
| `FULFILMENT` | `FULFILMENT::<subtype>` | `FULFILMENT::HD_WH`, `FULFILMENT::CC_PFS` |
| `RETURN_ORDER` | `RETURN_ORDER::<subtype>` | `RETURN_ORDER::DEFAULT` |
| `LOCATION` | `LOCATION::<type>` | `LOCATION::STORE`, `LOCATION::DC` |
| `PRODUCT_CATALOGUE` | `PRODUCT_CATALOGUE::*` | `PRODUCT_CATALOGUE::DEFAULT` |
| `INVENTORY_CATALOGUE` | `INVENTORY_CATALOGUE::*` | `INVENTORY_CATALOGUE::DEFAULT` |
| `VIRTUAL_CATALOGUE` | `VIRTUAL_CATALOGUE::*` | `VIRTUAL_CATALOGUE::DEFAULT` |

Note: `RETURN_ORDER` uses an underscore in the workflow entity type (`RETURN_ORDER::<type>`), but the GraphQL type is `ReturnOrder` (no underscore, camelCase).

## Known Issues and Workarounds

### Windows `::` Filename Issue

Fluent workflow names contain `::` (e.g., `ORDER::MULTI`). Windows disallows `:` in filenames, so `fluent workflow download` with a specific workflow name target fails on Windows.

**Preferred: MCP-based download (cross-platform):**

Use MCP tools to download workflows without writing `::` filenames:

```
1. workflow.list(profile, retailer) → get all workflow names
2. For each name:
   a. workflow.download(profile, retailer, workflow: "<NAME>") → JSON in response
   b. Sanitize filename: replace :: with __ (ORDER::HD → ORDER__HD.json)
   c. Save via Write tool to accounts/<PROFILE>/workflows/<RETAILER_REF>/<SAFE_NAME>.json
3. Write workflow-file-map.json: { "ORDER::HD": "ORDER__HD.json", ... }
```

This works identically on Windows, macOS, and Linux.

**Auto-generate `workflow-file-map.json`:** After downloading workflows (by any method), always write `workflow-file-map.json` to the workflow directory. This file maps Fluent workflow names (with `::`) to sanitized filenames (with `__`), enabling other skills to resolve workflow names to local files cross-platform:

```json
{
  "ORDER::HD": "ORDER__HD.json",
  "ORDER::CC": "ORDER__CC.json",
  "FULFILMENT::HD_WH": "FULFILMENT__HD_WH.json"
}
```

If downloading on macOS/Linux where `::` filenames are valid, still write the map for portability.

**CLI workaround (if MCP not available):**

On Windows, both `-w <name>` and `-w all` fail because the CLI writes `ORDER::HD.json` which contains the reserved `:` character. Use `--json` to pipe to stdout instead:

```bash
fluent workflow download -p YOUR_PROFILE -r YOUR_RETAILER_REF -w all --json > accounts/<PROFILE>/workflows/<RETAILER_REF>/workflows-raw.json
```

Then split the JSON array into one file per workflow with sanitized names (replace `::` with `__`) and persist `workflow-file-map.json` with original name to filename mapping.

On macOS/Linux, `-w all -o <dir>` works directly since `:` is allowed in filenames.
- When using `fluent workflow merge`, pass a **local file path** (not a workflow name) as the merge target:

```bash
# Works on Windows — local file path avoids :: in filename
fluent workflow merge fragment.json accounts/<PROFILE>/workflows/<RETAILER_REF>/ORDER__MULTI.json \
  -p YOUR_PROFILE -r YOUR_RETAILER_REF
```

### `workflow merge` Upload Auth Bug

`fluent workflow merge` merges locally but fails to upload with `token:undefined`. The CLI doesn't authenticate before the upload REST call.

**Workaround:** After merge completes locally, upload the merged file manually via REST API (see "Upload Workflow via REST API" above). The merged output file is named `<input-file>.merged.json`.

## Error Handling

| Error | Solution |
|-------|----------|
| No workflows found | Install modules containing workflows |
| Workflow not found | Check name spelling with `workflow list` |
| Merge conflict | Rename ruleset in fragment or use update mode |
| Invalid fragment JSON | Validate JSON syntax |
| `token:undefined` on merge upload | Use REST API upload workaround (see above) |
| `:` in filename (Windows) | Prefer MCP download (returns JSON, no file issue); or CLI `-w all`, or `--json` + filename normalization + `workflow-file-map.json`; use file paths for merge |
| Workflow upload rejected (403) | Use retailer-scoped token, not account-level |

## Best Practices

1. **Scope workflows by retailer** — Store in `accounts/<PROFILE>/workflows/<RETAILER_REF>/` to avoid mixing retailers
2. **Download workflows before merging** — Keep backups
3. **Test fragments in dev** — Before applying to production
4. **Use workflow logs** — Track modification history
5. **Document fragment purpose** — In fragment description field
6. **Validate merged workflows** — Review before deployment
7. **Keep fragments in version control** — For reusability
8. **Bump `version` and `versionComment`** — In workflow JSON on every edit
9. **Use REST API upload** — When CLI merge upload fails
10. **Use retailer-scoped tokens** — Account-level tokens lack workflow API access

## Post-Execution: Feedback Capture

After completing this skill (whether success or failure), write a feedback record:

1. **Classify outcome:** `SUCCESS` (completed cleanly), `PARTIAL_SUCCESS` (completed after fixing issues), `FAILURE` (could not complete), `BLOCKED` (prereq missing), `USER_CORRECTED` (user overrode approach)
2. **Build record:** Create a `feedback-record-v1` JSON object with:
   - `skill`: `"fluent-workflow"`
   - `feature`: feature slug if applicable, null otherwise
   - `phases`: trace of each phase with PASS/FAIL/SKIP
   - `learnings`: any gotchas discovered during execution
   - `userCorrections`: any corrections the user provided
3. **Redact secrets:** Strip tokens, passwords, API keys. Keep business identifiers.
4. **Append** one JSON line to `accounts/<PROFILE>/feedback/fluent-workflow.jsonl`
5. **Update** `accounts/<PROFILE>/feedback/index.json` counters (create with `mkdir -p` if missing)

**Skip capture if:** The execution was trivially simple (e.g., user asked a question, no actual write operation happened).

## Known Pitfalls
<!-- feedback-promoted: managed section, updated by feedback loop -->

_(No promoted learnings yet.)_

<!-- end feedback-promoted -->
