---
name: fluent-connect
description: Guided onboarding wizard to connect to an existing Fluent Commerce account. Discovers CLI profiles, selects retailer, wires MCP servers, prepares workspace, downloads workflows, decompiles JARs, and reports readiness with cached state. Triggers on "connect account", "switch account", "onboard", "wire up", "get started", "setup environment", "connect to fluent", "change account", "setup workspace", "initialize workspace", "discover profiles".
user-invocable: true
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
argument-hint: [--profile <name>] [--retailer <ref>] [--force]
cursor-tier: manual
---

# Fluent Account Connect

Guided wizard to connect this workspace to an existing Fluent Commerce account. Discovers CLI profiles, selects a retailer target, wires MCP servers, prepares workspace directories, downloads workflows, decompiles JARs, validates connectivity, and persists cached state so subsequent runs are instant.

## Pre-flight: Feedback Check

Before starting, check for past learnings from this skill:

1. Check if `accounts/<PROFILE>/feedback/fluent-connect.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

## Ownership Boundary

This skill owns the "connect to existing account" workflow: profile discovery, retailer selection, MCP wiring, workspace directory setup, JAR decompilation, state caching, and readiness reporting.

- Profile creation from scratch is owned by `/fluent-profile`.
- Full new-account bootstrap is owned by `/fluent-bootstrap`.
- MCP tool reference is owned by `/fluent-mcp-tools`.
- Workflow analysis is owned by `/fluent-workflow-analyzer`.
- Source code analysis is owned by `/fluent-custom-code`.
- Module validation is owned by `/fluent-module-validate`.

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

## When to Use

- "Connect me to an existing Fluent account"
- "Switch to a different account / retailer"
- "Set up my workspace for this profile"
- "Get me ready to work on [account]"
- "Onboard me" / "get started"
- "Setup workspace" / "initialize workspace"
- Re-running to validate an already-connected workspace

## Inputs

| Parameter | Required | Source | Description |
|-----------|----------|--------|-------------|
| `--profile <name>` | No | Argument or interactive | CLI profile name. If omitted, wizard discovers and asks. |
| `--retailer <ref>` | No | Argument or interactive | Retailer ref within the profile. If omitted, wizard discovers and asks. |
| `--force` | No | Argument | Ignore cached state, re-run full discovery even if nothing changed. |

If both `--profile` and `--retailer` are provided, skip the interactive selection phases and proceed directly to wiring and validation.

---

## Phase 0: Cache Check

Before doing any work, check if workspace state is already current.

### Steps

1. Read `accounts/<PROFILE>/workspace-state.json` — if missing, proceed to Phase 1.
2. Compute a content hash (see Content Hash section) and compare with `contentHash` in the stored state.
3. If hashes match and `--force` is NOT set:
   - Print the stored summary (profile, retailer, workflow count, source repo count, entity counts).
   - Print "Workspace state is current. Use --force to re-run."
   - **Stop here.**
4. If hashes differ or `--force` is set: continue to Phase 1.

If `--profile` was not given, skip cache check and go to Phase 1 (need to discover profiles first).

---

## Phase 1: Profile Discovery

### Step 1.1: List CLI profiles

```bash
fluent profile list
```

Also scan the filesystem for profile directories:

```bash
ls ~/.fluentcommerce/
```

```powershell
# PowerShell
Get-ChildItem "$env:USERPROFILE\.fluentcommerce"
```

Each subdirectory (excluding `.sessions`, `config.json`) is a potential profile. Each contains `profile.json` with `id`, `baseUrl`, `clientSecret`, `user`.

### Step 1.2: Present profiles to user

Read each `~/.fluentcommerce/<PROFILE>/profile.json` and build a summary table:

| # | Profile | Account | Environment | Base URL |
|---|---------|---------|-------------|----------|
| 1 | PROFILE_A | acme | sandbox | acme.sandbox.api.fluentretail.com |
| 2 | PROFILE_B | globex | test | globex.test.api.fluentretail.com |

**Account identification from base URL:**
- Pattern: `https://<account>[.<environment>].api.fluentretail.com`
- `.test.` = test environment
- `.sandbox.` = sandbox environment
- No qualifier = **production** (flag with warning)

### Step 1.3: Select profile

If `--profile` was provided, validate it exists in the list. If not, **ask the user** to pick from the discovered profiles.

**If no profiles exist at all:**

> No CLI profiles found. You need to create one first.
> Use `/fluent-profile` to create a profile, or `/fluent-bootstrap` for a complete new account setup.

Stop and delegate.

---

## Phase 2: Retailer Selection

### Step 2.1: Discover retailers for selected profile

Read retailer files from the profile directory:

```bash
ls ~/.fluentcommerce/<PROFILE>/retailer.*.json
```

```powershell
# PowerShell
Get-ChildItem "$env:USERPROFILE\.fluentcommerce\<PROFILE>\retailer.*.json"
```

Each file is named `retailer.<REF>.json` and contains:
```json
{ "id": "<retailer_id>", "ref": "<ref>", "user": "<username>" }
```

### Step 2.2: Present retailers to user

| # | Retailer Ref | Retailer ID | User |
|---|-------------|-------------|------|
| 1 | MY_RETAILER | 5 | retailer_admin |
| 2 | OTHER_RETAILER | 3 | other_admin |

### Step 2.3: Select retailer

If `--retailer` was provided, validate it matches a known retailer file. If not, **ask the user** to pick.

**If no retailers are configured:**

> No retailers found for profile `<PROFILE>`. You can:
> 1. Register an existing retailer: `fluent profile update <PROFILE> --retailer <REF> --id <ID>`
> 2. Create a new retailer: use `/fluent-cli-retailer`
> 3. Full account setup: use `/fluent-bootstrap`

