Metadata-Version: 2.4
Name: iomate-pkg-workflow
Version: 0.1.7
Summary: IOMate Package providing control-flow and error-handling Actions
License-File: LICENSE
Author: IOMate
Requires-Python: >=3.12,<=3.14.4
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: iomate-base (>=0.1.5,<0.2.0)
Description-Content-Type: text/markdown

<div align="center">
  <h1><strong>IOMATE-PKG-WORKFLOW</strong></h1>
</div>

<p align="center">
  <a href="https://github.com/iomateapp/iomate-pkg-workflow/actions?query=branch%staging">
    <img src="https://github.com/iomateapp/iomate-pkg-workflow/actions/workflows/quality-and-tests.yaml/badge.svg?branch=staging" />
  </a>
  <a href="https://codecov.io/gh/iomateapp/iomate-pkg-workflow">
    <img src="https://codecov.io/gh/iomateapp/iomate-pkg-workflow/branch/staging/graph/badge.svg" />
  </a>
  <img src="https://img.shields.io/pypi/dm/iomate-pkg-workflow" />
  <img src="https://img.shields.io/github/license/iomateapp/iomate-pkg-workflow" />
  <img src="https://img.shields.io/github/v/release/iomateapp/iomate-pkg-workflow" />
  <img src="https://img.shields.io/github/stars/iomateapp/iomate-pkg-workflow?style=flat" />
</p>

Control-flow and error-handling Actions for IOMate.

`iomate-pkg-workflow` is an IOMate Package built on top of
[`iomate-base`](https://github.com/roderiano/iomate-base).

It provides Actions for controlling execution flow and handling errors
inside IOMate Automations.

---

## Features

The package provides Actions in six groups:

- **Workflow:** conditionals, loops, break/continue, calls, and return.
- **Error Handling:** try/except/finally and explicit error raising.
- **Variables:** set, copy, increment, append, and remove.
- **Data Operations:** comparisons, collection access, filtering, mapping, sorting, and conversions.
- **Logging:** log messages and variable values.
- **Execution Utilities:** delay, retry, timeout, wait-until, assert, and no-op.

The Robot runtime is responsible for repeatedly executing loop blocks, enforcing timeout deadlines,
propagating workflow return values, and recognizing break/continue control signals. Data filtering
and mapping use declarative expressions; the package never evaluates arbitrary Python source from
an Automation.

## Requirements

- Python 3.12+
- Poetry
- `iomate-base`

The supported Python version range is defined in `pyproject.toml`.

---

## Installation

Install from PyPI:

```bash
pip install iomate-pkg-workflow
```

Or add it to a Poetry project:

```bash
poetry add iomate-pkg-workflow
```

The Package requires a compatible version of:

```text
iomate-base
```

---

## Development Setup

Clone the repository and install the development dependencies:

```bash
poetry install
```

Run commands through Poetry:

```bash
poetry run <command>
```

---

## Project Structure

```text
iomate-pkg-workflow/
├── pyproject.toml
├── poetry.lock
│
├── src/
│   └── iomate_pkg_workflow/
│       ├── actions/
│       │   ├── workflow/
│       │   └── error_handling/
│       ├── package.py
│       └── ...
│
├── tests/
│   ├── workflow/
│   ├── error_handling/
│   └── ...
│
├── README.md
├── CONTRIBUTING.md
└── CODE_OF_CONDUCT.md
```

The exact internal structure may evolve as the Package grows, but
Package-specific implementation must remain isolated from
`iomate-base`.

---

## Action Groups

### Workflow and composition

| Action | Inputs | Behavior |
| --- | --- | --- |
| `workflow.if` | `condition: bool` | Runs the nested block when true. |
| `workflow.else_if` | `condition: bool` | Runs when no earlier branch ran and this condition is true. |
| `workflow.else` | — | Runs when no earlier branch ran. |
| `workflow.for` | `items`, `variable` | Executes the block for each item. |
| `workflow.while` | `condition` | Re-evaluates the condition before each iteration. |
| `workflow.break` | — | Stops the innermost loop. |
| `workflow.continue` | — | Skips to the next loop iteration. |
| `workflow.call` | `workflow` | Calls another workflow in the same Automation. Its `result` output receives a returned value. |
| `workflow.return` | optional `value` | Returns from the current workflow. |

### Error Handling

| Action | Inputs | Behavior |
| --- | --- | --- |
| `workflow.try` | — | Runs a nested block while capturing errors. |
| `workflow.except` | optional `error_type` | Handles an error whose class name matches; empty matches any. Outputs `error` and `error_type`. |
| `workflow.finally` | — | Runs finalization and re-raises an unhandled error. |
| `workflow.raise` | `message`, optional `error_type` | Raises an allow-listed built-in exception. |

The legacy `error_handling.try`, `error_handling.except`, and `error_handling.finally` keys
remain registered for saved Automations. The runtime's `ChainState` remains the single source of
truth for error handling.

### Variables

| Action | Inputs | Behavior |
| --- | --- | --- |
| `workflow.variable.set` | `name`, `value` | Creates or overwrites a variable. |
| `workflow.variable.copy` | `source`, `target` | Copies a value and its type. |
| `workflow.variable.increment` | `name`, optional `amount` | Increments a numeric value (default amount 1). |
| `workflow.variable.append` | `name`, `value` | Appends an item to a list variable. |
| `workflow.variable.remove` | `name` | Removes a variable. |

### Data Operations

Available Actions: `workflow.data.equals`, `greater_than`, `contains`, `is_empty`,
`is_null`, `and`, `or`, `not`, `length`, `get_item`, `filter`, `map`, `sort`,
`to_string`, `to_number`, `to_boolean`, `default_if_empty`, `coalesce`, and
`workflow.data.remove_item`.

`filter` accepts an expression such as:

```json
{"field": "age", "op": "greater_than", "value": 18}
```

Supported expression operators are `truthy`, `equals`, `not_equals`, `greater_than`,
`greater_or_equal`, `less_than`, `less_or_equal`, `contains`, and `is_null`.
`map` selects a `field` (including dotted paths) or returns a `literal`. These expressions are
declarative data, never executable Python.

Boolean conversion accepts booleans, numeric zero/non-zero, and explicit strings:
`true/false`, `1/0`, `yes/no`, `on/off`, and the empty string. Other strings raise
`ValueError`.

### Logging and Execution Utilities

| Action | Inputs | Behavior |
| --- | --- | --- |
| `workflow.log` | `message`, optional `level` | Logs at debug, info, warning, or error. |
| `workflow.log_variable` | `name` | Logs a variable; runtime references are redacted. |
| `workflow.delay` | `seconds` | Waits for a non-negative duration and cooperates with cancellation. |
| `workflow.retry` | optional `max_attempts`, `delay` | Retries a nested block after errors. |
| `workflow.timeout` | `seconds` | Sets a cooperative deadline for a nested block. |
| `workflow.assert` | `condition`, `message` | Raises when the condition is false. |
| `workflow.wait_until` | `condition`, `timeout`, `interval` | Polls until true or timed out. |
| `workflow.no_op` | — | Does nothing. |

Timeouts are cooperative: the Robot checks deadlines between Actions and cannot forcibly interrupt
an Action that blocks internally. The Robot emits Action start, success, and failure events
automatically; these events do not depend on `workflow.log`.

## Action Contracts

Each Action has a stable key and a versioned contract.

Examples:

```text
workflow.if
workflow.else_if
workflow.else
error_handling.try
error_handling.except
error_handling.finally
```

Action Contracts define the interface consumed by the IOMate runtime,
including:

- Inputs
- Outputs
- Type constraints
- Variable flags
- Contract version
- Execution metadata

Example:

```json
{
  "key": "workflow.if",
  "version": "1.0.0",
  "inputs": [
    {
      "name": "condition",
      "type": "boolean",
      "required": true
    }
  ],
  "outputs": []
}
```

Contract changes must preserve backward compatibility whenever possible.

Breaking changes require an appropriate contract version change.

---

## iomate-pkg-workflow

This Package depends on `iomate-base` for the core IOMate abstractions.

The dependency direction must remain:

```text
iomate-base
     ↑
     │
iomate-pkg-workflow
```

`iomate-pkg-workflow` must not implement its own versions of:

- Variables
- Type Definitions
- Actions
- Action Contracts
- Package Registry
- Runtime abstractions

These capabilities must come from `iomate-base`.

---

## Package Interoperability

The Package must remain independent of other IOMate Packages.

For example, `iomate-pkg-workflow` must not directly depend on:

```text
iomate-pkg-selenium
iomate-pkg-http
iomate-pkg-claude
```

Interoperability between Packages is achieved through the shared
IOMate runtime and Variables defined by `iomate-base`.

```text
iomate-base
        │
        │ Variables
        ▼
    IOMate Runtime
        ▲
        │
        │ Variables
        │
iomate-pkg-workflow
```

This keeps Packages independently installable and reusable.

---

## Testing

Run the complete test suite:

```bash
poetry run pytest
```

Run tests with coverage:

```bash
poetry run pytest --cov=src/iomate_pkg_workflow --cov-report=term
```

The project requires a minimum coverage of:

```text
80%
```

Tests should cover:

- Action registration
- Action discovery
- Action metadata
- Input validation
- Output definitions
- Action Contracts
- Conditional behavior
- Error-handling behavior
- Contract compatibility

---

## Code Quality

Run Ruff:

```bash
poetry run ruff check .
```

Check formatting:

```bash
poetry run ruff format --check .
```

Format the project:

```bash
poetry run ruff format .
```

Run MyPy:

```bash
poetry run mypy src
```

---

## Pre-commit

Install the project's pre-commit hooks:

```bash
poetry run pre-commit install
```

Run all hooks:

```bash
poetry run pre-commit run --all-files
```

Run tests and type checking separately:

```bash
poetry run pytest
poetry run mypy src
```

---

## Documentation

Documentation should be updated when changes affect:

- Action behavior
- Action Contracts
- Inputs
- Outputs
- Type constraints
- Error handling
- Control-flow semantics
- Package configuration
- Compatibility requirements

Public Actions should include clear documentation and type annotations.

---

## Versioning

`iomate-pkg-workflow` follows Semantic Versioning:

```text
MAJOR.MINOR.PATCH
```

Examples:

```text
1.0.0
1.1.0
1.1.1
```

### MAJOR

Breaking changes to public Package behavior or Action Contracts.

### MINOR

Backward-compatible functionality, such as:

- New Actions
- New optional inputs
- New Action Groups

### PATCH

Backward-compatible fixes, such as:

- Bug fixes
- Internal implementation corrections
- Documentation corrections

---

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for:

- Branching strategy
- Development workflow
- Pull Request requirements
- Testing requirements
- Commit conventions
- Release process

See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for the project's
community standards.

---

## Release Process

Releases are prepared from `staging`.

The general release flow is:

```text
feature branch
      ↓
Pull Request
      ↓
staging
      ↓
release preparation
      ↓
release
      ↓
version/tag
      ↓
PyPI
```

Before publishing a release:

- All CI checks must pass
- Version must be updated according to Semantic Versioning
- Action Contract compatibility must be reviewed
- Package dependencies must be validated
- Release notes should be prepared
- Package artifacts must be validated
- The final version must be tagged in Git

The release artifact is published to PyPI as:

```text
iomate-pkg-workflow
```

---

## License

See [LICENSE](LICENSE) for licensing information.

---

## Architecture

`iomate-pkg-workflow` depends on `iomate-base` for Actions, contracts, type definitions,
variables, package registration, and runtime result types. Runtime-managed behavior is implemented
by the Robot execution engine.

```text
iomate-base
    |
    +-- iomate-pkg-workflow (Action definitions)
    |
    +-- iomate-robot (execution semantics)
```


