Skip to content

Migrate CLI from picocli to aesh with REPL console mode - #166

Draft
stalep wants to merge 9 commits into
Hyperfoil:mainfrom
stalep:aesh
Draft

Migrate CLI from picocli to aesh with REPL console mode#166
stalep wants to merge 9 commits into
Hyperfoil:mainfrom
stalep:aesh

Conversation

@stalep

@stalep stalep commented Jul 3, 2026

Copy link
Copy Markdown
Member

Replace the picocli-based single-command CLI with an aesh interactive REPL (Read-Eval-Print Loop) shell. Users can now run multiple commands in a single session with tab completion, history, and folder context.

Entity-centric command structure:
folder — add, list, remove, upload, export, import, structure,
recalculate, purge, values
node — add (jq/js/jsonata/sqlpath/sqlpathall/split/fixedthreshold/
relativedifference/stddev), list, remove, update
view — list, show, create, remove, update (--add/--remove/--reorder)
run — list, show, upload
notification — add, list, remove
legacy — load-tests, load-runs, verify
admin — create-user, create-team, add-member, list-users, list-teams,
create-api-key, list-api-keys, revoke-api-key
cd — set active folder context
upload — top-level shortcut for folder upload

Key features:

  • Folder context: 'cd myFolder' sets context, subsequent commands omit --to/--from
  • Tab completion for commands, folder names, and node names
  • acceptNameWithoutDashes on all options (picocli-compatible syntax)
  • @arguments for positional args matching original CLI syntax
  • Default limit of 50 on list commands to prevent OOM
  • Ctrl-C interrupt support (InterruptedException on all commands)
  • generateHelp on all commands (--help shows usage)
  • Views: create views, add/remove node columns, show pivoted data
  • Runs: list uploads, show raw JSON data, per-node value inspection
  • H5mCommandRegistryFactory filters top-level commands for clean tab completion
  • Graceful startup recovery on SQLite (handles missing tables)
  • Upload command awaits CompletableFuture completion before returning
  • Uses aesh Table utility for formatted output
  • NodeNameCompleter for node name tab completion in view/run commands

@stalep
stalep force-pushed the aesh branch 3 times, most recently from f32ed5b to 22bf867 Compare August 5, 2026 14:44
stalep added 9 commits August 6, 2026 09:54
Replace the picocli-based single-command CLI with an aesh interactive
REPL (Read-Eval-Print Loop) shell. Users can now run multiple commands
in a single session with tab completion, history, and folder context.

Entity-centric command structure:
  folder  — add, list, remove, upload, export, import, structure,
            recalculate, purge, values
  node    — add (jq/js/jsonata/sqlpath/sqlpathall/split/fixedthreshold/
            relativedifference/stddev), list, remove, update
  view    — list, show, create, remove, update (--add/--remove/--reorder)
  run     — list, show, upload
  notification — add, list, remove
  legacy  — load-tests, load-runs, verify
  admin   — create-user, create-team, add-member, list-users, list-teams,
            create-api-key, list-api-keys, revoke-api-key
  cd      — set active folder context
  upload  — top-level shortcut for folder upload

Key features:
- Folder context: 'cd myFolder' sets context, subsequent commands omit --to/--from
- Tab completion for commands, folder names, and node names
- acceptNameWithoutDashes on all options (picocli-compatible syntax)
- @arguments for positional args matching original CLI syntax
- Default limit of 50 on list commands to prevent OOM
- Ctrl-C interrupt support (InterruptedException on all commands)
- generateHelp on all commands (--help shows usage)
- Views: create views, add/remove node columns, show pivoted data
- Runs: list uploads, show raw JSON data, per-node value inspection
- H5mCommandRegistryFactory filters top-level commands for clean tab completion
- Graceful startup recovery on SQLite (handles missing tables)
- Upload command awaits CompletableFuture completion before returning
- Uses aesh Table utility for formatted output
- NodeNameCompleter for node name tab completion in view/run commands
Rebase aesh branch on origin/main. Update Quarkus version from
999-SNAPSHOT to 3.38.0 with aesh 3.16.4. Fix Vert.x Buffer import
changes (core → mutiny). Make CLI command fields package-private
to avoid reflective access warnings.

Convert remaining picocli commands to aesh: AddEDivisive,
ListProcessing, RemoveProcessing, ResumeProcessing. Create standalone
AddFingerprint command (replaces --fingerprint flag on AddJq/AddJs).

Fix test command syntax (node jq → node add jq). Remove outdated
null-value assertion for ephemeral-nullified intermediate nodes.

RecalculateCmd placeholder — folder-level recalculate API was removed
by PR Hyperfoil#210, needs reimplementation for CLI.

Detection test failures remain — fingerprint and fixedthreshold nodes
produce correct structure but detection values are not generated.
Requires investigation into work queue completion in REPL test context.
Three root causes fixed:

1. Aesh @option with List<String> stays null — change fingerprint
   option from List<String> to String in AddFixedThreshold,
   AddRelativeDifference, and AddStdDevAnomaly. Split on commas
   in the command code instead. This was causing _fp-* fingerprint
   nodes to be created with empty sources, breaking the cascade
   chain (fp1 -> _fp-ftNode never triggered).

2. Aesh doesn't process backslash-escaped quotes inside double-quoted
   strings — update toCommand() to use single quotes for arguments
   containing double quotes (e.g., JQ expressions like
   .results."quarkus3-jvm".load.avThroughput). This was causing
   JQ compilation errors ('Unexpected character: backslash').

3. Default display limit of 50 truncates QVSS test output — add
   --limit 200 to fixedthreshold_qvss_split_by_framework test.

Also update upload test assertions: intermediate node values are
ephemeral-nullified after processing (correct behavior). Tests now
assert on leaf values only.

All 483 non-CLI tests pass. CLI detection tests (fixedthreshold,
relativedifference, stddev, QVSS throughput/split/regression) pass.
Remaining CLI failures: upload_sqlpath (missing sqlpath command),
and sporadic SQLite SQLITE_BUSY timeouts (pre-existing).
Switch fingerprint option from @option String to @OptionList List<String>
in AddFixedThreshold, AddRelativeDifference, AddStdDevAnomaly, and
AddEDivisive. @OptionList is the correct aesh annotation for multi-valued
options — it handles both --fingerprint fp1 (single value) and
--fingerprint fp1,fp2 (comma-separated) natively.

Pin Quarkus version to 3.38.0 (ships aesh 3.16.4).

Fix Vert.x Buffer imports in notification plugins (GitHubIssuePlugin,
SlackPlugin, WebhookPlugin): io.vertx.core → io.vertx.mutiny.core.
Add 5 tests that simulate real user CLI workflow: cd into a folder
then operate without specifying --to/--from explicitly. Tests cover:
- cd + node add + upload + values (basic context flow)
- cd + node add + node remove (context with node management)
- cd + fixedthreshold + upload (detection nodes with context)
- cd .. to exit folder context
- cd + structure + recalculate (folder-level commands with context)

Fix AddEDivisive: add missing folder context fallback. Every other
node add command had 'if (groupName == null && invocation.hasFolderContext())'
but AddEDivisive was missing it.

Fix AddNotification: remove required=true on --to option. The required
flag caused aesh to reject the command before execute() ran, making
the folder context fallback code unreachable.
…ation

Critical fixes:
- AddSplit was a no-op: validated inputs but never called
  nodeService.create(). Now actually creates the split node.
- UploadCmd and RunUploadCmd: add null check for path argument
  to prevent NullPointerException.
- RemoveFolder: return FAILURE when folder is not found (was
  returning SUCCESS). Also add null check for name argument.

RecalculateCmd reimplemented:
- Was a stub that printed 'not yet supported' and returned SUCCESS.
- Now iterates top-level nodes via NodeGroupServiceInterface and
  calls folderService.recalculateNode() for each, waiting for all
  CompletableFutures with a 10-minute timeout.

Help text and descriptions:
- NodeAddCmd: remove sqlpath/sqlpathall (don't exist), add
  edivisive and fingerprint (do exist).
- NodeCmd: remove sqlpath from description.

Error message fixes:
- Replace 'NodeEntity group' with 'Node group' in ListNode and
  ListValue (internal class name leak).
- Replace 'FolderEntity' with 'Folder' in RemoveFolder.
- Fix missing space in error messages in AddFixedThreshold and
  AddRelativeDifference ('with name<value>' -> 'with name <value>').
RunUploadCmd was a full code duplicate of UploadCmd (identical logic,
only the class name differed). Now extends UploadCmd with just its
own @CommandDefinition. All fields, injection points, and execute()
logic are inherited.
The Quarkus 3.38.0 BOM manages aesh-processor:3.16.4. Omitting the
version from the annotationProcessorPaths entry lets Maven resolve
it from the BOM, keeping the aesh version in sync with Quarkus
automatically. No more manual version tracking needed.
UploadCmd improvements:
- Print processing ID for each uploaded file (single file: 'Processing id: 42',
  directory: 'file.json -> processing id: 42')
- Add --async flag: returns immediately without waiting for processing
- Synchronous mode: after completion, queries ValueService.getDetectionDescendants()
  and displays detection summary with node name, type, details, and fingerprint

New status command:
- 'status 42' or 'status 42 43 44' checks processing state via WorkService.getTracker()
- Returns PROCESSING, COMPLETED, FAILED, or 'not found'
- Falls back to DB check (root value exists) when tracker is cleaned up

New changes command:
- 'changes 42' lists detection values for an upload via ValueService.getDetectionDescendants()
- 'changes 42 --node throughput-regression' filters to a specific detection node
- Formatted output with node name, detection type, key fields, and fingerprint

Shared ChangeFormatter utility for consistent detection value display across
UploadCmd and ChangesCmd.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant