{
  "report_info": {
    "version": "9.0.1",
    "generated_at": "2026-07-21T01:54:40Z",
    "binary_name": "workflow-manager"
  },
  "binary": {
    "name": "workflow-manager",
    "path": "/opt/kodachi/dashboard/hooks/workflow-manager",
    "timestamp": "2026-07-21T01:54:40Z",
    "file_info": {
      "size": 4502848,
      "sha256": "63bf382c55e55fb3bd44067e3fe65b8e0e5aedc87528d6697bf31b306191d18b"
    },
    "flag_n": {
      "command": "info",
      "data": {
        "author": "Warith Al Maawali",
        "copyright": "© 2026 Kodachi OS",
        "description": "Workflow manager for batch command execution with conditional logic",
        "features": [
          "Template-based workflow management",
          "Conditional command execution",
          "Batch processing with retry logic",
          "State tracking and logging",
          "Concurrent execution support",
          "Pause steps with user confirmation",
          "Substring, regex and JSON path conditions",
          "JSON path subset support (dot fields + array indexes)",
          "Prerequisites validation before execution",
          "System state checking and probes",
          "Reusable probe functions for conditions"
        ],
        "license": "Proprietary",
        "name": "workflow-manager",
        "securityFeatures": {
          "authentication": "Not provided by cli-core (see online-auth)",
          "encryption": "Not provided by cli-core",
          "inputValidation": "Argument parsing via clap; per-command validation is the consumer's responsibility",
          "rateLimiting": "Not provided by cli-core"
        },
        "systemRequirements": {
          "dependencies": [
            "OpenSSL",
            "libcurl"
          ],
          "os": "Linux (Debian-based)",
          "privileges": "root/sudo for system operations"
        },
        "version": "9.8.4 (build 320)",
        "website": "https://www.digi77.com"
      },
      "errors": [],
      "metadata": {
        "executionTime": 1,
        "hostname": "REDACTED-BUILD-HOST",
        "user": "REDACTED-BUILD-USER"
      },
      "status": "success",
      "timestamp": "2026-07-21T01:54:40.155150502Z",
      "version": "9.8.4 (build 320)",
      "warnings": []
    },
    "flag_v": {
      "command": "version",
      "data": {
        "buildDate": "REDACTED-BUILD-TIME",
        "gitCommit": "unknown",
        "name": "workflow-manager",
        "rustVersion": "1.82.0",
        "version": "9.8.4 (build 320)"
      },
      "errors": [],
      "metadata": {
        "executionTime": 1,
        "hostname": "REDACTED-BUILD-HOST",
        "user": "REDACTED-BUILD-USER"
      },
      "status": "success",
      "timestamp": "2026-07-21T01:54:40.263999522Z",
      "version": "9.8.4 (build 320)",
      "warnings": []
    },
    "flag_h": {
      "command": "help",
      "data": {
        "commandCategories": [
          {
            "category": "Diagnostics",
            "commands": [
              {
                "description": "Validate workflow prerequisites",
                "examples": [
                  "workflow-manager prereq check initial_terminal_setup_wireguard_torrify",
                  "workflow-manager prereq validate my-workflow",
                  "workflow-manager prereq check my-workflow --json"
                ],
                "name": "prereq",
                "options": [
                  {
                    "description": "check, or validate (an alias for check)",
                    "flag": "<SUBCOMMAND>",
                    "required": true
                  },
                  {
                    "description": "Template whose prerequisites block is evaluated",
                    "flag": "<TEMPLATE>",
                    "required": true
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager prereq <check|validate> <TEMPLATE>"
              },
              {
                "description": "Query system state",
                "examples": [
                  "workflow-manager state",
                  "workflow-manager state online",
                  "workflow-manager state security_score --json"
                ],
                "name": "state",
                "options": [
                  {
                    "description": "Single state to query (online, torrify, tor_running, security_score, routing_mode, authenticated, ...). Omit to return all 20",
                    "flag": "[FIELD]",
                    "required": false
                  },
                  {
                    "description": "Emit the state as a JSON envelope (global flag)",
                    "flag": "--json",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager state [FIELD]"
              }
            ]
          },
          {
            "category": "Execution",
            "commands": [
              {
                "description": "Run a workflow template",
                "examples": [
                  "workflow-manager run my-workflow --dry-run",
                  "workflow-manager run my-workflow",
                  "workflow-manager run my-workflow --kill-policy continue",
                  "workflow-manager run my-workflow --max-log-size 20971520",
                  "workflow-manager run my-workflow --param interface=eth0 --param mode=safe",
                  "workflow-manager run my-workflow --yes",
                  "workflow-manager run my-workflow --json"
                ],
                "name": "run",
                "options": [
                  {
                    "description": "Template to execute",
                    "flag": "<TEMPLATE>",
                    "required": true
                  },
                  {
                    "default": "false",
                    "description": "List the steps that would run without executing any of them",
                    "flag": "--dry-run",
                    "required": false
                  },
                  {
                    "default": "stop",
                    "description": "What to do when a step fails: stop, continue or skip_remaining. Overrides global_settings.kill_policy",
                    "flag": "--kill-policy <POLICY>",
                    "required": false
                  },
                  {
                    "default": "10485760",
                    "description": "Cap the run log size in bytes. Overrides global_settings.max_log_size",
                    "flag": "--max-log-size <BYTES>",
                    "required": false
                  },
                  {
                    "description": "Override a declared workflow parameter. Repeat for multiple parameters",
                    "flag": "--param <KEY=VALUE>",
                    "required": false
                  },
                  {
                    "default": "false",
                    "description": "Skip ordinary top-level [y/N] prompts in text mode; never approves high-risk or included child steps",
                    "flag": "-y, --yes",
                    "required": false
                  },
                  {
                    "description": "Override a workflow parameter; may be repeated",
                    "flag": "--param <NAME=VALUE>",
                    "required": false
                  },
                  {
                    "description": "Carry one exact dashboard-approved child step record; may be repeated",
                    "flag": "--approved-step <JSON>",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager run <TEMPLATE> [OPTIONS]"
              }
            ]
          },
          {
            "category": "Steps",
            "commands": [
              {
                "description": "Add a step to a workflow template",
                "examples": [
                  "workflow-manager add my-workflow 'echo Hello World'",
                  "workflow-manager add my-workflow 'tar czf backup.tar.gz /data' -t 600 --description 'Archive data'",
                  "workflow-manager add my-workflow 'cleanup.sh' -c if_success",
                  "workflow-manager add my-workflow './notify.sh' --if-contains 'ERROR'",
                  "workflow-manager add my-workflow './handle-connected.sh' --if-json-path '$.status=\"connected\"'",
                  "workflow-manager add my-workflow './tor-ready.sh' --if-state tor_running --if-state-expect true",
                  "workflow-manager add my-workflow './low-score-fix.sh' --if-expression \"state.security_score < 60\"",
                  "workflow-manager add w1 \"ip-fetch\",\"online-auth check-login\",\"ip addr show\""
                ],
                "name": "add",
                "options": [
                  {
                    "description": "Template to append the step to",
                    "flag": "<TEMPLATE>",
                    "required": true
                  },
                  {
                    "description": "Command to execute. A comma separated list creates one step per command",
                    "flag": "<COMMAND>",
                    "required": true
                  },
                  {
                    "description": "Step description",
                    "flag": "--description <TEXT>",
                    "required": false
                  },
                  {
                    "default": "always",
                    "description": "Basic condition: always, if_success or if_fail",
                    "flag": "-c, --condition <TYPE>",
                    "required": false
                  },
                  {
                    "description": "Run only if the named probe from the profile's probes block matches",
                    "flag": "--if-probe <NAME>",
                    "required": false
                  },
                  {
                    "description": "Value the probe must return (JSON: true, 4, \"ok\")",
                    "flag": "--if-probe-expect <JSON>",
                    "required": false
                  },
                  {
                    "description": "Run only if a live system state matches (see `workflow-manager state`)",
                    "flag": "--if-state <NAME>",
                    "required": false
                  },
                  {
                    "description": "Value the state must have (JSON: true, false, \"wireguard\")",
                    "flag": "--if-state-expect <JSON>",
                    "required": false
                  },
                  {
                    "description": "Boolean expression over probe('NAME') and state.NAME, joined with && and ||",
                    "flag": "--if-expression <EXPR>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous step's output contains TEXT (substring, case sensitive)",
                    "flag": "--if-contains <TEXT>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output does not contain TEXT",
                    "flag": "--if-not-contains <TEXT>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output equals VALUE exactly (trimmed)",
                    "flag": "--if-equals <VALUE>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output matches the regex",
                    "flag": "--if-regex <PATTERN>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output does not match the regex",
                    "flag": "--if-not-regex <PATTERN>",
                    "required": false
                  },
                  {
                    "description": "Run only if a JSON field matches, e.g. '$.status=\"connected\"' (writes if_json_path_equals)",
                    "flag": "--if-json-path <EXPR>",
                    "required": false
                  },
                  {
                    "description": "Step timeout. Falls back to global_settings.default_timeout when omitted",
                    "flag": "-t, --timeout <SECONDS>",
                    "required": false
                  },
                  {
                    "default": "false",
                    "description": "Prompt [y/N] before this step runs (text mode only)",
                    "flag": "--confirm",
                    "required": false
                  },
                  {
                    "description": "Directory to run the step from",
                    "flag": "-w, --working-dir <PATH>",
                    "required": false
                  },
                  {
                    "default": "0",
                    "description": "Process priority, -20 (highest) to 19 (lowest). Negative values need root",
                    "flag": "--nice-level <N>",
                    "required": false
                  },
                  {
                    "description": "Comma separated allowlist of environment variables passed to the step",
                    "flag": "--env <VARS>",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager add <TEMPLATE> <COMMAND> [OPTIONS]"
              },
              {
                "description": "Add a pause step to a workflow template",
                "examples": [
                  "workflow-manager pause my-workflow -m 'Review results before continuing'",
                  "workflow-manager pause backup -m 'Verify backup integrity' -c if_success"
                ],
                "name": "pause",
                "options": [
                  {
                    "description": "Template to append the pause to",
                    "flag": "<TEMPLATE>",
                    "required": true
                  },
                  {
                    "description": "Message shown to the user while the workflow waits",
                    "flag": "-m, --message <TEXT>",
                    "required": false
                  },
                  {
                    "default": "always",
                    "description": "Basic condition: always, if_success or if_fail",
                    "flag": "-c, --condition <TYPE>",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager pause <TEMPLATE> [OPTIONS]"
              },
              {
                "description": "Add an include step to a workflow template (includes another profile)",
                "examples": [
                  "workflow-manager include my-workflow shared-prereqs --description 'Reusable setup steps'",
                  "workflow-manager include my-workflow tor-recovery -c if_fail",
                  "workflow-manager include my-workflow base-recovery-sequence --if-state online --if-state-expect true"
                ],
                "name": "include",
                "options": [
                  {
                    "description": "Template to append the include to",
                    "flag": "<TEMPLATE>",
                    "required": true
                  },
                  {
                    "description": "Existing profile whose steps are expanded in place at run time",
                    "flag": "<PROFILE>",
                    "required": true
                  },
                  {
                    "description": "Step description",
                    "flag": "--description <TEXT>",
                    "required": false
                  },
                  {
                    "default": "always",
                    "description": "Basic condition: always, if_success or if_fail",
                    "flag": "-c, --condition <TYPE>",
                    "required": false
                  },
                  {
                    "description": "Run only if the named probe from the profile's probes block matches",
                    "flag": "--if-probe <NAME>",
                    "required": false
                  },
                  {
                    "description": "Value the probe must return (JSON: true, 4, \"ok\")",
                    "flag": "--if-probe-expect <JSON>",
                    "required": false
                  },
                  {
                    "description": "Run only if a live system state matches (see `workflow-manager state`)",
                    "flag": "--if-state <NAME>",
                    "required": false
                  },
                  {
                    "description": "Value the state must have (JSON: true, false, \"wireguard\")",
                    "flag": "--if-state-expect <JSON>",
                    "required": false
                  },
                  {
                    "description": "Boolean expression over probe('NAME') and state.NAME, joined with && and ||",
                    "flag": "--if-expression <EXPR>",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager include <TEMPLATE> <PROFILE> [OPTIONS]"
              },
              {
                "description": "Update a step in a workflow template",
                "examples": [
                  "workflow-manager update my-workflow 1 'echo Updated Command' -t 300",
                  "workflow-manager update my-workflow 2 --if-contains 'ERROR' --description 'Alert on error'",
                  "workflow-manager update my-workflow 2 --clear-condition -c always",
                  "workflow-manager update my-workflow 3 -m 'Verify the archive, then press Enter' --confirm true",
                  "workflow-manager update my-workflow 4 --profile base-recovery-sequence"
                ],
                "name": "update",
                "options": [
                  {
                    "description": "Template to edit",
                    "flag": "<TEMPLATE>",
                    "required": true
                  },
                  {
                    "description": "Step number to update, as shown by `workflow-manager show`",
                    "flag": "<STEP_ID>",
                    "required": true
                  },
                  {
                    "description": "New command for a command step. Omit it to change only the flags below",
                    "flag": "[COMMAND]",
                    "required": false
                  },
                  {
                    "description": "New message for a pause step",
                    "flag": "-m, --message <TEXT>",
                    "required": false
                  },
                  {
                    "description": "New profile for an include step",
                    "flag": "--profile <NAME>",
                    "required": false
                  },
                  {
                    "description": "New step description",
                    "flag": "--description <TEXT>",
                    "required": false
                  },
                  {
                    "default": "always",
                    "description": "Basic condition: always, if_success or if_fail",
                    "flag": "-c, --condition <TYPE>",
                    "required": false
                  },
                  {
                    "description": "Run only if the named probe from the profile's probes block matches",
                    "flag": "--if-probe <NAME>",
                    "required": false
                  },
                  {
                    "description": "Value the probe must return (JSON: true, 4, \"ok\")",
                    "flag": "--if-probe-expect <JSON>",
                    "required": false
                  },
                  {
                    "description": "Run only if a live system state matches (see `workflow-manager state`)",
                    "flag": "--if-state <NAME>",
                    "required": false
                  },
                  {
                    "description": "Value the state must have (JSON: true, false, \"wireguard\")",
                    "flag": "--if-state-expect <JSON>",
                    "required": false
                  },
                  {
                    "description": "Boolean expression over probe('NAME') and state.NAME, joined with && and ||",
                    "flag": "--if-expression <EXPR>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous step's output contains TEXT (substring, case sensitive)",
                    "flag": "--if-contains <TEXT>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output does not contain TEXT",
                    "flag": "--if-not-contains <TEXT>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output equals VALUE exactly (trimmed)",
                    "flag": "--if-equals <VALUE>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output matches the regex",
                    "flag": "--if-regex <PATTERN>",
                    "required": false
                  },
                  {
                    "description": "Run only if the previous output does not match the regex",
                    "flag": "--if-not-regex <PATTERN>",
                    "required": false
                  },
                  {
                    "description": "Run only if a JSON field matches, e.g. '$.status=\"connected\"' (writes if_json_path_equals)",
                    "flag": "--if-json-path <EXPR>",
                    "required": false
                  },
                  {
                    "default": "false",
                    "description": "Drop the stored condition payload and reset to the basic type given by -c",
                    "flag": "--clear-condition",
                    "required": false
                  },
                  {
                    "description": "New step timeout",
                    "flag": "-t, --timeout <SECONDS>",
                    "required": false
                  },
                  {
                    "description": "Set or clear the confirm flag (true or false)",
                    "flag": "--confirm <BOOL>",
                    "required": false
                  },
                  {
                    "description": "New working directory for the step",
                    "flag": "-w, --working-dir <PATH>",
                    "required": false
                  },
                  {
                    "description": "New process priority, -20 (highest) to 19 (lowest)",
                    "flag": "--nice-level <N>",
                    "required": false
                  },
                  {
                    "description": "New comma separated environment allowlist",
                    "flag": "--env <VARS>",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager update <TEMPLATE> <STEP_ID> [COMMAND] [OPTIONS]"
              },
              {
                "description": "Delete a step from a workflow template",
                "examples": [
                  "workflow-manager delete-step my-workflow 2",
                  "workflow-manager show my-workflow && workflow-manager delete-step my-workflow 3"
                ],
                "name": "delete-step",
                "options": [
                  {
                    "description": "Template to edit",
                    "flag": "<TEMPLATE>",
                    "required": true
                  },
                  {
                    "description": "Step number to remove, as shown by `workflow-manager show`",
                    "flag": "<STEP_ID>",
                    "required": true
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager delete-step <TEMPLATE> <STEP_ID>"
              }
            ]
          },
          {
            "category": "Templates",
            "commands": [
              {
                "description": "Create a new workflow template",
                "examples": [
                  "workflow-manager create my-workflow",
                  "workflow-manager create backup-workflow --description 'Daily backup routine'",
                  "workflow-manager create diagnostics && workflow-manager add diagnostics './health-control net-check'"
                ],
                "name": "create",
                "options": [
                  {
                    "description": "Name of the template, stored as config/profiles/<NAME>.json",
                    "flag": "<NAME>",
                    "required": true
                  },
                  {
                    "description": "Human readable description of the workflow",
                    "flag": "--description <TEXT>",
                    "required": false
                  },
                  {
                    "description": "Overwrite an existing template with the same name",
                    "flag": "--force",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager create <NAME> [OPTIONS]"
              },
              {
                "description": "List all workflow templates",
                "examples": [
                  "workflow-manager list",
                  "workflow-manager list --json"
                ],
                "name": "list",
                "options": [
                  {
                    "description": "Emit the template list as a JSON envelope (global flag)",
                    "flag": "--json",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager list"
              },
              {
                "description": "Show details of a workflow template",
                "examples": [
                  "workflow-manager show my-workflow",
                  "workflow-manager show my-workflow --json"
                ],
                "name": "show",
                "options": [
                  {
                    "description": "Template to display",
                    "flag": "<TEMPLATE>",
                    "required": true
                  },
                  {
                    "description": "Print the raw profile JSON, which is exactly what the runner deserializes (global flag)",
                    "flag": "--json",
                    "required": false
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager show <TEMPLATE>"
              },
              {
                "description": "Delete an entire workflow template",
                "examples": [
                  "workflow-manager delete my-workflow",
                  "workflow-manager list && workflow-manager delete obsolete-workflow"
                ],
                "name": "delete",
                "options": [
                  {
                    "description": "Template to delete. This removes the profile JSON from disk and cannot be undone",
                    "flag": "<TEMPLATE>",
                    "required": true
                  }
                ],
                "requires_sudo": false,
                "usage": "workflow-manager delete <TEMPLATE>"
              }
            ]
          }
        ],
        "description": "Workflow manager for batch command execution with conditional logic",
        "environmentVariables": [
          {
            "default": "unset",
            "description": "Disable all colored output when set",
            "name": "NO_COLOR",
            "values": "1|true|yes (any value disables color)"
          }
        ],
        "exitCodes": {
          "0": "Success",
          "1": "General error",
          "2": "Invalid arguments",
          "3": "Permission denied",
          "4": "Network error",
          "5": "File not found"
        },
        "globalOptions": [
          {
            "description": "Print help information",
            "flag": "-h, --help"
          },
          {
            "description": "Print version information",
            "flag": "-v, --version"
          },
          {
            "description": "Display detailed information",
            "flag": "-n, --info"
          },
          {
            "description": "Show usage examples",
            "flag": "-e, --examples"
          },
          {
            "description": "Output in JSON format",
            "flag": "--json"
          },
          {
            "description": "Force output format (text|json)",
            "flag": "-o, --output-format <FORMAT>"
          },
          {
            "description": "Pretty-print JSON output with indentation",
            "flag": "--json-pretty"
          },
          {
            "description": "Enhanced JSON output with improved formatting (like jq)",
            "flag": "--json-human"
          },
          {
            "description": "Return only specified JSON fields (comma-separated)",
            "flag": "--json-filter <FIELD1,FIELD2>"
          },
          {
            "description": "Select specific fields to include in output (comma-separated)",
            "flag": "--fields <FIELD_LIST>"
          },
          {
            "description": "Limit number of results returned",
            "flag": "--limit <NUMBER>"
          },
          {
            "description": "Skip first N results (for pagination)",
            "flag": "--offset <NUMBER>"
          },
          {
            "description": "Enable verbose output",
            "flag": "--verbose"
          },
          {
            "description": "Suppress non-essential output",
            "flag": "--quiet"
          },
          {
            "description": "Disable colored output",
            "flag": "--no-color"
          }
        ],
        "name": "workflow-manager",
        "usage": "workflow-manager [OPTIONS] [COMMAND] [ARGS]"
      },
      "errors": [],
      "metadata": {
        "executionTime": 1,
        "hostname": "REDACTED-BUILD-HOST",
        "user": "REDACTED-BUILD-USER"
      },
      "status": "success",
      "timestamp": "2026-07-21T01:54:40.362663837Z",
      "version": "9.8.4 (build 320)",
      "warnings": []
    },
    "flag_e": {
      "command": "examples",
      "data": {
        "categories": [
          {
            "description": "Create a template, add a step, preview it, then run it. Templates are stored as JSON profiles under the hooks config directory (config/profiles/<NAME>.json).",
            "examples": [
              {
                "command": "workflow-manager create my-workflow",
                "description": "Create an empty workflow template",
                "expectedOutput": "Template 'my-workflow' created successfully"
              },
              {
                "command": "workflow-manager add my-workflow 'echo Hello World'",
                "description": "Append a command step to the template",
                "expectedOutput": "Step 1 added to template 'my-workflow'",
                "notes": "`add` requires the template to exist already, so run `create` first."
              },
              {
                "command": "workflow-manager show my-workflow",
                "description": "Inspect the steps, their IDs and their conditions",
                "expectedOutput": "Workflow Template: my-workflow\nStep 1: echo Hello World (condition: always)"
              },
              {
                "command": "workflow-manager run my-workflow --dry-run",
                "description": "Preview execution without running any command",
                "expectedOutput": "Dry run: 1 step would be executed",
                "notes": "Always dry-run first: steps run real shell commands."
              },
              {
                "command": "workflow-manager run my-workflow",
                "description": "Execute every step in order",
                "expectedOutput": "Workflow completed: Success (1/1 steps)",
                "notes": "workflow-manager itself does not need root. Individual steps may, if the command inside the step does."
              }
            ],
            "id": "0_quick_start",
            "title": "Quick Start"
          },
          {
            "description": "Create, list, view, and delete workflow templates.",
            "examples": [
              {
                "command": "workflow-manager create backup-workflow --description 'Daily backup routine'",
                "description": "Create a template with a human readable label",
                "expectedOutput": "Template 'backup-workflow' created successfully"
              },
              {
                "command": "workflow-manager list",
                "description": "Show every stored workflow template",
                "expectedOutput": "Workflow Templates (2 total)\n  backup-workflow (4 steps)\n  my-workflow (1 step)"
              },
              {
                "command": "workflow-manager show backup-workflow --json",
                "description": "Print the raw profile JSON, which is what the runner deserializes",
                "expectedOutput": "The full profile object: name, description, global_settings, prerequisites, probes and steps",
                "notes": "Use this to see the exact schema before hand editing config/profiles/backup-workflow.json."
              },
              {
                "command": "workflow-manager delete backup-workflow",
                "description": "Remove an entire workflow template",
                "expectedOutput": "Template 'backup-workflow' deleted successfully",
                "notes": "Destructive and irreversible: the profile JSON is deleted from disk. Use `delete-step` if you only want to remove one step."
              }
            ],
            "id": "1_template_management",
            "title": "Template Management"
          },
          {
            "description": "Add command steps to a template. A comma separated command list creates one step per command.",
            "examples": [
              {
                "command": "workflow-manager add my-workflow 'tar czf backup.tar.gz /data' --timeout 600 --description 'Archive data'",
                "description": "Add a step with a 10 minute timeout and a description",
                "expectedOutput": "Step 2 added to template 'my-workflow' (timeout 600s)",
                "notes": "--timeout (-t) is the STEP timeout. It shadows the cli-core global --timeout inside `add`."
              },
              {
                "command": "workflow-manager create w1 && workflow-manager add w1 \"ip-fetch\",\"online-auth check-login\",\"ip addr show\"",
                "description": "Create a template and add three steps in one call using comma separation",
                "expectedOutput": "Template 'w1' created, 3 steps added to template 'w1'",
                "notes": "All steps created in one call share the same timeout and condition settings."
              },
              {
                "command": "workflow-manager add my-workflow 'cleanup.sh' -c if_success",
                "description": "Run this step only if the previous step exited 0",
                "expectedOutput": "Step added with condition if_success"
              },
              {
                "command": "workflow-manager add my-workflow './health-control panic hard' --confirm",
                "description": "Mark a step as requiring an interactive confirmation before it runs",
                "expectedOutput": "Step added with confirm=true",
                "notes": "confirm=true prompts [y/N] before the step runs, in TEXT mode only. A --json run (what the dashboard uses) proceeds past it without prompting, so confirm is a human speed bump, not a safety gate."
              },
              {
                "command": "workflow-manager add my-workflow './long-scan.sh' --nice-level 10 -w /opt/kodachi/dashboard/hooks",
                "description": "Run a background friendly step from a specific working directory",
                "expectedOutput": "Step added with nice_level=10 and working_dir set",
                "notes": "nice-level range is -20 (highest priority) to 19 (lowest). Negative values need root."
              },
              {
                "command": "workflow-manager add my-workflow './report.sh' --env 'HOME,PATH,LANG'",
                "description": "Allow only the listed environment variables through to the step",
                "expectedOutput": "Step added with env_allowlist [HOME, PATH, LANG]",
                "notes": "Comma separated. Anything not listed is stripped from the step environment."
              }
            ],
            "id": "2_adding_steps",
            "title": "Adding Steps"
          },
          {
            "description": "Every condition the runner understands, expressed as an `add` flag. One condition per step.",
            "examples": [
              {
                "command": "workflow-manager add my-workflow './check-status.sh' -c always",
                "description": "Always execute (this is the default)",
                "expectedOutput": "Step added with condition always"
              },
              {
                "command": "workflow-manager add my-workflow './deploy.sh' -c if_success",
                "description": "Execute only if the previous step exited 0",
                "expectedOutput": "Step added with condition if_success",
                "notes": "The most common condition for sequential workflows."
              },
              {
                "command": "workflow-manager add my-workflow './rollback.sh' -c if_fail",
                "description": "Execute only if the previous step exited non-zero",
                "expectedOutput": "Step added with condition if_fail",
                "notes": "Useful for error recovery and rollback."
              },
              {
                "command": "workflow-manager add my-workflow './alert-success.sh' --if-contains 'success'",
                "description": "Execute if the previous step's output CONTAINS the text",
                "expectedOutput": "Step added with condition if_contains",
                "notes": "Plain substring match, case sensitive. No wildcards: use --if-regex if you need a pattern."
              },
              {
                "command": "workflow-manager add my-workflow './continue.sh' --if-not-contains 'error'",
                "description": "Execute if the previous output does NOT contain the text",
                "expectedOutput": "Step added with condition if_not_contains",
                "notes": "Substring match, case sensitive."
              },
              {
                "command": "workflow-manager add my-workflow './handle-done.sh' --if-equals 'ready'",
                "description": "Execute if the previous output is exactly this value",
                "expectedOutput": "Step added with condition if_equals",
                "notes": "Exact match, case sensitive. Output is trimmed before comparison."
              },
              {
                "command": "workflow-manager add my-workflow './process-result.sh' --if-regex '^status: (ok|success)$'",
                "description": "Execute if the previous output matches a regex",
                "expectedOutput": "Step added with condition if_regex"
              },
              {
                "command": "workflow-manager add my-workflow './alert-few-services.sh' --if-not-regex '(service.*active.*){5,}'",
                "description": "Execute if the previous output does NOT match a regex (here: fewer than 5 active services)",
                "expectedOutput": "Step added with condition if_not_regex",
                "notes": "Quantifiers such as {5,} let you use a regex as a crude counter."
              },
              {
                "command": "workflow-manager add my-workflow './handle-connected.sh' --if-json-path '$.status=\"connected\"'",
                "description": "Execute if a field in the previous step's JSON output equals a value",
                "expectedOutput": "Step added with condition if_json_path_equals",
                "notes": "The previous output must be valid JSON. The CLI flag is --if-json-path; the serde tag written into the profile is if_json_path_equals."
              },
              {
                "command": "workflow-manager add my-workflow './finland-detected.sh' --if-json-path '$.data.records[0].country_name=\"Finland\"'",
                "description": "Execute if a nested JSON field, reached through an array index, matches",
                "expectedOutput": "Step added with condition if_json_path_equals",
                "notes": "Supported path syntax: $ root, .field, [index]. Recursive descent (..) and wildcards (*) are NOT supported."
              },
              {
                "command": "workflow-manager add my-workflow './ip-online.sh' --if-json-path '$.ip_connectivity=true'",
                "description": "Execute if a JSON boolean is true",
                "expectedOutput": "Step added with condition if_json_path_equals",
                "notes": "Booleans and numbers are written unquoted: =true, =2. Strings need quotes: =\"ok\"."
              },
              {
                "command": "workflow-manager add my-workflow './tor-ready.sh' --if-state tor_running --if-state-expect true",
                "description": "Execute only when a live system state matches (independent of the previous step)",
                "expectedOutput": "Step added with condition if_state",
                "notes": "--if-state-expect takes JSON (true, false, 60, \"wireguard\"). Run `workflow-manager state` to see the state names."
              },
              {
                "command": "workflow-manager add my-workflow './skip-if-hardened.sh' --if-probe is_hardened --if-probe-expect false",
                "description": "Execute based on a probe function defined in the profile",
                "expectedOutput": "Step added with condition if_probe",
                "notes": "The probe name must exist in the profile's `probes` block, see the Probe Functions category. --if-probe-expect takes JSON."
              },
              {
                "command": "workflow-manager add my-workflow './low-score-fix.sh' --if-expression \"state.authenticated == true && state.security_score < 60\"",
                "description": "Execute if a boolean expression over states and probes evaluates true",
                "expectedOutput": "Step added with condition if_expression",
                "notes": "Grammar: atoms are probe('NAME') or state.NAME, operators == != < > <= >=, combined with && and || and negated with !. There is no contains() function and no step_id or workflow_status variable."
              }
            ],
            "id": "3_conditional_logic",
            "title": "Conditional Logic (CLI flags)"
          },
          {
            "description": "Run workflows and control what happens when a step fails.",
            "examples": [
              {
                "command": "workflow-manager run my-workflow --dry-run",
                "description": "List the steps that would run, without executing anything",
                "expectedOutput": "Dry run: 5 steps would be executed",
                "notes": "Conditions that depend on previous output cannot be fully resolved in a dry run."
              },
              {
                "command": "workflow-manager run my-workflow",
                "description": "Execute every step in order, evaluating each condition first",
                "expectedOutput": "Workflow completed: Success (5/5 steps, 2 skipped by condition)",
                "notes": "Steps run real shell commands. Read the template with `show` before running one you did not write."
              },
              {
                "command": "workflow-manager run my-workflow --kill-policy continue",
                "description": "Keep going after a failed step instead of stopping",
                "expectedOutput": "Workflow completed with failures (step 3 failed, remaining steps executed)",
                "notes": "Values: stop (default and safest), continue, skip_remaining. This overrides global_settings.kill_policy for this run."
              },
              {
                "command": "workflow-manager run my-workflow --max-log-size 20971520",
                "description": "Raise the per-run log cap for a very chatty workflow",
                "expectedOutput": "Workflow completed: Success",
                "notes": "Bytes, not megabytes. Default is 10485760 (10 MB). Overrides global_settings.max_log_size."
              },
              {
                "command": "workflow-manager run my-workflow --yes",
                "description": "Run unattended in text mode, skipping the [y/N] prompt on confirm:true steps",
                "expectedOutput": "Workflow completed: Success (no confirmation prompts shown)",
                "notes": "--yes (-y) approves EVERY confirm:true step, including destructive ones, with no prompt. It only affects text mode: the [y/N] prompt is text mode only."
              },
              {
                "command": "workflow-manager run my-workflow --json",
                "description": "Run non-interactively and get a machine readable result (this is how the dashboard runs workflows)",
                "expectedOutput": "JSON envelope with per-step status, exit codes and durations",
                "notes": "--json is non-interactive: confirm:true steps run WITHOUT any prompt and without --yes. Do not rely on confirm as a safety gate for automated runs."
              }
            ],
            "id": "4_workflow_execution",
            "title": "Workflow Execution"
          },
          {
            "description": "Update or delete a single step. Step IDs come from `show`.",
            "examples": [
              {
                "command": "workflow-manager show my-workflow",
                "description": "Find the step IDs before editing",
                "expectedOutput": "Step 1: echo Hello\nStep 2: ./backup.sh\nStep 3: ./cleanup.sh"
              },
              {
                "command": "workflow-manager update my-workflow 1 'echo Updated Command' -t 300",
                "description": "Replace step 1's command and timeout",
                "expectedOutput": "Step 1 updated successfully",
                "notes": "The command positional is optional: pass only the flags you want to change."
              },
              {
                "command": "workflow-manager update my-workflow 2 --if-contains 'ERROR' --description 'Alert on error'",
                "description": "Change a step's condition and its description in place",
                "expectedOutput": "Step 2 updated successfully (condition if_contains)",
                "notes": "update accepts the same condition flags as add: -c, --if-contains, --if-not-contains, --if-equals, --if-regex, --if-not-regex, --if-json-path, --if-probe(-expect), --if-state(-expect), --if-expression."
              },
              {
                "command": "workflow-manager update my-workflow 2 --clear-condition -c always",
                "description": "Drop a step's condition payload and reset it to a plain condition type",
                "expectedOutput": "Step 2 updated successfully (condition always)",
                "notes": "--clear-condition removes the stored pattern/path/probe value. Without it, switching from if_contains back to always can leave a stale payload."
              },
              {
                "command": "workflow-manager update my-workflow 3 -m 'Verify the archive, then press Enter' --confirm true",
                "description": "Update a pause step's message and require confirmation",
                "expectedOutput": "Step 3 updated successfully",
                "notes": "-m/--message applies to pause steps, --profile applies to include steps, the command positional applies to command steps."
              },
              {
                "command": "workflow-manager delete-step my-workflow 2",
                "description": "Remove step 2 from the workflow",
                "expectedOutput": "Step 2 deleted from 'my-workflow'",
                "notes": "Steps are renumbered after a delete, so re-run `show` before deleting another one."
              }
            ],
            "id": "5_step_management",
            "title": "Managing Individual Steps"
          },
          {
            "description": "Two non-command step types: a pause that waits for the user, and an include that expands another profile inline.",
            "examples": [
              {
                "command": "workflow-manager pause my-workflow -m 'Review results before continuing'",
                "description": "Add an interactive pause point",
                "expectedOutput": "Pause step added to template 'my-workflow'",
                "notes": "The run blocks until the user presses Enter, so a paused workflow is not suitable for unattended or --json runs."
              },
              {
                "command": "workflow-manager pause backup -m 'Verify backup integrity' -c if_success",
                "description": "Pause only when the previous step succeeded",
                "expectedOutput": "Pause step added with condition if_success"
              },
              {
                "command": "workflow-manager include my-workflow shared-prereqs --description 'Reusable setup steps'",
                "description": "Compose another profile into this template",
                "expectedOutput": "Include step 3 added to template 'my-workflow'",
                "notes": "The named profile must exist. Its steps are expanded in place when the workflow runs."
              },
              {
                "command": "workflow-manager include my-workflow tor-recovery -c if_fail",
                "description": "Pull in a recovery profile only when the previous step failed",
                "expectedOutput": "Include step added with condition if_fail",
                "notes": "include accepts -c/--condition plus --if-probe(-expect), --if-state(-expect) and --if-expression."
              }
            ],
            "id": "6_pause_and_include",
            "title": "Pause and Include Steps"
          },
          {
            "description": "Build a complete workflow in one shell line by chaining create and add with &&.",
            "examples": [
              {
                "command": "workflow-manager create tor-recovery && workflow-manager add tor-recovery './routing-switch recover internet' -t 60 && workflow-manager add tor-recovery './health-control net-check' -c if_success && workflow-manager add tor-recovery './tor-switch start' -c if_success -t 120",
                "description": "Create a template and add three conditional steps in one chain",
                "expectedOutput": "Template created, 3 steps added successfully",
                "notes": "`create` must come first: `add` refuses to run against a template that does not exist."
              },
              {
                "command": "workflow-manager create diagnostics && workflow-manager add diagnostics './health-control net-check' -t 30 && workflow-manager add diagnostics './tor-switch tor-status' -c if_success && workflow-manager add diagnostics './dns-leak test' -c if_success && workflow-manager add diagnostics './integrity-check check-all' -c if_success",
                "description": "Build a 4 step diagnostics workflow",
                "expectedOutput": "diagnostics created, 4 steps added"
              },
              {
                "command": "workflow-manager create backup && workflow-manager add backup 'tar czf backup.tar.gz /data' && workflow-manager pause backup -m 'Check backup size' -c if_success && workflow-manager add backup 'rsync backup.tar.gz remote:/backups' -c if_success && workflow-manager add backup 'rm backup.tar.gz' -c if_success",
                "description": "Mix command steps and a pause to build an interactive backup workflow",
                "expectedOutput": "Backup workflow with 4 steps created"
              }
            ],
            "id": "7_batch_building",
            "title": "Efficient Batch Building"
          },
          {
            "description": "End to end workflows built from real Kodachi hook commands.",
            "examples": [
              {
                "command": "workflow-manager create ip-verify && workflow-manager add ip-verify 'ip-fetch --json' -t 60 && workflow-manager add ip-verify 'echo Finland detected' --if-json-path '$.data.records[0].country_name=\"Finland\"' && workflow-manager run ip-verify",
                "description": "Fetch the public IP and branch on the geolocated country",
                "expectedOutput": "Finland detected",
                "notes": "Needs network access. ip-fetch does not need root."
              },
              {
                "command": "workflow-manager create auth-check && workflow-manager add auth-check 'online-auth check-login --json' -t 30 && workflow-manager add auth-check 'echo Session valid' --if-contains 'valid' && workflow-manager run auth-check",
                "description": "Confirm there is a valid authenticated session",
                "expectedOutput": "Session valid",
                "notes": "Many hook commands refuse to run without an authenticated session, so this is a useful first step in a longer workflow."
              },
              {
                "command": "workflow-manager create health-audit && workflow-manager add health-audit 'sudo health-control net-check --json' -t 60 && workflow-manager add health-audit 'echo Network online' --if-json-path '$.ip_connectivity=true' && workflow-manager add health-audit 'sudo routing-switch status --json' -c if_success -t 30 && workflow-manager run health-audit",
                "description": "Chain a network check into a routing status check",
                "expectedOutput": "Network online",
                "notes": "The steps themselves need root here (health-control and routing-switch do), workflow-manager does not."
              },
              {
                "command": "workflow-manager create tor-verify && workflow-manager add tor-verify 'sudo tor-switch get-tor-status --json' -t 30 && workflow-manager add tor-verify 'echo Tor responding' --if-json-path '$.data.is_responding=true' && workflow-manager run tor-verify",
                "description": "Verify the Tor daemon is up and answering",
                "expectedOutput": "Tor responding",
                "notes": "Requires Tor to be installed and its control port reachable."
              }
            ],
            "id": "8_kodachi_workflows",
            "title": "Real-World Kodachi Workflows"
          },
          {
            "description": "A profile can declare system state that must hold before any step runs. The block is `prerequisites` and it has exactly three fields: `required` (array), `optional` (array, warnings only) and `on_failure`. There is no flat form: keys such as \"authenticated\": true at the top of the block do not deserialize.",
            "examples": [
              {
                "command": "workflow-manager prereq check initial_terminal_setup_wireguard_torrify",
                "description": "Validate a profile's prerequisites without running the workflow",
                "expectedOutput": "All prerequisites met, or the list of failed checks with their error messages",
                "notes": "`prereq validate <TEMPLATE>` is accepted as an alias for `prereq check`."
              },
              {
                "command": "workflow-manager show initial_terminal_setup_wireguard_torrify --json",
                "description": "Read the exact prerequisites shape the runner expects",
                "expectedOutput": "The profile JSON, including the prerequisites block",
                "notes": "The shape is: \"prerequisites\": {\"required\": [{\"check\": \"state.online\", \"expect\": true, \"error\": \"Internet connection required\"}, {\"check\": \"state.torrify\", \"expect\": false, \"error\": \"System must not be torrified\"}], \"on_failure\": \"abort\"}. Each entry needs `check` and `error`; `expect` is optional and defaults to a truthy check."
              },
              {
                "command": "workflow-manager state",
                "description": "List the state names usable as a prerequisite `check` value",
                "expectedOutput": "A JSON object of all system states, for example {\"online\": true, \"torrify\": false, \"tor_running\": true, ...}",
                "notes": "A check is written as \"state.<NAME>\" (the bare \"<NAME>\" form is also accepted). Optional checks go in the `optional` array: they warn but never block."
              },
              {
                "command": "workflow-manager run initial_terminal_setup_wireguard_torrify --dry-run",
                "description": "See how on_failure behaves before committing to a real run",
                "expectedOutput": "Prerequisites validated, or 'Prerequisites not met' followed by the failed checks",
                "notes": "on_failure accepts \"abort\" (default) and \"warn\". Only \"abort\" stops the run: any other value, including a typo, lets the workflow continue. If the profile has no prerequisites block, no checks are performed."
              }
            ],
            "id": "9_prerequisites",
            "title": "Prerequisites"
          },
          {
            "description": "Query the live system state that conditions, probes and prerequisites read from.",
            "examples": [
              {
                "command": "workflow-manager state",
                "description": "Show every system state as JSON",
                "expectedOutput": "{\"online\": true, \"torrify\": false, \"dnscrypt\": true, \"routing_mode\": \"wireguard\", \"tor_running\": true}"
              },
              {
                "command": "workflow-manager state online",
                "description": "Query a single state field (cheaper: only that field is probed)",
                "expectedOutput": "{\"state\": \"online\", \"value\": true}",
                "notes": "20 states are available: online, routing_mode, vpn_connected, dnscrypt, ipv6_disabled, dns_kodachi_managed, firewall_active, kill_switch_armed, network_hardened, disk_encrypted, security_score, torrify, tor_running, tor_dns_active, tor_verified, mac_spoofing, bluetooth_enabled, wifi_enabled, authenticated, tor_instances_count."
              },
              {
                "command": "workflow-manager state security_score --json",
                "description": "Read a numeric state, for use with --if-expression comparisons",
                "expectedOutput": "{\"state\": \"security_score\", \"value\": 62}",
                "notes": "Numeric states support < > <= >= inside --if-expression, for example \"state.security_score < 60\"."
              }
            ],
            "id": "10_state_checking",
            "title": "System State Checking"
          },
          {
            "description": "A probe is a named, reusable check declared in the profile's `probes` block and referenced by --if-probe. A ProbeDefinition has exactly three fields: `probe_type` (\"builtin\", \"expression\" or \"count\"), `expression` (required for all three types) and an optional `description`. There is no `check` field.",
            "examples": [
              {
                "command": "workflow-manager add my-workflow 'echo Already hardened, skipping' --if-probe is_hardened --if-probe-expect true",
                "description": "Reference a probe from a step condition",
                "expectedOutput": "Step added with condition if_probe",
                "notes": "Add the probes block to config/profiles/my-workflow.json first: \"probes\": {\"harden_count\": {\"probe_type\": \"count\", \"expression\": \"count('harden', previous_output)\", \"description\": \"Count 'harden' occurrences\"}, \"is_hardened\": {\"probe_type\": \"expression\", \"expression\": \"probe('harden_count') >= 4\"}}"
              },
              {
                "command": "workflow-manager add my-workflow './use-tor-path.sh' --if-probe tor_up --if-probe-expect true",
                "description": "Use the one builtin probe: a live Tor connection check",
                "expectedOutput": "Step added with condition if_probe",
                "notes": "Declare it as \"tor_up\": {\"probe_type\": \"builtin\", \"expression\": \"tor_connection_check\"}. tor_connection_check is the ONLY builtin: any other expression under probe_type \"builtin\" fails at run time with 'Unknown builtin probe'. It shells out to ip-fetch check-tor, so it needs network access, and its result is cached for the run."
              },
              {
                "command": "workflow-manager show my-workflow --json",
                "description": "Confirm the probes block deserializes the way the runner expects",
                "expectedOutput": "The profile JSON with its `probes` map, each entry showing probe_type and expression",
                "notes": "probe_type \"count\" evaluates count('<TEXT>', previous_output) and returns a number. probe_type \"expression\" evaluates the same grammar as --if-expression, so it can reference other probes with probe('NAME') and states with state.NAME."
              }
            ],
            "id": "11_probe_functions",
            "title": "Probe Functions (profile JSON)"
          },
          {
            "description": "The `global_settings` block sets workflow wide defaults: kill_policy (\"stop\" by default), continue_policy (false by default), max_log_size (10485760 bytes), default_timeout (seconds) and working_dir. Step level values override them.",
            "examples": [
              {
                "command": "workflow-manager show policy-demo --json",
                "description": "Read the global_settings block of an existing profile",
                "expectedOutput": "\"global_settings\": {\"kill_policy\": \"stop\", \"continue_policy\": false, \"max_log_size\": 10485760, \"default_timeout\": 300, \"working_dir\": \".\"}",
                "notes": "continue_policy is the master override: when true the workflow always continues and kill_policy is ignored. When false, kill_policy decides: \"stop\" ends the run, \"continue\" carries on, \"skip_remaining\" skips the rest without failing."
              },
              {
                "command": "workflow-manager run policy-demo --kill-policy stop",
                "description": "Force the safest failure policy for one run, whatever the profile says",
                "expectedOutput": "Workflow stopped at the first failing step",
                "notes": "For security critical workflows use kill_policy \"stop\" with continue_policy false. For recovery workflows, \"continue\" is usually what you want."
              },
              {
                "command": "workflow-manager add slow-scan './deep-scan.sh' -t 60",
                "description": "Give one step its own timeout, overriding default_timeout",
                "expectedOutput": "Step added with timeout 60s",
                "notes": "A step with no timeout inherits global_settings.default_timeout. A timed out command is sent SIGTERM, then SIGKILL if it does not exit."
              }
            ],
            "id": "12_global_settings",
            "title": "Global Settings (profile JSON)"
          },
          {
            "description": "The 12 condition tags the runner accepts, exactly as they are written in the profile's `condition` object. Anything else fails to deserialize: always, if_success, if_fail, if_contains, if_not_contains, if_equals, if_regex, if_not_regex, if_json_path_equals, if_probe, if_state, if_expression.",
            "examples": [
              {
                "command": "workflow-manager show my-workflow --json",
                "description": "See the condition object the CLI flags actually write",
                "expectedOutput": "\"condition\": {\"type\": \"if_contains\", \"pattern\": \"SUCCESS\"}",
                "notes": "Field per tag: always / if_success / if_fail take none. if_contains, if_not_contains, if_regex, if_not_regex take `pattern`. if_equals takes `value`. if_json_path_equals takes `path` and `value`. if_probe takes `probe` and `expect`. if_state takes `state` and `expect`. if_expression takes `expression`."
              },
              {
                "command": "workflow-manager add my-workflow './alert.sh' --if-contains 'SUCCESS'",
                "description": "Substring matching, written as if_contains / if_not_contains",
                "expectedOutput": "Step added: {\"type\": \"if_contains\", \"pattern\": \"SUCCESS\"}",
                "notes": "This is a plain substring test, case sensitive. It is NOT glob: * and ? are literal characters here. For wildcards use if_regex."
              },
              {
                "command": "workflow-manager add my-workflow './connected.sh' --if-json-path '$.status.connected=true'",
                "description": "JSON path equality, written as if_json_path_equals",
                "expectedOutput": "Step added: {\"type\": \"if_json_path_equals\", \"path\": \"$.status.connected\", \"value\": true}",
                "notes": "The stored field is `value`, not `expect`. Path syntax is a strict subset: $ root, .field, [index]. Recursive descent (..) and wildcards are not supported."
              },
              {
                "command": "workflow-manager add my-workflow './score-fix.sh' --if-expression \"probe('harden_count') >= 4 || state.security_score < 60\"",
                "description": "Boolean expression, written as if_expression",
                "expectedOutput": "Step added: {\"type\": \"if_expression\", \"expression\": \"probe('harden_count') >= 4 || state.security_score < 60\"}",
                "notes": "Atoms: probe('NAME') and state.NAME. Operators: == != < > <= >=, joined with && and ||, negated with a leading !. Comparisons on booleans and strings support only == and !=."
              }
            ],
            "id": "13_condition_reference",
            "title": "Condition Reference (profile JSON)"
          },
          {
            "description": "A step object has two required fields, `id` and `type` (\"command\", \"pause\" or \"include\"), plus `condition` (defaults to always if absent). Everything else is optional: cmd, description, timeout, confirm, env_allowlist, working_dir, nice_level, message, profile, parameters, and the ColonyOps hints cell_store, score_impact and colonyops_safety.",
            "examples": [
              {
                "command": "workflow-manager show my-workflow --json",
                "description": "Read a complete step object as the runner stores it",
                "expectedOutput": "{\"id\": 1, \"type\": \"command\", \"cmd\": \"health-control net-check\", \"description\": \"Check network connectivity\", \"condition\": {\"type\": \"always\"}, \"timeout\": 60, \"confirm\": false, \"nice_level\": 0}",
                "notes": "`description` is optional, not required. A command step needs `cmd`, a pause step needs `message`, an include step needs `profile` (and may carry `parameters`)."
              },
              {
                "command": "workflow-manager add my-workflow './panic.sh' --confirm --nice-level -10",
                "description": "Write the confirm and nice_level step fields from the CLI",
                "expectedOutput": "Step added: {\"confirm\": true, \"nice_level\": -10}",
                "notes": "confirm:true prompts [y/N] in text mode only, and `run --yes` skips that prompt. A --json run never prompts. nice_level goes from -20 to 19; negative values need root."
              },
              {
                "command": "workflow-manager add my-workflow './report.sh' -w /opt/kodachi/dashboard/hooks --env 'HOME,PATH'",
                "description": "Write the working_dir and env_allowlist step fields",
                "expectedOutput": "Step added: {\"working_dir\": \"/opt/kodachi/dashboard/hooks\", \"env_allowlist\": [\"HOME\", \"PATH\"]}",
                "notes": "A step without working_dir inherits global_settings.working_dir. env_allowlist is a whitelist: variables not listed are not passed to the step."
              },
              {
                "command": "workflow-manager include my-workflow base-recovery-sequence",
                "description": "Write an include step, which expands another profile at run time",
                "expectedOutput": "Step added: {\"type\": \"include\", \"profile\": \"base-recovery-sequence\", \"condition\": {\"type\": \"always\"}}",
                "notes": "Include lets you keep a library of small reusable profiles and compose them. The included profile must already exist."
              }
            ],
            "id": "14_step_reference",
            "title": "Step Reference (profile JSON)"
          }
        ],
        "description": "Usage examples for workflow-manager",
        "name": "workflow-manager",
        "quickReference": [
          "workflow-manager --help",
          "workflow-manager --version",
          "workflow-manager --info --json",
          "workflow-manager --examples",
          "workflow-manager list",
          "workflow-manager show <TEMPLATE>",
          "workflow-manager run <TEMPLATE> --dry-run",
          "workflow-manager state"
        ]
      },
      "errors": [],
      "metadata": {
        "executionTime": 0,
        "hostname": "REDACTED-BUILD-HOST",
        "user": "REDACTED-BUILD-USER"
      },
      "status": "success",
      "timestamp": "2026-07-21T01:54:40.565977889Z",
      "version": "9.8.4 (build 320)",
      "warnings": []
    }
  }
}