### Step 2.4: Confirm target

Display the confirmed target before proceeding:

```
Target environment:
  Profile:     <PROFILE>
  Account:     <account>
  Environment: <tier>
  Base URL:    https://<account>.<tier>.api.fluentretail.com
  Retailer:    <RETAILER_REF> (ID: <RETAILER_ID>)
  User:        <username>
```

> **WARNING: PRODUCTION ENVIRONMENT** — If the base URL has no `.test.` or `.sandbox.` qualifier, display a prominent warning. All operations may affect live data. Ask for explicit confirmation before continuing.

---

## Phase 3: MCP Wiring

### Step 3.1: Check current configuration

Read `.mcp.json` in the workspace root. Check if it already targets the selected profile and retailer:

- `mcpServers["fluent-mcp"].env.FLUENT_PROFILE` matches selected profile?
- `mcpServers["fluent-mcp-extn"].env.FLUENT_PROFILE` matches selected profile?
- `mcpServers["fluent-mcp-extn"].env.FLUENT_PROFILE_RETAILER` matches selected retailer ref?

**If already configured correctly:** Report "Already connected to <PROFILE>/<RETAILER>. Validating connectivity..." and skip to Step 3.4.

**If switching from a different profile:** Warn the user: "Currently connected to <OLD_PROFILE>. Switching to <NEW_PROFILE>."

### Step 3.2: Update .mcp.json

**Before modifying**, show the user what will change:

```
MCP Configuration Update:
  fluent-mcp:      FLUENT_PROFILE = <OLD> → <NEW>
  fluent-mcp-extn: FLUENT_PROFILE = <OLD> → <NEW>
  fluent-mcp-extn: FLUENT_RETAILER_ID = <OLD> → <NEW>
Proceed? [yes/NO]
```

Wait for user confirmation. Then run the mcp-setup command:

```bash
npx @fluentcommerce/ai-skills mcp-setup --profile <PROFILE> --profile-retailer <RETAILER_REF>
```

This updates `.mcp.json` with:
- `fluent-mcp` server: `FLUENT_PROFILE=<PROFILE>`
- `fluent-mcp-extn` server: `FLUENT_PROFILE=<PROFILE>`, `FLUENT_PROFILE_RETAILER=<RETAILER_REF>`

The command uses merge semantics — it preserves existing non-conflicting env vars.

### Step 3.3: Read and verify .mcp.json

After mcp-setup completes, read `.mcp.json` and verify the three env vars from Step 3.1 are set correctly. Display the verified config to the user.

### Step 3.4: Prompt IDE reload

> **ACTION REQUIRED:** The MCP servers read environment variables at startup.
> You must reload the MCP servers for the new configuration to take effect.
>
> - **Claude Code:** Restart the session
>
> After reloading, confirm you are back and I will validate connectivity.

**WAIT for user to confirm they have reloaded before proceeding.**

### Step 3.5: Validate connectivity

After user confirms reload:

1. Run `config.validate` (MCP tool) — verify auth strategy is "profile" and no errors
2. Run `connection.test` (MCP tool) — verify authenticated user, retailer ID, and retailer ref match expectations

**If config.validate returns errors:**
- Profile load failure: check `~/.fluentcommerce/<PROFILE>/profile.json` exists and is valid JSON
- Auth not configured: check `.mcp.json` env vars are correct
- Missing retailer scope: check `FLUENT_PROFILE_RETAILER` is set

**If connection.test fails:**
- Auth error: credentials may be expired. Suggest `fluent profile update <PROFILE> --user <user> --username <user> --password <pass>`
- Network error: check base URL and connectivity

Report the connection status:

```
MCP Connectivity: OK
  Auth strategy: profile
  User:          <username>
  Retailer:      <RETAILER_REF> (ID: <RETAILER_ID>)
  Base URL:      https://<account>.<tier>.api.fluentretail.com
```

---

## Phase 4: Workspace Readiness

### Step 4.1: Ensure workspace directories exist

```bash
mkdir -p accounts/<PROFILE>/SOURCE/backend
mkdir -p accounts/<PROFILE>/SOURCE/frontend
mkdir -p accounts/<PROFILE>/workflows/<RETAILER_REF>
mkdir -p accounts/<PROFILE>/features
mkdir -p accounts/<PROFILE>/tasks
mkdir -p accounts/<PROFILE>/reports
mkdir -p accounts/<PROFILE>/analysis
mkdir -p accounts/<PROFILE>/feedback
mkdir -p accounts/<PROFILE>/sessions
mkdir -p accounts/<PROFILE>/settings/backups
mkdir -p accounts/<PROFILE>/manifests/backups
mkdir -p accounts/<PROFILE>/knowledge
```

```powershell
# PowerShell
$dirs = @(
  "accounts\<PROFILE>\SOURCE\backend",
  "accounts\<PROFILE>\SOURCE\frontend",
  "accounts\<PROFILE>\workflows\<RETAILER_REF>",
  "accounts\<PROFILE>\features",
  "accounts\<PROFILE>\tasks",
  "accounts\<PROFILE>\reports",
  "accounts\<PROFILE>\analysis",
  "accounts\<PROFILE>\feedback",
  "accounts\<PROFILE>\sessions",
  "accounts\<PROFILE>\settings\backups",
  "accounts\<PROFILE>\manifests\backups",
  "accounts\<PROFILE>\knowledge"
)
$dirs | ForEach-Object { New-Item -ItemType Directory -Force -Path $_ }
```

### Step 4.1b: Create README placeholders in each directory

Write a short `README.md` into each directory **only if one does not already exist**. This gives new users visibility into the full workspace structure and what each directory is for.

```bash
node -e "
const fs = require('fs');
const path = require('path');
const profile = process.argv[1];
const retailer = process.argv[2];
const base = path.join('accounts', profile);

const placeholders = {
  'SOURCE/backend': {
    title: 'Backend Source Code',
    content: 'Clone Java Maven plugin repos here. Each subdirectory should be one git repo with pom.xml + src/main/java/.\n\nExample:\n  git clone https://your-org/fc-plugin-custom.git\n\nStandalone JARs (no source): place .jar files here — auto-decompiled to .decompiled/\n\nPopulated by: git clone or manual copy\nAnalyzed by: /fluent-custom-code, /fluent-source-onboard'
  },
  'SOURCE/frontend': {
    title: 'Frontend Source Code',
    content: 'Mystique SDK component projects go here.\n\nDownload SDK: https://fluent.apps.fluentcommerce.com/_sdk/latest/omx-component-sdk.zip\nExtract, then build with: yarn install && yarn build\n\nPopulated by: git clone or SDK download\nScaffolded by: /fluent-mystique-scaffold\nBuilt by: /fluent-frontend-build'
  },
  'features': {
    title: 'Features',
    content: 'Feature lifecycle directories — one subdirectory per feature.\n\nEach feature dir contains:\n  spec.md         — Business requirements (from /fluent-use-case-discover)\n  plan.md         — Implementation plan (from /fluent-feature-plan)\n  architecture.md — Reverse-engineered docs (from /fluent-feature-explain)\n  status.json     — Machine-readable lifecycle state\n  assets/         — Screenshots, recordings, visual evidence\n\nCreated by: /fluent-use-case-discover\nDashboard: /fluent-feature-dashboard'
  },
  'tasks': {
    title: 'Operational Tasks',
    content: 'Operational task plans for non-feature work (module scaffolding, bootstrap, version management).\n\nFile naming: <YYYY-MM-DD>-<skill>-<slug>.md\n\nCreated by: various skills when planning gate produces a task plan'
  },
  'reports': {
    title: 'Reports',
    content: 'Ephemeral run outputs organized by type.\n\nSubdirectories (created on first use):\n  build/           — Build results from /fluent-build\n  pre-deploy/      — Pre-deploy check results\n  module-validate/ — Module validation reports\n  e2e-test/        — End-to-end test results\n  ui-test/         — Browser UI test evidence\n\nCreated by: /fluent-build, /fluent-pre-deploy-check, /fluent-e2e-test, /fluent-ui-test'
  },
  'analysis': {
    title: 'Analysis',
    content: 'Persistent cross-cutting analysis artifacts.\n\nSubdirectories (created on first use):\n  code/      — Source code analysis maps\n  modules/   — Module validation and inventory\n  topology/  — Connection topology maps\n  settings/  — Settings inventory and analysis\n  scope/     — Scope decomposition outputs\n\nCreated by: /fluent-custom-code, /fluent-connection-analysis, /fluent-implementation-map'
  },
  'feedback': {
    title: 'Feedback',
    content: 'Skill execution feedback — append-only JSONL files + index.json.\n\nOne file per skill: <skill-name>.jsonl\nAuto-captured by pilot skills: workflow-builder, workflow-deploy, settings, rule-scaffold\n\nUsed by: /fluent-feedback (dashboard, review, promote)'
  },
  'sessions': {
    title: 'Sessions',
    content: 'Audit trail exports — session change summaries.\n\nCreated by: /fluent-session'
  },
  'settings/backups': {
    title: 'Settings Backups',
    content: 'Non-manifest setting backups taken before any setting change.\n\nFile naming: <setting-name>_<YYYY-MM-DD>.json\n\nCreated by: /fluent-settings (mandatory safety protocol)'
  },
  'manifests/backups': {
    title: 'Manifest Backups',
    content: 'Manifest setting backups taken before ANY manifest create/update.\n\nFile naming: <setting-name>_<YYYY-MM-DD>.json\n\nCreated by: /fluent-mystique-builder (mandatory safety protocol)\nNever deploy a manifest without backing up the existing one first.'
  },
  'knowledge': {
    title: 'Account Knowledge Overrides',
    content: 'Account-specific conventions, business rules, naming, integrations, and test data.\nOverrides generic platform knowledge from knowledge/.\n\nPopulated by: /fluent-knowledge-init or manual creation'
  }
};

let created = 0;
for (const [dir, info] of Object.entries(placeholders)) {
  const readmePath = path.join(base, dir, 'README.md');
  if (!fs.existsSync(readmePath)) {
    const content = '# ' + info.title + '\n\n' + info.content + '\n';
    fs.writeFileSync(readmePath, content);
    created++;
  }
}
console.log('Scaffold: ' + created + ' README placeholders created (' + (Object.keys(placeholders).length - created) + ' already existed)');
" <PROFILE> <RETAILER_REF>
```

The same Node.js script works identically on Windows (Git Bash/PowerShell), macOS, and Linux.

Directory structure after scaffold:

```
accounts/
  <PROFILE>/
    SOURCE/                          <- account-level, shared across retailers
      backend/                       <- Java Maven plugin repos (README.md)
        <repo-name>/
        .decompiled/<jar-basename>/
      frontend/                      <- Mystique SDK component projects (README.md)
        <sdk-project-name>/
    workflows/                       <- retailer-scoped workflow JSONs
      <RETAILER_REF>/
        ORDER__HD.json
    features/                        <- feature lifecycle (README.md)
    tasks/                           <- operational plans (README.md)
    reports/                         <- ephemeral run outputs (README.md)
    analysis/                        <- persistent cross-cutting analysis (README.md)
    feedback/                        <- skill execution feedback (README.md)
    sessions/                        <- audit trail exports (README.md)
    settings/
      backups/                       <- non-manifest setting backups (README.md)
    manifests/
      backups/                       <- manifest setting backups (README.md)
    knowledge/                       <- account-specific knowledge overrides (README.md)
    workspace-state.json
```

SOURCE is at the profile level because plugin code is deployed per-account (shared across retailers). Workflows are scoped by retailer ref inside the `workflows/` directory because they can differ per retailer.

All operations are idempotent — `mkdir -p` skips existing dirs, README creation skips existing files. On Windows with Git Bash, forward slashes and `mkdir -p` work correctly.

### Step 4.2: Check and download workflows

Check if workflows directory has content:

```bash
ls accounts/<PROFILE>/workflows/<RETAILER_REF>/*.json 2>/dev/null | wc -l
```

```powershell
# PowerShell
(Get-ChildItem "accounts\<PROFILE>\workflows\<RETAILER_REF>\*.json" -ErrorAction SilentlyContinue).Count
```

**If empty (count is 0):**

**Preferred: MCP-based download (cross-platform, avoids `::` filename issue):**

```
1. workflow.list(profile: "<PROFILE>", retailer: "<RETAILER_REF>")
   → get all workflow names (e.g., ORDER::HD, FULFILMENT::HD_WH)

2. For each workflow name:
   a. workflow.download(profile: "<PROFILE>", retailer: "<RETAILER_REF>", workflow: "<NAME>")
      → returns full JSON content in response (no file written)
   b. Sanitize filename: replace :: with __ (e.g., ORDER::HD → ORDER__HD.json)
   c. Write JSON content to accounts/<PROFILE>/workflows/<RETAILER_REF>/<SANITIZED_NAME>.json

3. Write workflow-file-map.json mapping original names to sanitized filenames:
   { "ORDER::HD": "ORDER__HD.json", "FULFILMENT::HD_WH": "FULFILMENT__HD_WH.json" }
```

This approach works identically on Windows, macOS, and Linux because `::` never appears in a filename.

**MANDATORY post-download step (both MCP and CLI paths):** After writing all workflow files, generate `workflow-file-map.json`:

```bash
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');
"
```

This enables downstream skills (`/fluent-workflow-analyzer`, `/fluent-custom-code`, `/fluent-feature-explain`) to resolve `ORDER::HD` to `ORDER__HD.json`. Always generate even on macOS/Linux for cross-platform portability.

**Fallback: CLI download (if MCP servers not yet connected):**

On macOS/Linux (`::` is valid in filenames):

```bash
fluent workflow list -p <PROFILE> -r <RETAILER_REF>
fluent workflow download -p <PROFILE> -r <RETAILER_REF> -w all -o accounts/<PROFILE>/workflows/<RETAILER_REF>/
```

On Windows (both `-w <name>` and `-w all` fail because the CLI writes `ORDER::HD.json` and `:` is reserved):

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

Then split into one file per workflow with sanitized names (replace `::` with `__`). The mandatory post-download step above generates the `workflow-file-map.json` mapping.

Write/update workflow context:

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

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

Note: `-r` expects retailer **ref** (e.g., `MY_RETAILER`), not retailer ID.

**If workflows already exist:**

Report count and freshness. If most recent file is older than 7 days, suggest re-downloading:

```bash
ls -lt accounts/<PROFILE>/workflows/<RETAILER_REF>/*.json | head -5
```

```powershell
# PowerShell
Get-ChildItem "accounts\<PROFILE>\workflows\<RETAILER_REF>\*.json" | Sort-Object LastWriteTime -Descending | Select-Object -First 5
```

If `workflow-context.json` exists, verify `profile` + `retailerRef` match the active target. If mismatched, re-download workflows into the correct retailer folder and overwrite context.

**Ownership:** `workflow-context.json` is created and maintained exclusively by this skill (`/fluent-connect`) during workflow download. Other skills (`/fluent-workflow`, `/fluent-custom-code`, `/fluent-workflow-analyzer`) read this file to resolve profile/retailer context but do not create or modify it.

### Step 4.3: Check source code

Scan both backend and frontend subdirectories:

```bash
ls accounts/<PROFILE>/SOURCE/backend/ 2>/dev/null
ls accounts/<PROFILE>/SOURCE/frontend/ 2>/dev/null
```

```powershell
# PowerShell
Get-ChildItem "accounts\<PROFILE>\SOURCE\backend" -ErrorAction SilentlyContinue
Get-ChildItem "accounts\<PROFILE>\SOURCE\frontend" -ErrorAction SilentlyContinue
```

**If repos with Java source found (under `SOURCE/backend/`):**

Report discovered repos. Validate each has expected structure (`module.json`, `pom.xml`, or `src/main/java/`).

**Extract module identity (version + symbolic name):**

For each discovered repo, extract identity using this precedence:

`symbolicName`:
1. `resources/module.json` → `name` field (preferred)
2. JAR `META-INF/MANIFEST.MF` → `Bundle-SymbolicName` (if present)
3. POM fallback → `<groupId>/<artifactId>` (or `<artifactId>` alone if `groupId` missing)

`version`:
1. `resources/module.json` → `version` field (preferred)
2. POM → `<project><version>` (fallback to `<project><parent><version>` if module version is omitted or inherited)
3. JAR manifest → `Implementation-Version` or `Bundle-Version`

POM extraction examples:

```xml
<!-- Direct version -->
<project>
  <groupId>com.fluentcommerce</groupId>
  <artifactId>fc-module-extensions</artifactId>
  <version>1.2.3</version>
  <name>FC Module Extensions</name>
</project>

<!-- Inherited version (no <version> at project level) -->
<project>
  <parent>
    <version>1.2.3</version>
  </parent>
  <artifactId>fc-module-extensions</artifactId>
</project>
```

Record where each value came from (e.g., `versionSource: "module.json"` or `versionSource: "pom.parent.version"`) for traceability.

Report format (classify each by type):

