processes 1.0.5__tar.gz → 2.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. {processes-1.0.5 → processes-2.0.1}/.github/workflows/docs.yml +11 -0
  2. {processes-1.0.5 → processes-2.0.1}/.github/workflows/lint.yml +4 -0
  3. {processes-1.0.5 → processes-2.0.1}/.github/workflows/mypy.yml +4 -0
  4. {processes-1.0.5 → processes-2.0.1}/.github/workflows/publish.yml +0 -3
  5. {processes-1.0.5 → processes-2.0.1}/.gitignore +2 -0
  6. {processes-1.0.5 → processes-2.0.1}/CHANGELOG.md +24 -0
  7. {processes-1.0.5 → processes-2.0.1}/PKG-INFO +107 -40
  8. processes-2.0.1/README.md +210 -0
  9. {processes-1.0.5 → processes-2.0.1}/assets/banner.svg +53 -22
  10. processes-2.0.1/assets/logo.png +0 -0
  11. processes-2.0.1/assets/logo.svg +71 -0
  12. processes-2.0.1/assets/social_banner.png +0 -0
  13. processes-2.0.1/assets/social_banner.svg +100 -0
  14. processes-2.0.1/docs/assets/favicon.svg +26 -0
  15. processes-2.0.1/docs/examples/advanced.md +215 -0
  16. processes-2.0.1/docs/examples/basic.md +160 -0
  17. processes-2.0.1/docs/examples/intro.md +13 -0
  18. processes-1.0.5/README.md → processes-2.0.1/docs/index.md +1 -4
  19. processes-2.0.1/docs/reference.md +9 -0
  20. {processes-1.0.5 → processes-2.0.1}/examples/02_task_dependencies_result_passing/README.md +1 -1
  21. processes-2.0.1/examples/README.md +40 -0
  22. processes-2.0.1/mkdocs.yml +53 -0
  23. processes-2.0.1/src/processes/exception_html_formatter.py +351 -0
  24. {processes-1.0.5 → processes-2.0.1}/src/processes/html_logging.py +42 -83
  25. {processes-1.0.5 → processes-2.0.1}/src/processes/process.py +9 -4
  26. {processes-1.0.5 → processes-2.0.1}/src/processes/task.py +21 -16
  27. processes-2.0.1/src/processes/themes/languages/de.json +15 -0
  28. processes-2.0.1/src/processes/themes/languages/en.json +15 -0
  29. processes-2.0.1/src/processes/themes/languages/es.json +15 -0
  30. processes-2.0.1/src/processes/themes/languages/fr.json +15 -0
  31. processes-2.0.1/src/processes/themes/languages/it.json +15 -0
  32. processes-2.0.1/src/processes/themes/languages/pt.json +15 -0
  33. processes-2.0.1/src/processes/themes/palettes/catppuccin.css +11 -0
  34. processes-2.0.1/src/processes/themes/palettes/neobones.css +11 -0
  35. processes-2.0.1/src/processes/themes/palettes/neutral.css +11 -0
  36. processes-2.0.1/src/processes/themes/palettes/slate.css +11 -0
  37. processes-2.0.1/src/processes/themes/styles/classic.html +49 -0
  38. processes-2.0.1/src/processes/themes/styles/compact.html +67 -0
  39. processes-2.0.1/src/processes/themes/styles/modern.html +115 -0
  40. processes-2.0.1/tests/conftest.py +9 -0
  41. processes-2.0.1/tests/manual_tests/__init__.py +0 -0
  42. processes-2.0.1/tests/manual_tests/manual_pipeline_inspect.py +423 -0
  43. processes-2.0.1/tests/manual_tests/manual_themed_tracebacks.py +302 -0
  44. processes-2.0.1/tests/test_complex_dag_failures.py +361 -0
  45. processes-2.0.1/tests/test_email_themes.py +489 -0
  46. processes-2.0.1/tests/test_examples.py +48 -0
  47. {processes-1.0.5 → processes-2.0.1}/tests/test_normal_run_no_errors.py +22 -14
  48. processes-2.0.1/tests/test_parallel_race_conditions.py +251 -0
  49. processes-1.0.5/docs/index.md +0 -127
  50. processes-1.0.5/docs/reference.md +0 -6
  51. processes-1.0.5/examples/README.md +0 -112
  52. processes-1.0.5/mkdocs.yml +0 -31
  53. processes-1.0.5/tests/mail_config.example.toml +0 -13
  54. processes-1.0.5/tests/manual_test_email.py +0 -103
  55. processes-1.0.5/tests/test_examples.py +0 -17
  56. {processes-1.0.5 → processes-2.0.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  57. {processes-1.0.5 → processes-2.0.1}/.github/ISSUE_TEMPLATE/custom.md +0 -0
  58. {processes-1.0.5 → processes-2.0.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  59. {processes-1.0.5 → processes-2.0.1}/.github/workflows/lint-pr.yml +0 -0
  60. {processes-1.0.5 → processes-2.0.1}/.github/workflows/tags.yml +0 -0
  61. {processes-1.0.5 → processes-2.0.1}/.github/workflows/tests.yml +0 -0
  62. {processes-1.0.5 → processes-2.0.1}/LICENSE +0 -0
  63. {processes-1.0.5 → processes-2.0.1}/examples/01_basic_tasks_and_dependencies/README.md +0 -0
  64. {processes-1.0.5 → processes-2.0.1}/examples/01_basic_tasks_and_dependencies/example1.py +0 -0
  65. {processes-1.0.5 → processes-2.0.1}/examples/02_task_dependencies_result_passing/example2.py +0 -0
  66. {processes-1.0.5 → processes-2.0.1}/pyproject.toml +0 -0
  67. {processes-1.0.5 → processes-2.0.1}/pytest.ini +0 -0
  68. {processes-1.0.5 → processes-2.0.1}/src/processes/__init__.py +0 -0
  69. {processes-1.0.5 → processes-2.0.1}/tests/__init__.py +0 -0
  70. {processes-1.0.5 → processes-2.0.1}/tests/log_cleaner.py +0 -0
  71. {processes-1.0.5 → processes-2.0.1}/tests/test_args_kwargs.py +0 -0
  72. {processes-1.0.5 → processes-2.0.1}/tests/test_dependencies.py +0 -0
  73. {processes-1.0.5 → processes-2.0.1}/tests/test_logfiles.py +0 -0
  74. {processes-1.0.5 → processes-2.0.1}/tests/test_unique_name.py +0 -0
  75. {processes-1.0.5 → processes-2.0.1}/uv.lock +0 -0
@@ -3,6 +3,17 @@ on:
3
3
  push:
4
4
  branches:
5
5
  - main
6
+ paths:
7
+ - "**.py"
8
+ - "docs/**"
9
+ - "mkdocs.yml"
10
+ pull_request:
11
+ branches:
12
+ - main
13
+ paths:
14
+ - "**.py"
15
+ - "docs/**"
16
+ - "mkdocs.yml"
6
17
  permissions:
7
18
  contents: write
8
19
  jobs:
@@ -3,8 +3,12 @@ name: Lint
3
3
  on:
4
4
  push:
5
5
  branches: [main]
6
+ paths:
7
+ - "**.py"
6
8
  pull_request:
7
9
  branches: [main]
10
+ paths:
11
+ - "**.py"
8
12
 
9
13
  jobs:
10
14
  lint:
@@ -3,8 +3,12 @@ name: mypy-check
3
3
  on:
4
4
  push:
5
5
  branches: [main]
6
+ paths:
7
+ - "**.py"
6
8
  pull_request:
7
9
  branches: [main]
10
+ paths:
11
+ - "**.py"
8
12
 
9
13
  jobs:
10
14
  lint:
@@ -18,9 +18,6 @@ jobs:
18
18
  - name: Ruff Check
19
19
  run: uv run ruff check .
20
20
 
21
- - name: Ruff Format
22
- run: uv run ruff format --check .
23
-
24
21
  - name: Mypy
25
22
  run: uv run mypy src
26
23
 
@@ -54,6 +54,8 @@ cover/
54
54
  # Translations
55
55
  *.mo
56
56
  *.pot
57
+ CLAUDE.md
58
+ /.claude
57
59
 
58
60
  # Django stuff:
59
61
  *.log
@@ -1,3 +1,27 @@
1
+ ## v2.0.1 (2026-06-12)
2
+
3
+ ### Fix
4
+
5
+ - **publish.yml**: remove unneeded step ruff format check in quality-gate
6
+
7
+ ## v2.0.0 (2026-06-12)
8
+
9
+ ### BREAKING CHANGE
10
+
11
+ - log records no longer carry
12
+ ``post_traceback_html_body``. Consumers introspecting that attribute
13
+ must read ``record.task_context`` instead.
14
+
15
+ ### Feat
16
+
17
+ - **email_alerting**: Traced Variables section with file:line reference in email body
18
+ - **email_alerting**: language alternatives for HTML email body
19
+ - **email_alerting**: template-driven HTML body from pure metadata
20
+
21
+ ### Fix
22
+
23
+ - **process**: parallel runner no longer raises on unrunnable tail
24
+
1
25
  ## v1.0.5 (2026-01-19)
2
26
 
3
27
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: processes
3
- Version: 1.0.5
3
+ Version: 2.0.1
4
4
  Summary: A Python library for managing and executing dependent tasks in parallel or sequential order with automatic dependency resolution and topological sorting
5
5
  Project-URL: Homepage, https://github.com/oliverm91/processes
6
6
  Project-URL: Documentation, https://oliverm91.github.io/processes/
@@ -26,7 +26,7 @@ Description-Content-Type: text/markdown
26
26
  <img src="https://raw.githubusercontent.com/oliverm91/processes/refs/heads/main/assets/banner.svg" width="100%" alt="Processes - Smart Task Orchestration">
27
27
  </div>
28
28
 
29
- # 🚀 Processes: Smart Task Orchestration
29
+ # 🚀 Processes: Robust Routines Management
30
30
 
31
31
  [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
32
32
  ![Fast & Lightweight](https://img.shields.io/badge/Library-Pure%20Python-green.svg)
@@ -92,53 +92,120 @@ The library operates on two main primitives:
92
92
  ---
93
93
 
94
94
  ## 💻 Quick Start
95
- Define your tasks and their dependencies. **Processes** will handle the execution order and data injection between tasks.
95
+
96
+ Four short examples — read top to bottom.
97
+
98
+ ### 1. One task
96
99
 
97
100
  ```python
98
- from datetime import date
101
+ from processes import Process, Task
99
102
 
100
- from processes import Process, Task, TaskDependency, HTMLSMTPHandler
103
+ def hello():
104
+ return 42
101
105
 
102
- # 1. Setup Email Alerts (Optional)
103
- smtp_handler = HTMLSMTPHandler(
104
- ('smtp_server', 587), 'sender@example.com', ['admin@example.com', 'user@example.com'],
105
- use_tls=True, credentials=('user', 'pass')
106
- )
106
+ tasks = [Task("greet", "run.log", hello)]
107
+
108
+ with Process(tasks) as process:
109
+ result = process.run()
110
+
111
+ print(result.passed_tasks_results["greet"].result) # 42
112
+ ```
113
+
114
+ ### 2. `args` and `kwargs`
115
+
116
+ `args` and `kwargs` are forwarded to your function — like `func(*args, **kwargs)`.
117
+
118
+ ```python
119
+ from processes import Process, Task
120
+
121
+ def fetch(source, *, limit=100, dry_run=False):
122
+ return ["row1", "row2"]
107
123
 
108
- # 2. If necessary, create wrappers for your Tasks.
109
- def get_previous_working_day():
110
- return date(2025, 12, 30)
111
- def indep_task():
112
- return "foo"
113
- def search_and_sum_csv(t: date):
114
- return 10
115
- def sum_data_from_csv_and_x(x, a=1, b=2):
116
- return x + a + b
117
-
118
- # 3. Create the Task Graph (order is irrelevant, that is handled by Process)
119
124
  tasks = [
120
- Task("t-1", "etl.log", get_previous_working_day),
121
- Task("intependent", "indep.log", indep_task, html_mail_handler=smtp_handler), # This task will send email on failure
122
- Task("sum_csv", "etl.log", search_and_sum_csv,
123
- dependencies= [
124
- TaskDependency("t-1",
125
- use_result_as_additional_args=True) # Adds result of t-1 task to search_and_sum_csv function as aditional args
126
- ]
127
- ),
128
- Task("sum_x_and_csv", "etl.log", sum_data_from_csv_and_x,
129
- args = (10,), kwargs = {"b": 100},
130
- dependencies=[
131
- TaskDependency("sum_csv",
132
- use_result_as_additional_kwargs=True,
133
- additional_kwarg_name="a")
134
- ]
135
- )
125
+ Task(
126
+ "fetch_orders", "run.log", fetch,
127
+ args=("orders_api",),
128
+ kwargs={"limit": 500, "dry_run": True},
129
+ ),
136
130
  ]
137
131
 
138
- # 4. Run the Process
139
- with Process(tasks) as process: # Context Manager ensures correct disposal of loggers
140
- process_result = process.run() # To enable parallelization use .run(parallel=True)
132
+ with Process(tasks) as process:
133
+ process.run()
134
+ ```
135
+
136
+ ### 3. Dependencies + result injection
137
+
138
+ `TaskDependency` orders tasks. To also pipe the upstream result into the downstream function, pick one:
139
+
140
+ * `use_result_as_additional_args=True` — appended as the next **positional** argument.
141
+ * `use_result_as_additional_kwargs=True` + `additional_kwarg_name="..."` — passed as a **keyword** argument.
142
+
143
+ ```python
144
+ from processes import Process, Task, TaskDependency
145
+
146
+ def load_users():
147
+ return [{"id": 1}, {"id": 2}, {"id": 3}]
148
+
149
+ def enrich(api_key, users): # `users` injected positionally
150
+ return [{**u, "name": f"user-{u['id']}"} for u in users]
151
+
152
+ def summarize(*, enriched, label="report"): # `enriched` injected as kwarg
153
+ return f"{label}: {len(enriched)} users"
154
+
155
+ tasks = [
156
+ Task("load", "run.log", load_users),
157
+
158
+ Task(
159
+ "enrich", "run.log", enrich,
160
+ args=("MY_API_KEY",),
161
+ dependencies=[
162
+ TaskDependency("load", use_result_as_additional_args=True),
163
+ ],
164
+ ),
165
+
166
+ Task(
167
+ "summary", "run.log", summarize,
168
+ kwargs={"label": "daily"},
169
+ dependencies=[
170
+ TaskDependency(
171
+ "enrich",
172
+ use_result_as_additional_kwargs=True,
173
+ additional_kwarg_name="enriched",
174
+ ),
175
+ ],
176
+ ),
177
+ ]
178
+
179
+ with Process(tasks) as process:
180
+ result = process.run(parallel=True)
181
+
182
+ print(result.passed_tasks_results["summary"].result)
183
+ # "daily: 3 users"
184
+ ```
185
+
186
+ > Task order doesn't matter — `Process` sorts them. A failure only skips its own dependents; the rest keeps running.
187
+
188
+ ### 4. Email alerts on failure
189
+
190
+ Attach an `HTMLSMTPHandler` to any task. If it raises, an HTML email is sent.
191
+
192
+ ```python
193
+ from processes import HTMLSMTPHandler, Process, Task
194
+
195
+ smtp = HTMLSMTPHandler(
196
+ mailhost=("smtp.example.com", 587),
197
+ fromaddr="alerts@example.com",
198
+ toaddrs=["oncall@example.com"],
199
+ credentials=("user", "pass"),
200
+ secure=(), # () = STARTTLS; omit for no encryption
201
+ )
202
+
203
+ tasks = [
204
+ Task("risky_step", "run.log", lambda: 1 / 0, html_mail_handler=smtp),
205
+ ]
141
206
 
207
+ with Process(tasks) as process:
208
+ process.run()
142
209
  ```
143
210
 
144
211
  ---
@@ -0,0 +1,210 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/oliverm91/processes/refs/heads/main/assets/banner.svg" width="100%" alt="Processes - Smart Task Orchestration">
3
+ </div>
4
+
5
+ # 🚀 Processes: Robust Routines Management
6
+
7
+ [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
8
+ ![Fast & Lightweight](https://img.shields.io/badge/Library-Pure%20Python-green.svg)
9
+
10
+
11
+ [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-blue.svg)](https://oliverm91.github.io/processes/)
12
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
13
+
14
+
15
+ [![Python Tests Status](https://github.com/oliverm91/processes/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/oliverm91/processes/actions/workflows/tests.yml)
16
+ [![Ruff Lint Status](https://github.com/oliverm91/processes/actions/workflows/lint.yml/badge.svg?branch=main)](https://github.com/oliverm91/processes/actions/workflows/lint.yml)
17
+ [![mypy-check](https://github.com/oliverm91/processes/actions/workflows/mypy.yml/badge.svg)](https://github.com/oliverm91/processes/actions/workflows/mypy.yml)
18
+
19
+ [![PyPI version](https://img.shields.io/pypi/v/processes.svg)](https://pypi.org/project/processes/)
20
+
21
+
22
+
23
+
24
+ **Processes** is a lightweight, high-performance Python library designed to execute complex task graphs. It manages **dependencies**, handles **parallel execution**, and ensures system resilience without any external libraries.
25
+
26
+ File logging and **email notification** is supported.
27
+
28
+ ---
29
+
30
+ ## 📑 Table of Contents
31
+ * [✨ Features](#-features)
32
+ * [⚙️ Core Concepts](#️-core-concepts)
33
+ * [🛠️ Use Cases](#️-use-cases)
34
+ * [💻 Quick Start](#-quick-start)
35
+ * [🛡️ Fault Tolerance & Logs](#️-fault-tolerance--logs)
36
+ * [📦 Installation](#-installation)
37
+
38
+ ---
39
+
40
+ ## ✨ Features
41
+
42
+ * **🐍 Pure Python:** Zero external dependencies. Built entirely on the **Python Standard Library**.
43
+ * **⚡ Parallel Execution:** Built-in support for parallelization to maximize throughput.
44
+ * **🔗 Dependency Resolution:** Automatically sorts and executes tasks based on their requirements, regardless of input order.
45
+ * **📝 Shared Logging:** Multiple tasks can write to the same logfile or maintain separate ones seamlessly.
46
+ * **📧 Email Notifications:** Integrated SMTP support (including HTML) to alert you the moment an exception occurs.
47
+
48
+ ---
49
+
50
+ ## ⚙️ Core Concepts
51
+
52
+ The library operates on two main primitives:
53
+
54
+ 1. **Task**: The atomic unit of work. It encapsulates a function, its parameters, its specific logfile, and its relationship with other tasks.
55
+ 2. **Process**: The orchestrator. It builds the execution graph, validates dependencies, and manages the lifecycle of the entire workflow.
56
+
57
+
58
+ ---
59
+
60
+ ## 🛠️ Use Cases
61
+ - **ETL Pipelines:** Fetch data from an API, transform it, and load it into a database as separate, dependent tasks.
62
+
63
+ - **System Maintenance:** Run parallel cleanup scripts, check server health, and receive email alerts if a specific check fails.
64
+
65
+ - **Automated Reporting:** Generate multiple data parts in parallel, aggregate them into a final report, and distribute via SMTP.
66
+
67
+
68
+ ---
69
+
70
+ ## 💻 Quick Start
71
+
72
+ Four short examples — read top to bottom.
73
+
74
+ ### 1. One task
75
+
76
+ ```python
77
+ from processes import Process, Task
78
+
79
+ def hello():
80
+ return 42
81
+
82
+ tasks = [Task("greet", "run.log", hello)]
83
+
84
+ with Process(tasks) as process:
85
+ result = process.run()
86
+
87
+ print(result.passed_tasks_results["greet"].result) # 42
88
+ ```
89
+
90
+ ### 2. `args` and `kwargs`
91
+
92
+ `args` and `kwargs` are forwarded to your function — like `func(*args, **kwargs)`.
93
+
94
+ ```python
95
+ from processes import Process, Task
96
+
97
+ def fetch(source, *, limit=100, dry_run=False):
98
+ return ["row1", "row2"]
99
+
100
+ tasks = [
101
+ Task(
102
+ "fetch_orders", "run.log", fetch,
103
+ args=("orders_api",),
104
+ kwargs={"limit": 500, "dry_run": True},
105
+ ),
106
+ ]
107
+
108
+ with Process(tasks) as process:
109
+ process.run()
110
+ ```
111
+
112
+ ### 3. Dependencies + result injection
113
+
114
+ `TaskDependency` orders tasks. To also pipe the upstream result into the downstream function, pick one:
115
+
116
+ * `use_result_as_additional_args=True` — appended as the next **positional** argument.
117
+ * `use_result_as_additional_kwargs=True` + `additional_kwarg_name="..."` — passed as a **keyword** argument.
118
+
119
+ ```python
120
+ from processes import Process, Task, TaskDependency
121
+
122
+ def load_users():
123
+ return [{"id": 1}, {"id": 2}, {"id": 3}]
124
+
125
+ def enrich(api_key, users): # `users` injected positionally
126
+ return [{**u, "name": f"user-{u['id']}"} for u in users]
127
+
128
+ def summarize(*, enriched, label="report"): # `enriched` injected as kwarg
129
+ return f"{label}: {len(enriched)} users"
130
+
131
+ tasks = [
132
+ Task("load", "run.log", load_users),
133
+
134
+ Task(
135
+ "enrich", "run.log", enrich,
136
+ args=("MY_API_KEY",),
137
+ dependencies=[
138
+ TaskDependency("load", use_result_as_additional_args=True),
139
+ ],
140
+ ),
141
+
142
+ Task(
143
+ "summary", "run.log", summarize,
144
+ kwargs={"label": "daily"},
145
+ dependencies=[
146
+ TaskDependency(
147
+ "enrich",
148
+ use_result_as_additional_kwargs=True,
149
+ additional_kwarg_name="enriched",
150
+ ),
151
+ ],
152
+ ),
153
+ ]
154
+
155
+ with Process(tasks) as process:
156
+ result = process.run(parallel=True)
157
+
158
+ print(result.passed_tasks_results["summary"].result)
159
+ # "daily: 3 users"
160
+ ```
161
+
162
+ > Task order doesn't matter — `Process` sorts them. A failure only skips its own dependents; the rest keeps running.
163
+
164
+ ### 4. Email alerts on failure
165
+
166
+ Attach an `HTMLSMTPHandler` to any task. If it raises, an HTML email is sent.
167
+
168
+ ```python
169
+ from processes import HTMLSMTPHandler, Process, Task
170
+
171
+ smtp = HTMLSMTPHandler(
172
+ mailhost=("smtp.example.com", 587),
173
+ fromaddr="alerts@example.com",
174
+ toaddrs=["oncall@example.com"],
175
+ credentials=("user", "pass"),
176
+ secure=(), # () = STARTTLS; omit for no encryption
177
+ )
178
+
179
+ tasks = [
180
+ Task("risky_step", "run.log", lambda: 1 / 0, html_mail_handler=smtp),
181
+ ]
182
+
183
+ with Process(tasks) as process:
184
+ process.run()
185
+ ```
186
+
187
+ ---
188
+
189
+ ## 🛡️ Fault Tolerance & Logs
190
+ ### Resilience by Design
191
+ If a `Task` raises an exception, the `Process` **does not stop**. It intelligently skips any tasks that depend on the failed one but continues to execute all other independent branches of your workflow.
192
+
193
+ ### Advanced Logging
194
+ All tasks record their execution flow to their assigned logfiles. You can share a single logfile across the whole process or isolate specific tasks for easier debugging.
195
+
196
+
197
+ ---
198
+
199
+ ## 📦 Installation
200
+
201
+ Registered in PyPI: https://pypi.org/project/processes/
202
+ ```bash
203
+ pip install processes
204
+ ```
205
+
206
+ Also, since it's a pure Python library, you can install it directly from the repository:
207
+
208
+ ```bash
209
+ pip install git+https://github.com/oliverm91/processes.git
210
+ ```
@@ -28,30 +28,61 @@
28
28
  <path d="M0,0 L1200,0 M0,100 L1200,100 M0,200 L1200,200 M0,300 L1200,300 M0,400 L1200,400" stroke="#4ecca3" stroke-width="1"/>
29
29
  </g>
30
30
 
31
- <!-- Task flow visualization (left side) -->
32
- <g opacity="0.8">
33
- <!-- Top branch flowing down -->
34
- <line x1="80" y1="120" x2="140" y2="120" stroke="#4ecca3" stroke-width="3" stroke-linecap="round"/>
35
- <line x1="140" y1="120" x2="200" y2="180" stroke="#4ecca3" stroke-width="3" stroke-linecap="round"/>
31
+ <!-- Task flow visualization (left side) - New logo design -->
32
+ <g opacity="0.9" transform="translate(30, 80)">
33
+ <!-- Connections (edges) -->
34
+ <g stroke-width="3" stroke-linecap="round">
35
+ <!-- Blue branches -->
36
+ <g stroke="#4ecca3" fill="none">
37
+ <!-- Top to second level -->
38
+ <path d="M 125 20 L 80 60"/>
39
+ <path d="M 125 20 L 170 60"/>
40
+
41
+ <!-- Second to third level -->
42
+ <path d="M 80 60 L 125 100"/>
43
+ <path d="M 170 60 L 125 100"/>
44
+ <path d="M 80 60 L 60 120"/>
45
+
46
+ <!-- Vertical parallel branches -->
47
+ <path d="M 125 100 L 125 185"/>
48
+ <path d="M 60 120 L 60 185"/>
49
+ </g>
50
+
51
+ <!-- Connection to failing task (blue) -->
52
+ <g stroke="#4ecca3" fill="none">
53
+ <path d="M 170 60 L 190 120"/>
54
+ </g>
55
+
56
+ <!-- Failed branch (red) -->
57
+ <g stroke="#ef4444" fill="none">
58
+ <path d="M 190 120 L 190 185"/>
59
+ </g>
60
+ </g>
36
61
 
37
- <!-- Middle branch straight -->
38
- <line x1="80" y1="200" x2="200" y2="200" stroke="#4ecca3" stroke-width="3" stroke-linecap="round"/>
62
+ <!-- Nodes (tasks) -->
63
+ <g fill="#4ecca3" filter="url(#glow)">
64
+ <!-- Top node -->
65
+ <circle cx="125" cy="20" r="8"/>
66
+
67
+ <!-- Second level -->
68
+ <circle cx="80" cy="60" r="8"/>
69
+ <circle cx="170" cy="60" r="8"/>
70
+
71
+ <!-- Third level -->
72
+ <circle cx="125" cy="100" r="8"/>
73
+ <circle cx="60" cy="120" r="7"/>
74
+
75
+ <!-- Final nodes -->
76
+ <circle cx="60" cy="190" r="10"/>
77
+ <circle cx="125" cy="190" r="10"/>
78
+ </g>
39
79
 
40
- <!-- Bottom branch flowing up -->
41
- <line x1="80" y1="280" x2="140" y2="280" stroke="#4ecca3" stroke-width="3" stroke-linecap="round"/>
42
- <line x1="140" y1="280" x2="200" y2="220" stroke="#4ecca3" stroke-width="3" stroke-linecap="round"/>
80
+ <!-- Failed branch nodes (red) -->
81
+ <g fill="#ef4444" filter="url(#glow)">
82
+ <circle cx="190" cy="120" r="7"/>
83
+ <circle cx="190" cy="190" r="10"/>
84
+ </g>
43
85
 
44
- <!-- Merge point -->
45
- <circle cx="200" cy="200" r="8" fill="#4ecca3" filter="url(#glow)"/>
46
-
47
- <!-- Arrow to right -->
48
- <line x1="200" y1="200" x2="314" y2="200" stroke="#4ecca3" stroke-width="3" stroke-linecap="round">
49
- <animate attributeName="stroke-dasharray" values="0 400; 400 0" dur="2s" repeatCount="indefinite"/>
50
- <animate attributeName="stroke-dashoffset" values="0; -400" dur="2s" repeatCount="indefinite"/>
51
- </line>
52
- <polygon points="320,200 305,193 305,207" fill="#4ecca3" filter="url(#glow)">
53
- <animate attributeName="opacity" values="0.5;1;0.5" dur="2s" repeatCount="indefinite"/>
54
- </polygon>
55
86
  </g>
56
87
 
57
88
  <!-- Main Title -->
@@ -61,7 +92,7 @@
61
92
 
62
93
  <!-- Subtitle -->
63
94
  <text x="600" y="210" font-family="'SF Mono', 'Monaco', 'Courier New', monospace" font-size="28" fill="#ffffff" text-anchor="middle" opacity="0.9">
64
- Smart Task Orchestration
95
+ Robust Routines Management
65
96
  </text>
66
97
 
67
98
  <!-- Feature badges -->
Binary file
@@ -0,0 +1,71 @@
1
+ <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1" />
5
+ <stop offset="100%" style="stop-color:#16213e;stop-opacity:1" />
6
+ </linearGradient>
7
+
8
+ <filter id="glow">
9
+ <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
10
+ <feMerge>
11
+ <feMergeNode in="coloredBlur"/>
12
+ <feMergeNode in="SourceGraphic"/>
13
+ </feMerge>
14
+ </filter>
15
+ </defs>
16
+
17
+ <!-- Transparent background -->
18
+
19
+ <!-- Task graph structure -->
20
+ <g stroke-width="3" stroke-linecap="round">
21
+ <!-- Blue branches -->
22
+ <g stroke="#4ecca3" fill="none">
23
+ <!-- Top to second level -->
24
+ <path d="M 250 120 L 160 200"/>
25
+ <path d="M 250 120 L 340 200"/>
26
+
27
+ <!-- Second to third level -->
28
+ <path d="M 160 200 L 250 280"/>
29
+ <path d="M 340 200 L 250 280"/>
30
+ <path d="M 160 200 L 120 300"/>
31
+
32
+ <!-- Vertical parallel branches -->
33
+ <path d="M 250 280 L 250 415"/>
34
+ <path d="M 120 300 L 120 415"/>
35
+ </g>
36
+
37
+ <!-- Connection to failing task (blue) -->
38
+ <g stroke="#4ecca3" fill="none">
39
+ <path d="M 340 200 L 380 300"/>
40
+ </g>
41
+
42
+ <!-- Failed branch (red) -->
43
+ <g stroke="#ef4444" fill="none">
44
+ <path d="M 380 300 L 380 415"/>
45
+ </g>
46
+
47
+ <!-- Nodes (tasks) -->
48
+ <g fill="#4ecca3" filter="url(#glow)">
49
+ <!-- Top node -->
50
+ <circle cx="250" cy="120" r="12"/>
51
+
52
+ <!-- Second level -->
53
+ <circle cx="160" cy="200" r="12"/>
54
+ <circle cx="340" cy="200" r="12"/>
55
+
56
+ <!-- Third level -->
57
+ <circle cx="250" cy="280" r="12"/>
58
+ <circle cx="120" cy="300" r="10"/>
59
+
60
+ <!-- Final nodes -->
61
+ <circle cx="120" cy="420" r="14"/>
62
+ <circle cx="250" cy="420" r="14"/>
63
+ </g>
64
+
65
+ <!-- Failed branch nodes (red) -->
66
+ <g fill="#ef4444" filter="url(#glow)">
67
+ <circle cx="380" cy="300" r="10"/>
68
+ <circle cx="380" cy="420" r="14"/>
69
+ </g>
70
+ </g>
71
+ </svg>
Binary file