@fluentcommerce/ai-skills 0.1.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +622 -0
  3. package/bin/cli.mjs +1973 -0
  4. package/content/cli/agents/fluent-cli/agent.json +149 -0
  5. package/content/cli/agents/fluent-cli.md +132 -0
  6. package/content/cli/skills/fluent-bootstrap/SKILL.md +181 -0
  7. package/content/cli/skills/fluent-cli-index/SKILL.md +63 -0
  8. package/content/cli/skills/fluent-cli-mcp-cicd/SKILL.md +77 -0
  9. package/content/cli/skills/fluent-cli-reference/SKILL.md +1031 -0
  10. package/content/cli/skills/fluent-cli-retailer/SKILL.md +85 -0
  11. package/content/cli/skills/fluent-cli-settings/SKILL.md +106 -0
  12. package/content/cli/skills/fluent-connect/SKILL.md +886 -0
  13. package/content/cli/skills/fluent-module-deploy/SKILL.md +349 -0
  14. package/content/cli/skills/fluent-profile/SKILL.md +180 -0
  15. package/content/cli/skills/fluent-workflow/SKILL.md +310 -0
  16. package/content/dev/agents/fluent-dev/agent.json +88 -0
  17. package/content/dev/agents/fluent-dev.md +525 -0
  18. package/content/dev/reference-modules/catalog.json +4754 -0
  19. package/content/dev/skills/fluent-build/SKILL.md +192 -0
  20. package/content/dev/skills/fluent-connection-analysis/SKILL.md +386 -0
  21. package/content/dev/skills/fluent-custom-code/SKILL.md +895 -0
  22. package/content/dev/skills/fluent-data-module-scaffold/SKILL.md +714 -0
  23. package/content/dev/skills/fluent-e2e-test/SKILL.md +394 -0
  24. package/content/dev/skills/fluent-event-api/SKILL.md +945 -0
  25. package/content/dev/skills/fluent-feature-explain/SKILL.md +603 -0
  26. package/content/dev/skills/fluent-feature-plan/PLAN_TEMPLATE.md +695 -0
  27. package/content/dev/skills/fluent-feature-plan/SKILL.md +227 -0
  28. package/content/dev/skills/fluent-job-batch/SKILL.md +138 -0
  29. package/content/dev/skills/fluent-mermaid-validate/SKILL.md +86 -0
  30. package/content/dev/skills/fluent-module-scaffold/SKILL.md +1928 -0
  31. package/content/dev/skills/fluent-module-validate/SKILL.md +775 -0
  32. package/content/dev/skills/fluent-pre-deploy-check/SKILL.md +1108 -0
  33. package/content/dev/skills/fluent-retailer-config/SKILL.md +1111 -0
  34. package/content/dev/skills/fluent-rule-scaffold/SKILL.md +385 -0
  35. package/content/dev/skills/fluent-scope-decompose/SKILL.md +1021 -0
  36. package/content/dev/skills/fluent-session-audit-export/SKILL.md +632 -0
  37. package/content/dev/skills/fluent-session-summary/SKILL.md +195 -0
  38. package/content/dev/skills/fluent-settings/SKILL.md +1058 -0
  39. package/content/dev/skills/fluent-source-onboard/SKILL.md +632 -0
  40. package/content/dev/skills/fluent-system-monitoring/SKILL.md +767 -0
  41. package/content/dev/skills/fluent-test-data/SKILL.md +513 -0
  42. package/content/dev/skills/fluent-trace/SKILL.md +1143 -0
  43. package/content/dev/skills/fluent-transition-api/SKILL.md +346 -0
  44. package/content/dev/skills/fluent-version-manage/SKILL.md +744 -0
  45. package/content/dev/skills/fluent-workflow-analyzer/SKILL.md +959 -0
  46. package/content/dev/skills/fluent-workflow-builder/SKILL.md +319 -0
  47. package/content/dev/skills/fluent-workflow-deploy/SKILL.md +267 -0
  48. package/content/mcp-extn/agents/fluent-mcp.md +69 -0
  49. package/content/mcp-extn/skills/fluent-mcp-tools/SKILL.md +461 -0
  50. package/content/mcp-official/agents/fluent-mcp-core.md +91 -0
  51. package/content/mcp-official/skills/fluent-mcp-core/SKILL.md +94 -0
  52. package/content/rfl/agents/fluent-rfl.md +56 -0
  53. package/content/rfl/skills/fluent-rfl-assess/SKILL.md +172 -0
  54. package/docs/CAPABILITY_MAP.md +77 -0
  55. package/docs/CLI_COVERAGE.md +47 -0
  56. package/docs/DEV_WORKFLOW.md +802 -0
  57. package/docs/FLOW_RUN.md +142 -0
  58. package/docs/USE_CASES.md +404 -0
  59. package/metadata.json +156 -0
  60. package/package.json +51 -0
@@ -0,0 +1,886 @@
1
+ ---
2
+ name: fluent-connect
3
+ 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".
4
+ user-invocable: true
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
6
+ argument-hint: [--profile <name>] [--retailer <ref>] [--force]
7
+ ---
8
+
9
+ # Fluent Account Connect
10
+
11
+ 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.
12
+
13
+ ## Ownership Boundary
14
+
15
+ 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.
16
+
17
+ - Profile creation from scratch is owned by `/fluent-profile`.
18
+ - Full new-account bootstrap is owned by `/fluent-bootstrap`.
19
+ - MCP tool reference is owned by `/fluent-mcp-tools`.
20
+ - Workflow analysis is owned by `/fluent-workflow-analyzer`.
21
+ - Source code analysis is owned by `/fluent-custom-code`.
22
+ - Module validation is owned by `/fluent-module-validate`.
23
+
24
+ ## When to Use
25
+
26
+ - "Connect me to an existing Fluent account"
27
+ - "Switch to a different account / retailer"
28
+ - "Set up my workspace for this profile"
29
+ - "Get me ready to work on [account]"
30
+ - "Onboard me" / "get started"
31
+ - "Setup workspace" / "initialize workspace"
32
+ - Re-running to validate an already-connected workspace
33
+
34
+ ## Inputs
35
+
36
+ | Parameter | Required | Source | Description |
37
+ |-----------|----------|--------|-------------|
38
+ | `--profile <name>` | No | Argument or interactive | CLI profile name. If omitted, wizard discovers and asks. |
39
+ | `--retailer <ref>` | No | Argument or interactive | Retailer ref within the profile. If omitted, wizard discovers and asks. |
40
+ | `--force` | No | Argument | Ignore cached state, re-run full discovery even if nothing changed. |
41
+
42
+ If both `--profile` and `--retailer` are provided, skip the interactive selection phases and proceed directly to wiring and validation.
43
+
44
+ ---
45
+
46
+ ## Phase 0: Cache Check
47
+
48
+ Before doing any work, check if workspace state is already current.
49
+
50
+ ### Steps
51
+
52
+ 1. Read `accounts/<PROFILE>/workspace-state.json` — if missing, proceed to Phase 1.
53
+ 2. Compute a content hash (see Content Hash section) and compare with `contentHash` in the stored state.
54
+ 3. If hashes match and `--force` is NOT set:
55
+ - Print the stored summary (profile, retailer, workflow count, source repo count, entity counts).
56
+ - Print "Workspace state is current. Use --force to re-run."
57
+ - **Stop here.**
58
+ 4. If hashes differ or `--force` is set: continue to Phase 1.
59
+
60
+ If `--profile` was not given, skip cache check and go to Phase 1 (need to discover profiles first).
61
+
62
+ ---
63
+
64
+ ## Phase 1: Profile Discovery
65
+
66
+ ### Step 1.1: List CLI profiles
67
+
68
+ ```bash
69
+ fluent profile list
70
+ ```
71
+
72
+ Also scan the filesystem for profile directories:
73
+
74
+ ```bash
75
+ ls ~/.fluentcommerce/
76
+ ```
77
+
78
+ ```powershell
79
+ # PowerShell
80
+ Get-ChildItem "$env:USERPROFILE\.fluentcommerce"
81
+ ```
82
+
83
+ Each subdirectory (excluding `.sessions`, `config.json`) is a potential profile. Each contains `profile.json` with `id`, `baseUrl`, `clientSecret`, `user`.
84
+
85
+ ### Step 1.2: Present profiles to user
86
+
87
+ Read each `~/.fluentcommerce/<PROFILE>/profile.json` and build a summary table:
88
+
89
+ | # | Profile | Account | Environment | Base URL |
90
+ |---|---------|---------|-------------|----------|
91
+ | 1 | PROFILE_A | acme | sandbox | acme.sandbox.api.fluentretail.com |
92
+ | 2 | PROFILE_B | globex | test | globex.test.api.fluentretail.com |
93
+
94
+ **Account identification from base URL:**
95
+ - Pattern: `https://<account>[.<environment>].api.fluentretail.com`
96
+ - `.test.` = test environment
97
+ - `.sandbox.` = sandbox environment
98
+ - No qualifier = **production** (flag with warning)
99
+
100
+ ### Step 1.3: Select profile
101
+
102
+ If `--profile` was provided, validate it exists in the list. If not, **ask the user** to pick from the discovered profiles.
103
+
104
+ **If no profiles exist at all:**
105
+
106
+ > No CLI profiles found. You need to create one first.
107
+ > Use `/fluent-profile` to create a profile, or `/fluent-bootstrap` for a complete new account setup.
108
+
109
+ Stop and delegate.
110
+
111
+ ---
112
+
113
+ ## Phase 2: Retailer Selection
114
+
115
+ ### Step 2.1: Discover retailers for selected profile
116
+
117
+ Read retailer files from the profile directory:
118
+
119
+ ```bash
120
+ ls ~/.fluentcommerce/<PROFILE>/retailer.*.json
121
+ ```
122
+
123
+ ```powershell
124
+ # PowerShell
125
+ Get-ChildItem "$env:USERPROFILE\.fluentcommerce\<PROFILE>\retailer.*.json"
126
+ ```
127
+
128
+ Each file is named `retailer.<REF>.json` and contains:
129
+ ```json
130
+ { "id": "<retailer_id>", "ref": "<ref>", "user": "<username>" }
131
+ ```
132
+
133
+ ### Step 2.2: Present retailers to user
134
+
135
+ | # | Retailer Ref | Retailer ID | User |
136
+ |---|-------------|-------------|------|
137
+ | 1 | MY_RETAILER | 5 | retailer_admin |
138
+ | 2 | OTHER_RETAILER | 3 | other_admin |
139
+
140
+ ### Step 2.3: Select retailer
141
+
142
+ If `--retailer` was provided, validate it matches a known retailer file. If not, **ask the user** to pick.
143
+
144
+ **If no retailers are configured:**
145
+
146
+ > No retailers found for profile `<PROFILE>`. You can:
147
+ > 1. Register an existing retailer: `fluent profile update <PROFILE> --retailer <REF> --id <ID>`
148
+ > 2. Create a new retailer: use `/fluent-cli-retailer`
149
+ > 3. Full account setup: use `/fluent-bootstrap`
150
+
151
+ ### Step 2.4: Confirm target
152
+
153
+ Display the confirmed target before proceeding:
154
+
155
+ ```
156
+ Target environment:
157
+ Profile: <PROFILE>
158
+ Account: <account>
159
+ Environment: <tier>
160
+ Base URL: https://<account>.<tier>.api.fluentretail.com
161
+ Retailer: <RETAILER_REF> (ID: <RETAILER_ID>)
162
+ User: <username>
163
+ ```
164
+
165
+ > **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.
166
+
167
+ ---
168
+
169
+ ## Phase 3: MCP Wiring
170
+
171
+ ### Step 3.1: Check current configuration
172
+
173
+ Read `.mcp.json` in the workspace root. Check if it already targets the selected profile and retailer:
174
+
175
+ - `mcpServers["fluent-mcp"].env.FLUENT_PROFILE` matches selected profile?
176
+ - `mcpServers["fluent-mcp-extn"].env.FLUENT_PROFILE` matches selected profile?
177
+ - `mcpServers["fluent-mcp-extn"].env.FLUENT_PROFILE_RETAILER` matches selected retailer ref?
178
+
179
+ **If already configured correctly:** Report "Already connected to <PROFILE>/<RETAILER>. Validating connectivity..." and skip to Step 3.4.
180
+
181
+ **If switching from a different profile:** Warn the user: "Currently connected to <OLD_PROFILE>. Switching to <NEW_PROFILE>."
182
+
183
+ ### Step 3.2: Update .mcp.json
184
+
185
+ Run the existing mcp-setup command:
186
+
187
+ ```bash
188
+ npx @fluentcommerce/ai-skills mcp-setup --profile <PROFILE> --profile-retailer <RETAILER_REF>
189
+ ```
190
+
191
+ This updates `.mcp.json` with:
192
+ - `fluent-mcp` server: `FLUENT_PROFILE=<PROFILE>`
193
+ - `fluent-mcp-extn` server: `FLUENT_PROFILE=<PROFILE>`, `FLUENT_PROFILE_RETAILER=<RETAILER_REF>`
194
+
195
+ The command uses merge semantics — it preserves existing non-conflicting env vars.
196
+
197
+ ### Step 3.3: Read and verify .mcp.json
198
+
199
+ 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.
200
+
201
+ ### Step 3.4: Prompt IDE reload
202
+
203
+ > **ACTION REQUIRED:** The MCP servers read environment variables at startup.
204
+ > You must reload the MCP servers for the new configuration to take effect.
205
+ >
206
+ > - **VS Code:** Restart the extension host or reload window
207
+ > - **Claude Code CLI:** Restart the session
208
+ > - **Cursor:** Cmd+Shift+P -> "MCP: Restart Servers"
209
+ >
210
+ > After reloading, confirm you are back and I will validate connectivity.
211
+
212
+ **WAIT for user to confirm they have reloaded before proceeding.**
213
+
214
+ ### Step 3.5: Validate connectivity
215
+
216
+ After user confirms reload:
217
+
218
+ 1. Run `config.validate` (MCP tool) — verify auth strategy is "profile" and no errors
219
+ 2. Run `connection.test` (MCP tool) — verify authenticated user, retailer ID, and retailer ref match expectations
220
+
221
+ **If config.validate returns errors:**
222
+ - Profile load failure: check `~/.fluentcommerce/<PROFILE>/profile.json` exists and is valid JSON
223
+ - Auth not configured: check `.mcp.json` env vars are correct
224
+ - Missing retailer scope: check `FLUENT_PROFILE_RETAILER` is set
225
+
226
+ **If connection.test fails:**
227
+ - Auth error: credentials may be expired. Suggest `fluent profile update <PROFILE> --username <user> --password <pass>`
228
+ - Network error: check base URL and connectivity
229
+
230
+ Report the connection status:
231
+
232
+ ```
233
+ MCP Connectivity: OK
234
+ Auth strategy: profile
235
+ User: <username>
236
+ Retailer: <RETAILER_REF> (ID: <RETAILER_ID>)
237
+ Base URL: https://<account>.<tier>.api.fluentretail.com
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Phase 4: Workspace Readiness
243
+
244
+ ### Step 4.1: Ensure workspace directories exist
245
+
246
+ ```bash
247
+ mkdir -p accounts/<PROFILE>/SOURCE
248
+ mkdir -p accounts/<PROFILE>/workflows/<RETAILER_REF>
249
+ mkdir -p accounts/<PROFILE>/analysis
250
+ ```
251
+
252
+ ```powershell
253
+ # PowerShell
254
+ New-Item -ItemType Directory -Force -Path "accounts\<PROFILE>\SOURCE", "accounts\<PROFILE>\workflows\<RETAILER_REF>", "accounts\<PROFILE>\analysis"
255
+ ```
256
+
257
+ Directory structure:
258
+
259
+ ```
260
+ accounts/
261
+ <PROFILE>/
262
+ SOURCE/ <- account-level, shared across retailers
263
+ <repo-name>/
264
+ .decompiled/<jar-basename>/
265
+ workflows/ <- retailer-scoped workflow JSONs
266
+ <RETAILER_REF>/
267
+ ORDER__HD.json
268
+ analysis/ <- generated reusable artifacts
269
+ workspace-state.json
270
+ ```
271
+
272
+ 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.
273
+
274
+ These are idempotent. On Windows with Git Bash, forward slashes and `mkdir -p` work correctly.
275
+
276
+ ### Step 4.2: Check and download workflows
277
+
278
+ Check if workflows directory has content:
279
+
280
+ ```bash
281
+ ls accounts/<PROFILE>/workflows/<RETAILER_REF>/*.json 2>/dev/null | wc -l
282
+ ```
283
+
284
+ ```powershell
285
+ # PowerShell
286
+ (Get-ChildItem "accounts\<PROFILE>\workflows\<RETAILER_REF>\*.json" -ErrorAction SilentlyContinue).Count
287
+ ```
288
+
289
+ **If empty (count is 0):**
290
+
291
+ **Preferred: MCP-based download (cross-platform, avoids `::` filename issue):**
292
+
293
+ ```
294
+ 1. workflow.list(profile: "<PROFILE>", retailer: "<RETAILER_REF>")
295
+ → get all workflow names (e.g., ORDER::HD, FULFILMENT::HD_WH)
296
+
297
+ 2. For each workflow name:
298
+ a. workflow.download(profile: "<PROFILE>", retailer: "<RETAILER_REF>", workflow: "<NAME>")
299
+ → returns full JSON content in response (no file written)
300
+ b. Sanitize filename: replace :: with __ (e.g., ORDER::HD → ORDER__HD.json)
301
+ c. Write JSON content to accounts/<PROFILE>/workflows/<RETAILER_REF>/<SANITIZED_NAME>.json
302
+
303
+ 3. Write workflow-file-map.json mapping original names to sanitized filenames:
304
+ { "ORDER::HD": "ORDER__HD.json", "FULFILMENT::HD_WH": "FULFILMENT__HD_WH.json" }
305
+ ```
306
+
307
+ This approach works identically on Windows, macOS, and Linux because `::` never appears in a filename.
308
+
309
+ **Fallback: CLI download (if MCP servers not yet connected):**
310
+
311
+ On macOS/Linux (`::` is valid in filenames):
312
+
313
+ ```bash
314
+ fluent workflow list -p <PROFILE> -r <RETAILER_REF>
315
+ fluent workflow download -p <PROFILE> -r <RETAILER_REF> -w all -o accounts/<PROFILE>/workflows/<RETAILER_REF>/
316
+ ```
317
+
318
+ On Windows (both `-w <name>` and `-w all` fail because the CLI writes `ORDER::HD.json` and `:` is reserved):
319
+
320
+ ```bash
321
+ fluent workflow download -p <PROFILE> -r <RETAILER_REF> -w all --json > accounts/<PROFILE>/workflows/<RETAILER_REF>/workflows-raw.json
322
+ ```
323
+
324
+ Then split into one file per workflow with sanitized names (replace `::` with `__`) and persist `workflow-file-map.json` mapping original workflow name to filename.
325
+
326
+ Write/update workflow context:
327
+
328
+ `accounts/<PROFILE>/workflows/<RETAILER_REF>/workflow-context.json`
329
+
330
+ ```json
331
+ {
332
+ "profile": "<PROFILE>",
333
+ "retailerRef": "<RETAILER_REF>",
334
+ "retailerId": "<RETAILER_ID>",
335
+ "downloadedAt": "<ISO-8601>"
336
+ }
337
+ ```
338
+
339
+ Note: `-r` expects retailer **ref** (e.g., `MY_RETAILER`), not retailer ID.
340
+
341
+ **If workflows already exist:**
342
+
343
+ Report count and freshness. If most recent file is older than 7 days, suggest re-downloading:
344
+
345
+ ```bash
346
+ ls -lt accounts/<PROFILE>/workflows/<RETAILER_REF>/*.json | head -5
347
+ ```
348
+
349
+ ```powershell
350
+ # PowerShell
351
+ Get-ChildItem "accounts\<PROFILE>\workflows\<RETAILER_REF>\*.json" | Sort-Object LastWriteTime -Descending | Select-Object -First 5
352
+ ```
353
+
354
+ 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.
355
+
356
+ ### Step 4.3: Check source code
357
+
358
+ ```bash
359
+ ls accounts/<PROFILE>/SOURCE/ 2>/dev/null
360
+ ```
361
+
362
+ ```powershell
363
+ # PowerShell
364
+ Get-ChildItem "accounts\<PROFILE>\SOURCE" -ErrorAction SilentlyContinue
365
+ ```
366
+
367
+ **If repos with Java source found:**
368
+
369
+ Report discovered repos. Validate each has expected structure (`module.json`, `pom.xml`, or `src/main/java/`).
370
+
371
+ **Extract module identity (version + symbolic name):**
372
+
373
+ For each discovered repo, extract identity using this precedence:
374
+
375
+ `symbolicName`:
376
+ 1. `resources/module.json` → `name` field (preferred)
377
+ 2. JAR `META-INF/MANIFEST.MF` → `Bundle-SymbolicName` (if present)
378
+ 3. POM fallback → `<groupId>/<artifactId>` (or `<artifactId>` alone if `groupId` missing)
379
+
380
+ `version`:
381
+ 1. `resources/module.json` → `version` field (preferred)
382
+ 2. POM → `<project><version>` (fallback to `<project><parent><version>` if module version is omitted or inherited)
383
+ 3. JAR manifest → `Implementation-Version` or `Bundle-Version`
384
+
385
+ POM extraction examples:
386
+
387
+ ```xml
388
+ <!-- Direct version -->
389
+ <project>
390
+ <groupId>com.fluentcommerce</groupId>
391
+ <artifactId>fc-module-extensions</artifactId>
392
+ <version>1.2.3</version>
393
+ <name>FC Module Extensions</name>
394
+ </project>
395
+
396
+ <!-- Inherited version (no <version> at project level) -->
397
+ <project>
398
+ <parent>
399
+ <version>1.2.3</version>
400
+ </parent>
401
+ <artifactId>fc-module-extensions</artifactId>
402
+ </project>
403
+ ```
404
+
405
+ Record where each value came from (e.g., `versionSource: "module.json"` or `versionSource: "pom.parent.version"`) for traceability.
406
+
407
+ Report format (classify each by type):
408
+
409
+ ```
410
+ Source code:
411
+ Custom Extension (editable, buildable):
412
+ - <repo-name-1>/ <symbolic-name> v<X.Y.Z> (N rules, Maven)
413
+ Configuration-Only (editable, not buildable):
414
+ - <repo-name-2>/ <symbolic-name> v<X.Y.Z> (workflows + settings, no rules)
415
+ Reference Modules (read-only):
416
+ - <module-name>/ <symbolic-name> v<X.Y.Z> (N OOTB rules, JAR)
417
+ ```
418
+
419
+ **Handle double-nested git clone directories:**
420
+ 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.
421
+
422
+ **If reference module packages found (module.json + JAR):**
423
+
424
+ 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.
425
+
426
+ **If only standalone JAR files found (no module.json alongside):**
427
+
428
+ When a module is deployed but the original source code is not available, look for `.jar` files under `SOURCE/`. If a JAR is found, decompile it to produce browsable source for analysis:
429
+
430
+ 1. **Locate JARs:**
431
+
432
+ Use `Glob` with pattern `accounts/<PROFILE>/SOURCE/**/*.jar` for cross-platform file discovery. Exclude `target/dependency/` results.
433
+
434
+ ```bash
435
+ find accounts/<PROFILE>/SOURCE/ -name "*.jar" -not -path "*/target/dependency/*" 2>/dev/null
436
+ ```
437
+
438
+ ```powershell
439
+ # PowerShell
440
+ Get-ChildItem "accounts\<PROFILE>\SOURCE" -Recurse -Filter "*.jar" | Where-Object { $_.FullName -notlike "*\target\dependency\*" }
441
+ ```
442
+
443
+ 2. **Auto-download CFR decompiler if not present, then decompile:**
444
+
445
+ > **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.
446
+
447
+ ```bash
448
+ # Auto-download CFR (~2MB single JAR, no installation needed)
449
+ if [ ! -f tools/cfr.jar ]; then
450
+ mkdir -p tools
451
+ curl -L -o tools/cfr.jar "https://github.com/leibnitz27/cfr/releases/download/0.152/cfr-0.152.jar"
452
+ fi
453
+
454
+ # Create deterministic decompiled output directory
455
+ mkdir -p accounts/<PROFILE>/SOURCE/.decompiled/<jar-basename>
456
+
457
+ # Option A: CFR with --jarfilter to extract only rule classes (preferred)
458
+ java -jar tools/cfr.jar "<jar-file>.jar" \
459
+ --outputdir "accounts/<PROFILE>/SOURCE/.decompiled/<jar-basename>" \
460
+ --jarfilter "com.fluentcommerce.rule"
461
+
462
+ # Option B: CFR full decompilation (all classes)
463
+ java -jar tools/cfr.jar "<jar-file>.jar" \
464
+ --outputdir "accounts/<PROFILE>/SOURCE/.decompiled/<jar-basename>"
465
+
466
+ # Option C: Fernflower (IntelliJ's built-in decompiler)
467
+ java -jar fernflower.jar <jar-file>.jar accounts/<PROFILE>/SOURCE/.decompiled/<jar-basename>
468
+
469
+ # Option D: If neither is available, use javap for class listing
470
+ jar tf <jar-file>.jar | grep "\.class$"
471
+ ```
472
+
473
+ ```powershell
474
+ # PowerShell — auto-download CFR
475
+ if (-not (Test-Path "tools\cfr.jar")) {
476
+ New-Item -ItemType Directory -Force -Path "tools"
477
+ Invoke-WebRequest -Uri "https://github.com/leibnitz27/cfr/releases/download/0.152/cfr-0.152.jar" -OutFile "tools\cfr.jar"
478
+ }
479
+
480
+ # CFR with --jarfilter
481
+ java -jar tools/cfr.jar "<jar-file>.jar" --outputdir "accounts\<PROFILE>\SOURCE\.decompiled\<jar-basename>" --jarfilter "com.fluentcommerce.rule"
482
+ ```
483
+
484
+ The `--jarfilter` flag restricts decompilation to classes matching the package prefix, keeping output focused on rule logic. If no decompiler is available and `curl`/Java is missing, log a warning and skip decompilation. Record JAR paths for later.
485
+
486
+ 3. **Extract module.json from the JAR** (if present):
487
+
488
+ ```bash
489
+ unzip -p <jar-file>.jar module.json > accounts/<PROFILE>/SOURCE/.decompiled/<jar-basename>/module.json
490
+ ```
491
+
492
+ ```powershell
493
+ # PowerShell
494
+ Add-Type -AssemblyName System.IO.Compression.FileSystem
495
+ $jar = [System.IO.Compression.ZipFile]::OpenRead("<jar-file>.jar")
496
+ $entry = $jar.GetEntry("module.json")
497
+ if ($entry) {
498
+ $stream = $entry.Open()
499
+ $reader = New-Object System.IO.StreamReader($stream)
500
+ $reader.ReadToEnd() | Set-Content "accounts\<PROFILE>\SOURCE\.decompiled\<jar-basename>\module.json"
501
+ $reader.Close(); $stream.Close()
502
+ }
503
+ $jar.Dispose()
504
+ ```
505
+
506
+ 4. **Create a `DECOMPILED.md` marker file** in the decompiled output directory:
507
+
508
+ ```markdown
509
+ # Decompiled Source
510
+
511
+ - **Source JAR:** <jar-filename>.jar
512
+ - **Decompiled on:** <date>
513
+ - **Decompiler:** CFR / Fernflower / javap
514
+ - **Note:** This is decompiled bytecode, not original source. Variable names may be synthetic. Comments and annotations may be incomplete.
515
+ ```
516
+
517
+ After decompilation, `/fluent-custom-code` can analyze the decompiled classes for rule discovery, workflow-rule mapping, and behavior explanation.
518
+
519
+ > **Decompilation limitations:**
520
+ > - Local variable names may be replaced with synthetic names (`var1`, `var2`)
521
+ > - Comments, Javadoc, and some annotations may be lost
522
+ > - Generic type information may be partially erased
523
+ > - Confidence label should be "low-medium" for decompiled source vs "high" for original
524
+
525
+ **If neither source nor JAR found:**
526
+
527
+ > No custom source code or JAR files found under `accounts/<PROFILE>/SOURCE/`.
528
+ > This is not blocking — it means no custom plugins are available for analysis.
529
+ >
530
+ > Options:
531
+ > 1. Clone source repos: `git clone <repo-url>` into `accounts/<PROFILE>/SOURCE/`
532
+ > 2. Copy module JARs: place `.jar` files in `accounts/<PROFILE>/SOURCE/` for decompilation
533
+ > 3. Download from Fluent: if the module is deployed, the JAR may be retrievable from the build artifacts
534
+
535
+ ### Step 4.4: Build deployed rule inventory
536
+
537
+ Query the live environment for the complete picture of what's deployed.
538
+
539
+ **4.4a: Query deployed custom rules**
540
+
541
+ Use the MCP `plugin.list` tool to get all registered orchestration rules. Filter for account-specific rules (prefixed with the account context, not `FLUENTRETAIL.*`):
542
+
543
+ ```
544
+ plugin.list → N total rules
545
+ - FLUENTRETAIL.* → platform rules (standard, no source needed)
546
+ - <ACCOUNT>.* → custom rules (these need source or JARs)
547
+ ```
548
+
549
+ **4.4b: Cross-reference deployed vs local**
550
+
551
+ For each custom rule discovered in the live registry:
552
+
553
+ | Deployed Rule | Local Source? | Local JAR? | Status |
554
+ |---------------|--------------|------------|--------|
555
+ | `<ACCOUNT>.<module>.<RuleName>` | `SOURCE/<repo>/...RuleName.java` | - | Full source |
556
+ | `<ACCOUNT>.<module>.<OtherRule>` | - | `SOURCE/<module>.jar` | Decompiled |
557
+ | `<ACCOUNT>.<module>.<UnknownRule>` | - | - | **Missing** |
558
+
559
+ **4.4c: Report the inventory**
560
+
561
+ ```
562
+ Deployed Rule Inventory:
563
+ Total custom rules deployed: N
564
+ With full source code: X (modifiable)
565
+ With decompiled source (JAR): Y (read-only, can analyze)
566
+ Missing (no source or JAR): Z (cannot analyze)
567
+ ```
568
+
569
+ **4.4d: Recommendations based on inventory**
570
+
571
+ - **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.
572
+ - **JAR-only** modules: can analyze behavior via decompiled source. Cannot modify directly. Recommend cloning original source or scaffolding a new extension module.
573
+ - **Missing** modules: flag as a gap. Ask the user to provide the source or JAR.
574
+
575
+ > **Important:** JAR-decompiled source is read-only for analysis. Never suggest editing decompiled files.
576
+
577
+ ### Step 4.5: Entity count queries
578
+
579
+ Run lightweight discovery queries to understand what's configured:
580
+
581
+ ```graphql
582
+ { locations(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
583
+ { networks(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
584
+ { inventoryCatalogues(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
585
+ { productCatalogues(first: 1) { edges { node { id } } pageInfo { hasNextPage } } }
586
+ ```
587
+
588
+ Record presence/absence and approximate counts.
589
+
590
+ ### Step 4.6: Check analysis artifacts
591
+
592
+ ```bash
593
+ ls accounts/<PROFILE>/analysis/ 2>/dev/null
594
+ ```
595
+
596
+ ```powershell
597
+ # PowerShell
598
+ Get-ChildItem "accounts\<PROFILE>\analysis" -ErrorAction SilentlyContinue
599
+ ```
600
+
601
+ 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.
602
+
603
+ If the user explicitly asked for source analysis/readiness artifacts, run `/fluent-custom-code <PROFILE> --retailer <RETAILER_REF>` now instead of deferring.
604
+
605
+ ---
606
+
607
+ ## Phase 5: Persist State and Report
608
+
609
+ ### Step 5.1: Write per-profile state
610
+
611
+ Write `accounts/<PROFILE>/workspace-state.json`:
612
+
613
+ ```json
614
+ {
615
+ "schema": "workspace-state-v1",
616
+ "profile": "<PROFILE>",
617
+ "contentHash": "<sha256-hex>",
618
+ "createdAt": "<ISO-8601>",
619
+ "updatedAt": "<ISO-8601>",
620
+ "environment": {
621
+ "account": "<account-name>",
622
+ "tier": "<test|sandbox|production>",
623
+ "baseUrl": "<base-url>",
624
+ "retailerRef": "<RETAILER_REF>",
625
+ "retailerId": "<RETAILER_ID>"
626
+ },
627
+ "discovery": {
628
+ "workflows": { "count": 0, "downloaded": true, "path": "accounts/<PROFILE>/workflows/<RETAILER_REF>" },
629
+ "modules": { "installed": [], "count": 0 },
630
+ "sourceRepos": [
631
+ { "name": "<repo-name>", "symbolicName": "<symbolic-name>", "version": "<X.Y.Z>", "versionSource": "<module.json|pom|pom.parent>", "hasModuleJson": true, "ruleCount": 0 }
632
+ ],
633
+ "decompiledRepos": [],
634
+ "entities": { "locations": 0, "networks": 0, "inventoryCatalogues": 0, "productCatalogues": 0 },
635
+ "ruleInventory": { "total": 0, "withSource": 0, "withJar": 0, "missing": 0 },
636
+ "connectivity": { "status": "OK", "user": "<username>", "retailer": "<tradingName>" }
637
+ },
638
+ "mcpConfig": { "exists": true, "hasOfficialServer": true, "hasExtensionServer": true, "profileMatch": true },
639
+ "nextSteps": []
640
+ }
641
+ ```
642
+
643
+ ### Step 5.2: Write/merge workspace index
644
+
645
+ Write or merge into `accounts/workspace-index.json`:
646
+
647
+ ```json
648
+ {
649
+ "schema": "workspace-index-v1",
650
+ "updatedAt": "<ISO-8601>",
651
+ "profiles": {
652
+ "<PROFILE>": {
653
+ "status": "READY",
654
+ "retailer": "<RETAILER_REF>",
655
+ "account": "<account-name>",
656
+ "tier": "<tier>",
657
+ "stateHash": "<sha256-hex>"
658
+ }
659
+ }
660
+ }
661
+ ```
662
+
663
+ If the index already exists, read it first and merge the new profile entry. Do not overwrite other profiles.
664
+
665
+ ### Step 5.3: Readiness report
666
+
667
+ Present a comprehensive summary:
668
+
669
+ ```
670
+ ================================================================
671
+ FLUENT CONNECT: Readiness Report
672
+ ================================================================
673
+
674
+ Profile: <PROFILE>
675
+ Account: <account> (<tier>)
676
+ Retailer: <RETAILER_REF> (ID: <RETAILER_ID>)
677
+ User: <username>
678
+
679
+ MCP Status:
680
+ fluent-mcp [OK] Profile auth
681
+ fluent-mcp-extn [OK] Profile auth + retailer scope
682
+
683
+ Workspace:
684
+ Workflows [OK] N files
685
+ Source code [OK] X repos (Y rules with full source)
686
+ JARs [OK] Z decompiled (W rules, read-only)
687
+ Analysis [--] No artifacts yet
688
+
689
+ Modules:
690
+ <symbolic-name-1> v<X.Y.Z> (N rules, source)
691
+ <symbolic-name-2> v<X.Y.Z> (M rules, decompiled)
692
+
693
+ Deployed Rule Inventory:
694
+ Custom rules deployed: N
695
+ With full source: X [modifiable]
696
+ With decompiled JAR: Y [analyzable, read-only]
697
+ Missing source: Z [blind spot]
698
+
699
+ Entities:
700
+ Locations: N
701
+ Networks: N
702
+ Catalogues: N (inventory) / N (product)
703
+
704
+ Suggested Next Steps:
705
+ 1. Full analysis: /fluent-custom-code
706
+ 2. Workflow deep-dive: /fluent-workflow-analyzer
707
+ 3. Create test data: /fluent-test-data
708
+ 4. Run E2E tests: /fluent-e2e-test
709
+ 5. RFL assessment: /fluent-rfl-assess
710
+
711
+ Workspace: accounts/<PROFILE>/ (source shared, retailer content under <RETAILER_REF>/)
712
+ State saved to: accounts/<PROFILE>/workspace-state.json
713
+ ================================================================
714
+ ```
715
+
716
+ ### Capability Matrix
717
+
718
+ | Capability | Requires | Status Logic |
719
+ |-----------|----------|-------------|
720
+ | GraphQL operations | MCP connected | `connection.test` OK |
721
+ | Event dispatch | MCP connected + retailer scope | connection OK + retailerId present |
722
+ | Workflow analysis | Workflows downloaded | workflow JSON count > 0 |
723
+ | Full code analysis | Source repos present | `SOURCE/` has repos with `src/main/java/` |
724
+ | JAR-based analysis | Decompiled JARs present | `SOURCE/.decompiled/*/` exists |
725
+ | Code + workflow cross-ref | Workflows + any source | workflows + (source or decompiled) |
726
+ | Rule modification | Full source available | repo has original Java + pom.xml |
727
+ | Analysis reuse | Artifacts exist + fresh | `analysis/` has files and not stale |
728
+ | Complete rule coverage | All deployed rules have source | no "missing" in inventory |
729
+
730
+ ### Blocked Capabilities
731
+
732
+ If any capability is blocked, explain what's needed and how to fix it.
733
+
734
+ ---
735
+
736
+ ## Content Hash
737
+
738
+ The content hash determines whether workspace state is current. Recompute on every run and compare with the stored hash.
739
+
740
+ ### What to hash
741
+
742
+ 1. **Profile config:** `~/.fluentcommerce/<PROFILE>/profile.json`
743
+ 2. **Retailer configs:** all `~/.fluentcommerce/<PROFILE>/retailer.*.json` files
744
+ 3. **Source repo listing:** sorted list of directory names under `accounts/<PROFILE>/SOURCE/`
745
+ 4. **Workflow file listing:** sorted list of `.json` filenames in `accounts/<PROFILE>/workflows/<RETAILER_REF>/`
746
+ 5. **JAR/ZIP listing:** sorted list of `.jar` and `.zip` files under `accounts/<PROFILE>/SOURCE/`
747
+
748
+ ### How to compute
749
+
750
+ Use Node.js (always available):
751
+
752
+ ```bash
753
+ node -e "
754
+ const crypto = require('crypto');
755
+ const fs = require('fs');
756
+ const path = require('path');
757
+ const h = crypto.createHash('sha256');
758
+ const profile = process.argv[1];
759
+ const home = process.env.HOME || process.env.USERPROFILE;
760
+
761
+ // 1. Profile config
762
+ const profFile = path.join(home, '.fluentcommerce', profile, 'profile.json');
763
+ if (fs.existsSync(profFile)) h.update(fs.readFileSync(profFile));
764
+
765
+ // 2. Retailer configs
766
+ const profDir = path.join(home, '.fluentcommerce', profile);
767
+ if (fs.existsSync(profDir)) {
768
+ fs.readdirSync(profDir).filter(f => f.startsWith('retailer.') && f.endsWith('.json')).sort()
769
+ .forEach(f => h.update(fs.readFileSync(path.join(profDir, f))));
770
+ }
771
+
772
+ // 3. Source repo listing
773
+ const srcDir = path.join('accounts', profile, 'SOURCE');
774
+ if (fs.existsSync(srcDir)) {
775
+ fs.readdirSync(srcDir, {withFileTypes:true}).filter(e => e.isDirectory()).map(e => e.name).sort()
776
+ .forEach(n => h.update('src:' + n));
777
+ }
778
+
779
+ // 4. Workflow file listing (retailer-scoped)
780
+ const retailer = process.argv[2];
781
+ const wfDir = path.join('accounts', profile, 'workflows', retailer);
782
+ if (fs.existsSync(wfDir)) {
783
+ fs.readdirSync(wfDir).filter(f => f.endsWith('.json')).sort()
784
+ .forEach(f => h.update('wf:' + f));
785
+ }
786
+
787
+ // 5. JAR/ZIP listing
788
+ if (fs.existsSync(srcDir)) {
789
+ const jars = [];
790
+ function findJars(d) {
791
+ for (const e of fs.readdirSync(d, {withFileTypes:true})) {
792
+ if (['target','dist','node_modules','.git'].includes(e.name)) continue;
793
+ const f = path.join(d, e.name);
794
+ if (e.isDirectory()) findJars(f);
795
+ else if (e.name.endsWith('.jar') || e.name.endsWith('.zip')) jars.push(f.replace(/\\\\/g,'/'));
796
+ }
797
+ }
798
+ findJars(srcDir);
799
+ jars.sort().forEach(j => h.update('jar:' + j));
800
+ }
801
+
802
+ console.log(h.digest('hex'));
803
+ " <PROFILE> <RETAILER_REF>
804
+ ```
805
+
806
+ Any change (new workflow download, new repo clone, profile update, new JAR file) produces a new hash and triggers a re-run.
807
+
808
+ ---
809
+
810
+ ## Idempotency
811
+
812
+ This skill is designed to be run multiple times safely:
813
+
814
+ 1. **Cached state matches:** If content hash hasn't changed, print summary and stop immediately.
815
+ 2. **Already configured:** If `.mcp.json` already targets the correct profile/retailer, skip mcp-setup. Still validate connectivity.
816
+ 3. **Directories exist:** `mkdir -p` is idempotent.
817
+ 4. **Workflows downloaded:** Report count and freshness. Do not re-download unless user requests or `--force` is used.
818
+ 5. **Source cloned:** Report repos found. Do not modify.
819
+ 6. **Artifacts exist:** Report age. Do not regenerate.
820
+
821
+ ### Switching Accounts
822
+
823
+ When the user runs `/fluent-connect` with a different profile than currently configured:
824
+
825
+ 1. Detect the mismatch by reading `.mcp.json` first
826
+ 2. Warn: "Currently connected to <OLD_PROFILE>. Switching to <NEW_PROFILE>."
827
+ 3. Run mcp-setup with the new profile
828
+ 4. Require IDE reload
829
+ 5. Validate the new connection
830
+ 6. Persist new workspace state
831
+ 7. Report readiness for the new account
832
+
833
+ ---
834
+
835
+ ## Error Handling
836
+
837
+ | Phase | Error | Resolution |
838
+ |-------|-------|-----------|
839
+ | 0 | workspace-state.json corrupted | Delete and re-run full discovery |
840
+ | 1 | No profiles exist | Delegate to `/fluent-profile` |
841
+ | 1 | `fluent` CLI not found | Install: `npm i -g @fluentcommerce/cli` |
842
+ | 2 | No retailers for profile | Register via `fluent profile update` or `/fluent-cli-retailer` |
843
+ | 3 | mcp-setup fails | Check `npx @fluentcommerce/ai-skills --help` works and retry mcp-setup |
844
+ | 3 | connection.test auth failure | Update credentials: `fluent profile update <PROFILE> --username <user> --password <pass>` |
845
+ | 3 | connection.test network error | Verify base URL and network access |
846
+ | 4 | Workflow download fails | Check profile/retailer context. May need `fluent profile use <PROFILE> --retailer <REF>` first |
847
+ | 4 | Decompiler not found | Log warning with install instructions. Skip decompilation, record JAR paths for later. |
848
+ | 4 | Permission error on mkdir | Check workspace write permissions |
849
+
850
+ ## Delegation Table
851
+
852
+ | Situation | Delegate To |
853
+ |-----------|------------|
854
+ | No profiles exist | `/fluent-profile` |
855
+ | Need to create new account | `/fluent-bootstrap` |
856
+ | Need to create retailer | `/fluent-cli-retailer` |
857
+ | MCP tool reference | `/fluent-mcp-tools` |
858
+ | Workflow deep analysis | `/fluent-workflow-analyzer` |
859
+ | Source code analysis | `/fluent-custom-code` |
860
+ | Settings management | `/fluent-settings` |
861
+ | Test data creation | `/fluent-test-data` |
862
+
863
+ ## Cross-Platform Compatibility
864
+
865
+ 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.
866
+
867
+ **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.
868
+
869
+ ### Path reference
870
+
871
+ | Bash | PowerShell | Notes |
872
+ |------|-----------|-------|
873
+ | `~/.fluentcommerce/` | `$env:USERPROFILE\.fluentcommerce\` | Home directory |
874
+ | `2>/dev/null` | `-ErrorAction SilentlyContinue` | Suppress errors |
875
+ | `mkdir -p <path>` | `New-Item -ItemType Directory -Force -Path <path>` | Create nested dirs |
876
+ | `ls <path>` | `Get-ChildItem <path>` | List directory |
877
+ | `ls <path> \| wc -l` | `(Get-ChildItem <path>).Count` | Count files |
878
+ | `ls -lt <path> \| head -5` | `Get-ChildItem <path> \| Sort-Object LastWriteTime -Descending \| Select-Object -First 5` | Most recent files |
879
+ | `find <path> -name "*.jar"` | `Get-ChildItem <path> -Recurse -Filter "*.jar"` | Recursive file search |
880
+ | `unzip -p file.jar entry` | `[System.IO.Compression.ZipFile]::OpenRead(...)` | Extract from JAR/ZIP |
881
+
882
+ ### Windows-specific notes
883
+
884
+ - The `fluent` CLI must be in PATH.
885
+ - Workflow filenames may fail on Windows when names include reserved characters (for example `::`); use `--json` export + filename normalization fallback.
886
+ - `java`, `mvn`, and `jar` commands work identically on all platforms if installed and in PATH.