```
Source code:
  Custom Extension (editable, buildable):
    - <repo-name-1>/  <symbolic-name> v<X.Y.Z> (N rules, Maven)
  Configuration-Only (editable, not buildable):
    - <repo-name-2>/  <symbolic-name> v<X.Y.Z> (workflows + settings, no rules)
  Reference Modules (read-only):
    - <module-name>/  <symbolic-name> v<X.Y.Z> (N OOTB rules, JAR)
```

**Handle double-nested git clone directories:**
If a directory under SOURCE contains only one subdirectory with a similar name (e.g., `<repo>/<repo>/`), treat the inner directory as the actual module root. This is a common git clone artifact.

**If reference module packages found (module.json + JAR):**

Reference modules have both `module.json` (with full rule metadata) and compiled JARs under `assets/rules/`. Read rule names, descriptions, and version from `module.json` directly — no decompilation needed for metadata. Only decompile if deep analysis of rule implementation logic is requested.

**If only standalone JAR files found (no module.json alongside):**

When a module is deployed but the original source code is not available, look for `.jar` files under `SOURCE/backend/`. If a JAR is found, decompile it to produce browsable source for analysis:

1. **Locate JARs:**

Use `Glob` with pattern `accounts/<PROFILE>/SOURCE/backend/**/*.jar` for cross-platform file discovery. Exclude `target/dependency/` results.

```bash
find accounts/<PROFILE>/SOURCE/backend/ -name "*.jar" -not -path "*/target/dependency/*" 2>/dev/null
```

```powershell
# PowerShell
Get-ChildItem "accounts\<PROFILE>\SOURCE\backend" -Recurse -Filter "*.jar" | Where-Object { $_.FullName -notlike "*\target\dependency\*" }
```

2. **Auto-download CFR decompiler if not present, then decompile:**

> **Cross-platform note:** The decompilation commands below use bash syntax (`mkdir -p`, `curl`). On Windows, use Git Bash, WSL, or the PowerShell equivalents shown where available. The `java -jar` and `jar tf` commands work identically on all platforms.

```bash
# Auto-download CFR (~2MB single JAR, no installation needed)
CFR_DIR="$HOME/.fluent-ai-skills/tools"
CFR_JAR="$CFR_DIR/cfr.jar"
if [ ! -f "$CFR_JAR" ]; then
  mkdir -p "$CFR_DIR"
  curl -L -o "$CFR_JAR" "https://github.com/leibnitz27/cfr/releases/download/0.152/cfr-0.152.jar"
fi

# Create deterministic decompiled output directory
mkdir -p accounts/<PROFILE>/SOURCE/backend/.decompiled/<jar-basename>

# Option A: CFR with --jarfilter to extract only rule classes (preferred)
java -jar "$CFR_JAR" "<jar-file>.jar" \
  --outputdir "accounts/<PROFILE>/SOURCE/backend/.decompiled/<jar-basename>" \
  --jarfilter "com.fluentcommerce.rule"

# Option B: CFR full decompilation (all classes)
java -jar "$CFR_JAR" "<jar-file>.jar" \
  --outputdir "accounts/<PROFILE>/SOURCE/backend/.decompiled/<jar-basename>"

# Option C: Fernflower (IntelliJ's built-in decompiler)
java -jar fernflower.jar <jar-file>.jar accounts/<PROFILE>/SOURCE/backend/.decompiled/<jar-basename>

# Option D: If neither is available, use javap for class listing
jar tf <jar-file>.jar | grep "\.class$"
```

```powershell
# PowerShell — auto-download CFR
$CfrDir = "$env:USERPROFILE\.fluent-ai-skills\tools"
$CfrJar = "$CfrDir\cfr.jar"
if (-not (Test-Path $CfrJar)) {
  New-Item -ItemType Directory -Force -Path $CfrDir
  Invoke-WebRequest -Uri "https://github.com/leibnitz27/cfr/releases/download/0.152/cfr-0.152.jar" -OutFile $CfrJar
}

# CFR with --jarfilter
java -jar $CfrJar "<jar-file>.jar" --outputdir "accounts\<PROFILE>\SOURCE\backend\.decompiled\<jar-basename>" --jarfilter "com.fluentcommerce.rule"
```

The `--jarfilter` flag restricts decompilation to classes matching the package prefix, keeping output focused on rule logic.

**Decompiler auto-install fallback:** If `$CFR_JAR` is missing and `curl` is unavailable (e.g., restricted CI environment), try downloading via Node.js:

```bash
node -e "const https=require('https'),fs=require('fs'),p=require('path'),d=p.join(require('os').homedir(),'.fluent-ai-skills','tools');fs.mkdirSync(d,{recursive:true});const f=fs.createWriteStream(p.join(d,'cfr.jar'));https.get('https://github.com/leibnitz27/cfr/releases/download/0.152/cfr-0.152.jar',r=>{if(r.statusCode===302){https.get(r.headers.location,r2=>r2.pipe(f))}else{r.pipe(f)}})"
```

If neither `curl` nor `node` can download the file, and `java` is not available, log a warning and skip decompilation. Record JAR paths for later.

**Decompiled output warning:** After decompiling, create a `README-DECOMPILED.txt` file in each `.decompiled/<jar-basename>/` directory with the content: "These files were auto-decompiled from JAR artifacts. DO NOT EDIT — they are read-only reference material. Re-decompile from the source JAR if you need updated output."

3. **Extract module.json from the JAR** (if present):

```bash
unzip -p <jar-file>.jar module.json > accounts/<PROFILE>/SOURCE/backend/.decompiled/<jar-basename>/module.json
```

```powershell
# PowerShell
Add-Type -AssemblyName System.IO.Compression.FileSystem
$jar = [System.IO.Compression.ZipFile]::OpenRead("<jar-file>.jar")
$entry = $jar.GetEntry("module.json")
if ($entry) {
  $stream = $entry.Open()
  $reader = New-Object System.IO.StreamReader($stream)
  $reader.ReadToEnd() | Set-Content "accounts\<PROFILE>\SOURCE\backend\.decompiled\<jar-basename>\module.json"
  $reader.Close(); $stream.Close()
}
$jar.Dispose()
```

4. **Create a `DECOMPILED.md` marker file** in the decompiled output directory:

```markdown
# Decompiled Source — DO NOT EDIT

- **Source JAR:** <jar-filename>.jar
- **Decompiled on:** <date>
- **Decompiler:** CFR / Fernflower / javap

> **WARNING: This is decompiled bytecode, NOT original source.**
> Variable names may be synthetic. Comments and annotations may be incomplete.
> These files are READ-ONLY for analysis. Never edit decompiled files —
> modify the original source or scaffold a new module instead.
```

After decompilation, `/fluent-custom-code` can analyze the decompiled classes for rule discovery, workflow-rule mapping, and behavior explanation.

> **Decompilation limitations:**
> - Local variable names may be replaced with synthetic names (`var1`, `var2`)
> - Comments, Javadoc, and some annotations may be lost
> - Generic type information may be partially erased
> - Confidence label should be "low-medium" for decompiled source vs "high" for original

**If neither source nor JAR found:**

> No custom source code or JAR files found under `accounts/<PROFILE>/SOURCE/backend/` or `accounts/<PROFILE>/SOURCE/frontend/`.
> This is not blocking — it means no custom plugins are available for analysis.
>
> Options:
> 1. Clone Java plugin repos: `git clone <repo-url>` into `accounts/<PROFILE>/SOURCE/backend/`
> 2. Clone SDK projects: `git clone <repo-url>` into `accounts/<PROFILE>/SOURCE/frontend/`
> 3. Copy module JARs: place `.jar` files in `accounts/<PROFILE>/SOURCE/backend/` for decompilation
> 3. Download from Fluent: if the module is deployed, the JAR may be retrievable from the build artifacts

### Step 4.4: Build deployed rule inventory

Query the live environment for the complete picture of what's deployed.

**4.4a: Query deployed custom rules**

Use the MCP `plugin.list` tool to get all registered orchestration rules. Filter for account-specific rules (prefixed with the account context, not `FLUENTRETAIL.*`):

```
plugin.list → N total rules
  - FLUENTRETAIL.*  → platform rules (standard, no source needed)
  - <ACCOUNT>.*     → custom rules (these need source or JARs)
```

**4.4b: Cross-reference deployed vs local**

For each custom rule discovered in the live registry:

| Deployed Rule | Local Source? | Local JAR? | Status |
|---------------|--------------|------------|--------|
| `<ACCOUNT>.<module>.<RuleName>` | `SOURCE/backend/<repo>/...RuleName.java` | - | Full source |
| `<ACCOUNT>.<module>.<OtherRule>` | - | `SOURCE/backend/<module>.jar` | Decompiled |
| `<ACCOUNT>.<module>.<UnknownRule>` | - | - | **Missing** |

**4.4c: Report the inventory**

```
Deployed Rule Inventory:
  Total custom rules deployed:     N
  With full source code:           X  (modifiable)
  With decompiled source (JAR):    Y  (read-only, can analyze)
  Missing (no source or JAR):      Z  (cannot analyze)
```

**4.4d: Recommendations based on inventory**

- **Full source** modules: ready for analysis, modification, and redeployment. Use `/fluent-custom-code` for deep analysis, `/fluent-rule-scaffold` to add new rules, `/fluent-build` to compile.
- **JAR-only** modules: can analyze behavior via decompiled source. Cannot modify directly. Recommend cloning original source or scaffolding a new extension module.
- **Missing** modules: flag as a gap. Ask the user to provide the source or JAR.

> **Important:** JAR-decompiled source is read-only for analysis. Never suggest editing decompiled files.

### Step 4.5: Entity count queries

Run lightweight discovery queries to understand what's configured:

```graphql
{ locations(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
{ networks(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
{ inventoryCatalogues(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
{ productCatalogues(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
```

Record presence/absence and approximate counts.

### Step 4.6: Check analysis artifacts

```bash
ls accounts/<PROFILE>/analysis/ 2>/dev/null
```

```powershell
# PowerShell
Get-ChildItem "accounts\<PROFILE>\analysis" -ErrorAction SilentlyContinue
```

If artifacts exist (e.g., `custom-code/source-map.json`, `module-validate/*.report.json`), report their age and freshness. If no artifacts exist, note it as a future step.

If the user explicitly asked for source analysis/readiness artifacts, run `/fluent-custom-code <PROFILE> --retailer <RETAILER_REF>` now instead of deferring.

---

## Phase 5: Persist State and Report

### Step 5.1: Write per-profile state

Write `accounts/<PROFILE>/workspace-state.json`:

```json
{
  "schema": "workspace-state-v1",
  "profile": "<PROFILE>",
  "contentHash": "<sha256-hex>",
  "createdAt": "<ISO-8601>",
  "updatedAt": "<ISO-8601>",
  "environment": {
    "account": "<account-name>",
    "tier": "<test|sandbox|production>",
    "baseUrl": "<base-url>",
    "retailerRef": "<RETAILER_REF>",
    "retailerId": "<RETAILER_ID>"
  },
  "discovery": {
    "workflows": { "count": 0, "downloaded": true, "path": "accounts/<PROFILE>/workflows/<RETAILER_REF>" },
    "modules": { "installed": [], "count": 0 },
    "sourceRepos": [
      { "name": "<repo-name>", "symbolicName": "<symbolic-name>", "version": "<X.Y.Z>", "versionSource": "<module.json|pom|pom.parent>", "hasModuleJson": true, "ruleCount": 0 }
    ],
    "decompiledRepos": [],
    "entities": { "locations": 0, "networks": 0, "inventoryCatalogues": 0, "productCatalogues": 0 },
    "ruleInventory": { "total": 0, "withSource": 0, "withJar": 0, "missing": 0 },
    "connectivity": { "status": "OK", "user": "<username>", "retailer": "<tradingName>" }
  },
  "mcpConfig": { "exists": true, "hasOfficialServer": true, "hasExtensionServer": true, "profileMatch": true },
  "nextSteps": []
}
```

### Step 5.2: Write/merge workspace index

Write or merge into `accounts/workspace-index.json`:

```json
{
  "schema": "workspace-index-v1",
  "updatedAt": "<ISO-8601>",
  "profiles": {
    "<PROFILE>": {
      "status": "READY",
      "retailer": "<RETAILER_REF>",
      "account": "<account-name>",
      "tier": "<tier>",
      "stateHash": "<sha256-hex>"
    }
  }
}
```

If the index already exists, read it first and merge the new profile entry. Do not overwrite other profiles.

### Step 5.3: Readiness report

Present a comprehensive summary:

```
================================================================
  FLUENT CONNECT: Readiness Report
================================================================

  Profile:      <PROFILE>
  Account:      <account> (<tier>)
  Retailer:     <RETAILER_REF> (ID: <RETAILER_ID>)
  User:         <username>

  MCP Status:
    fluent-mcp       [OK] Profile auth
    fluent-mcp-extn  [OK] Profile auth + retailer scope

  Workspace:
    Workflows        [OK] N files
    Source code      [OK] X repos (Y rules with full source)
    JARs             [OK] Z decompiled (W rules, read-only)
    Analysis         [--] No artifacts yet

  Modules:
    <symbolic-name-1>   v<X.Y.Z>  (N rules, source)
    <symbolic-name-2>   v<X.Y.Z>  (M rules, decompiled)

  Deployed Rule Inventory:
    Custom rules deployed:   N
    With full source:        X  [modifiable]
    With decompiled JAR:     Y  [analyzable, read-only]
    Missing source:          Z  [blind spot]

  Entities:
    Locations:       N
    Networks:        N
    Catalogues:      N (inventory) / N (product)

  Suggested Next Steps:
    1. Full analysis:         /fluent-custom-code
    2. Workflow deep-dive:    /fluent-workflow-analyzer
    3. Create test data:      /fluent-test-data
    4. Run E2E tests:         /fluent-e2e-test
    5. RFL assessment:        /fluent-rfl-assess

  Workspace:      accounts/<PROFILE>/ (source shared, retailer content under <RETAILER_REF>/)
  State saved to: accounts/<PROFILE>/workspace-state.json
================================================================
```

### Capability Matrix

| Capability | Requires | Status Logic |
|-----------|----------|-------------|
| GraphQL operations | MCP connected | `connection.test` OK |
| Event dispatch | MCP connected + retailer scope | connection OK + retailerId present |
| Workflow analysis | Workflows downloaded | workflow JSON count > 0 |
| Full code analysis | Source repos present | `SOURCE/backend/` has repos with `src/main/java/` |
| JAR-based analysis | Decompiled JARs present | `SOURCE/backend/.decompiled/*/` exists |
| Code + workflow cross-ref | Workflows + any source | workflows + (source or decompiled) |
| Rule modification | Full source available | repo has original Java + pom.xml |
| Analysis reuse | Artifacts exist + fresh | `analysis/` has files and not stale |
| Complete rule coverage | All deployed rules have source | no "missing" in inventory |

### Blocked Capabilities

If any capability is blocked, explain what's needed and how to fix it.

---

## Content Hash

The content hash determines whether workspace state is current. Recompute on every run and compare with the stored hash.

### What to hash

1. **Profile config:** `~/.fluentcommerce/<PROFILE>/profile.json`
2. **Retailer configs:** all `~/.fluentcommerce/<PROFILE>/retailer.*.json` files
3. **Source repo listing:** sorted list of directory names under `accounts/<PROFILE>/SOURCE/backend/` and `accounts/<PROFILE>/SOURCE/frontend/`
4. **Workflow file listing:** sorted list of `.json` filenames in `accounts/<PROFILE>/workflows/<RETAILER_REF>/`
5. **JAR/ZIP listing:** sorted list of `.jar` and `.zip` files under `accounts/<PROFILE>/SOURCE/backend/`

### How to compute

Use Node.js (always available):

```bash
node -e "
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const h = crypto.createHash('sha256');
const profile = process.argv[1];
const home = process.env.HOME || process.env.USERPROFILE;

// 1. Profile config
const profFile = path.join(home, '.fluentcommerce', profile, 'profile.json');
if (fs.existsSync(profFile)) h.update(fs.readFileSync(profFile));

// 2. Retailer configs
const profDir = path.join(home, '.fluentcommerce', profile);
if (fs.existsSync(profDir)) {
  fs.readdirSync(profDir).filter(f => f.startsWith('retailer.') && f.endsWith('.json')).sort()
    .forEach(f => h.update(fs.readFileSync(path.join(profDir, f))));
}

// 3. Source repo listing (backend + frontend)
const srcDir = path.join('accounts', profile, 'SOURCE');
const backendDir = path.join(srcDir, 'backend');
const frontendDir = path.join(srcDir, 'frontend');
if (fs.existsSync(backendDir)) {
  fs.readdirSync(backendDir, {withFileTypes:true}).filter(e => e.isDirectory()).map(e => e.name).sort()
    .forEach(n => h.update('src:backend:' + n));
}
if (fs.existsSync(frontendDir)) {
  fs.readdirSync(frontendDir, {withFileTypes:true}).filter(e => e.isDirectory()).map(e => e.name).sort()
    .forEach(n => h.update('src:frontend:' + n));
}

// 4. Workflow file listing (retailer-scoped)
const retailer = process.argv[2];
const wfDir = path.join('accounts', profile, 'workflows', retailer);
if (fs.existsSync(wfDir)) {
  fs.readdirSync(wfDir).filter(f => f.endsWith('.json')).sort()
    .forEach(f => h.update('wf:' + f));
}

// 5. JAR/ZIP listing (backend only)
if (fs.existsSync(backendDir)) {
  const jars = [];
  function findJars(d) {
    for (const e of fs.readdirSync(d, {withFileTypes:true})) {
      if (['target','dist','node_modules','.git'].includes(e.name)) continue;
      const f = path.join(d, e.name);
      if (e.isDirectory()) findJars(f);
      else if (e.name.endsWith('.jar') || e.name.endsWith('.zip')) jars.push(f.replace(/\\\\/g,'/'));
    }
  }
  findJars(backendDir);
  jars.sort().forEach(j => h.update('jar:' + j));
}

console.log(h.digest('hex'));
" <PROFILE> <RETAILER_REF>
```

Any change (new workflow download, new repo clone, profile update, new JAR file) produces a new hash and triggers a re-run.

---

## Idempotency

This skill is designed to be run multiple times safely:

1. **Cached state matches:** If content hash hasn't changed, print summary and stop immediately.
2. **Already configured:** If `.mcp.json` already targets the correct profile/retailer, skip mcp-setup. Still validate connectivity.
3. **Directories exist:** `mkdir -p` is idempotent.
4. **Workflows downloaded:** Report count and freshness. Do not re-download unless user requests or `--force` is used.
5. **Source cloned:** Report repos found. Do not modify.
6. **Artifacts exist:** Report age. Do not regenerate.

### Switching Accounts

When the user runs `/fluent-connect` with a different profile than currently configured:

1. Detect the mismatch by reading `.mcp.json` first
2. Warn: "Currently connected to <OLD_PROFILE>. Switching to <NEW_PROFILE>."
3. Run mcp-setup with the new profile
4. Require IDE reload
5. Validate the new connection
6. Persist new workspace state
7. Report readiness for the new account

---

## Error Handling

| Phase | Error | Resolution |
|-------|-------|-----------|
| 0 | workspace-state.json corrupted | Delete and re-run full discovery |
| 1 | No profiles exist | Delegate to `/fluent-profile` |
| 1 | `fluent` CLI not found | Install from [docs.fluentcommerce.com](https://docs.fluentcommerce.com/building-blocks/fluent-cli-package) |
| 2 | No retailers for profile | Register via `fluent profile update` or `/fluent-cli-retailer` |
| 3 | mcp-setup fails | Check `npx @fluentcommerce/ai-skills --help` works and retry mcp-setup |
| 3 | connection.test auth failure | Update credentials: `fluent profile update <PROFILE> --username <user> --password <pass>` |
| 3 | connection.test network error | Verify base URL and network access |
| 4 | Workflow download fails | Check profile/retailer context. May need `fluent profile use <PROFILE> --retailer <REF>` first |
| 4 | Decompiler not found | Log warning with install instructions. Skip decompilation, record JAR paths for later. |
| 4 | Permission error on mkdir | Check workspace write permissions |

## Delegation Table

| Situation | Delegate To |
|-----------|------------|
| No profiles exist | `/fluent-profile` |
| Need to create new account | `/fluent-bootstrap` |
| Need to create retailer | `/fluent-cli-retailer` |
| MCP tool reference | `/fluent-mcp-tools` |
| Workflow deep analysis | `/fluent-workflow-analyzer` |
| Source code analysis | `/fluent-custom-code` |
| Settings management | `/fluent-settings` |
| Test data creation | `/fluent-test-data` |

## Cross-Platform Compatibility

All commands in this skill are shown in both **Bash** (macOS/Linux/Git Bash on Windows) and **PowerShell** (native Windows) where they differ. Commands that are identical on all platforms (e.g., `fluent profile list`, `node -e`, `npx`) are shown once.

**Shell detection:** AI agents should check `process.platform` (Node.js) or `$PSVersionTable` (PowerShell) to pick the right variant. In Claude Code on Windows, the shell is Git Bash so POSIX syntax works.

### Path reference

| Bash | PowerShell | Notes |
|------|-----------|-------|
| `~/.fluentcommerce/` | `$env:USERPROFILE\.fluentcommerce\` | Home directory |
| `2>/dev/null` | `-ErrorAction SilentlyContinue` | Suppress errors |
| `mkdir -p <path>` | `New-Item -ItemType Directory -Force -Path <path>` | Create nested dirs |
| `ls <path>` | `Get-ChildItem <path>` | List directory |
| `ls <path> \| wc -l` | `(Get-ChildItem <path>).Count` | Count files |
| `ls -lt <path> \| head -5` | `Get-ChildItem <path> \| Sort-Object LastWriteTime -Descending \| Select-Object -First 5` | Most recent files |
| `find <path> -name "*.jar"` | `Get-ChildItem <path> -Recurse -Filter "*.jar"` | Recursive file search |
| `unzip -p file.jar entry` | `[System.IO.Compression.ZipFile]::OpenRead(...)` | Extract from JAR/ZIP |

### Windows-specific notes

- The `fluent` CLI must be in PATH.
- Workflow filenames may fail on Windows when names include reserved characters (for example `::`); use `--json` export + filename normalization fallback.
- `java`, `mvn`, and `jar` commands work identically on all platforms if installed and in PATH.

## 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-connect"`
   - `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-connect.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 -->
