smythe 0.2.0__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 (93) hide show
  1. smythe-0.2.0/.github/ISSUE_TEMPLATE/bug_report.md +45 -0
  2. smythe-0.2.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  3. smythe-0.2.0/.github/ISSUE_TEMPLATE/feature_request.md +36 -0
  4. smythe-0.2.0/.github/ISSUE_TEMPLATE/release-checklist.md +34 -0
  5. smythe-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +45 -0
  6. smythe-0.2.0/.github/workflows/ci.yml +49 -0
  7. smythe-0.2.0/.github/workflows/publish.yml +44 -0
  8. smythe-0.2.0/.gitignore +31 -0
  9. smythe-0.2.0/CHANGELOG.md +198 -0
  10. smythe-0.2.0/CODE_OF_CONDUCT.md +135 -0
  11. smythe-0.2.0/CONTRIBUTING.md +93 -0
  12. smythe-0.2.0/LICENSE +21 -0
  13. smythe-0.2.0/PKG-INFO +529 -0
  14. smythe-0.2.0/RELEASING.md +46 -0
  15. smythe-0.2.0/ROADMAP.md +42 -0
  16. smythe-0.2.0/Readme.md +483 -0
  17. smythe-0.2.0/SECURITY.md +72 -0
  18. smythe-0.2.0/docs/checkpoint-format.md +79 -0
  19. smythe-0.2.0/docs/mcp.md +69 -0
  20. smythe-0.2.0/examples/01_pipeline.yaml +29 -0
  21. smythe-0.2.0/examples/01_quickstart_yaml.py +25 -0
  22. smythe-0.2.0/examples/02_dynamic_planning.py +35 -0
  23. smythe-0.2.0/examples/03_parallel_budget.py +44 -0
  24. smythe-0.2.0/examples/04_resume_after_crash.py +72 -0
  25. smythe-0.2.0/examples/05_mcp_filesystem.py +107 -0
  26. smythe-0.2.0/examples/06_mcp_github.py +78 -0
  27. smythe-0.2.0/examples/07_mcp_saas.py +78 -0
  28. smythe-0.2.0/examples/README.md +18 -0
  29. smythe-0.2.0/examples/_providers.py +88 -0
  30. smythe-0.2.0/examples/mcp_file_server.py +37 -0
  31. smythe-0.2.0/plans/01-bug-fixes.md +271 -0
  32. smythe-0.2.0/plans/02-everything-else.md +357 -0
  33. smythe-0.2.0/plans/03-openclaw-agentskills-prd.md +279 -0
  34. smythe-0.2.0/plans/04-mcp-tool-support.md +241 -0
  35. smythe-0.2.0/pyproject.toml +66 -0
  36. smythe-0.2.0/smythe/__init__.py +83 -0
  37. smythe-0.2.0/smythe/agent.py +47 -0
  38. smythe-0.2.0/smythe/async_executor.py +148 -0
  39. smythe-0.2.0/smythe/budget.py +115 -0
  40. smythe-0.2.0/smythe/checkpoint.py +267 -0
  41. smythe-0.2.0/smythe/constrained_planner.py +189 -0
  42. smythe-0.2.0/smythe/constrained_prompts.py +63 -0
  43. smythe-0.2.0/smythe/executor.py +98 -0
  44. smythe-0.2.0/smythe/executor_base.py +163 -0
  45. smythe-0.2.0/smythe/graph.py +329 -0
  46. smythe-0.2.0/smythe/loader.py +171 -0
  47. smythe-0.2.0/smythe/mcp.py +338 -0
  48. smythe-0.2.0/smythe/memory.py +144 -0
  49. smythe-0.2.0/smythe/openclaw_adapter.py +61 -0
  50. smythe-0.2.0/smythe/planner.py +171 -0
  51. smythe-0.2.0/smythe/prompts.py +167 -0
  52. smythe-0.2.0/smythe/provider.py +496 -0
  53. smythe-0.2.0/smythe/registry.py +164 -0
  54. smythe-0.2.0/smythe/router.py +101 -0
  55. smythe-0.2.0/smythe/skills.py +70 -0
  56. smythe-0.2.0/smythe/swarm.py +490 -0
  57. smythe-0.2.0/smythe/synthesizer.py +187 -0
  58. smythe-0.2.0/smythe/task.py +25 -0
  59. smythe-0.2.0/smythe/tools.py +166 -0
  60. smythe-0.2.0/smythe/tracer.py +105 -0
  61. smythe-0.2.0/tests/__init__.py +0 -0
  62. smythe-0.2.0/tests/helpers.py +114 -0
  63. smythe-0.2.0/tests/mcp_test_server.py +35 -0
  64. smythe-0.2.0/tests/test_agent.py +83 -0
  65. smythe-0.2.0/tests/test_async_executor.py +359 -0
  66. smythe-0.2.0/tests/test_budget.py +193 -0
  67. smythe-0.2.0/tests/test_checkpoint.py +277 -0
  68. smythe-0.2.0/tests/test_constrained_planner.py +212 -0
  69. smythe-0.2.0/tests/test_examples_smoke.py +51 -0
  70. smythe-0.2.0/tests/test_executor.py +160 -0
  71. smythe-0.2.0/tests/test_executor_base.py +62 -0
  72. smythe-0.2.0/tests/test_graph.py +203 -0
  73. smythe-0.2.0/tests/test_graph_export.py +65 -0
  74. smythe-0.2.0/tests/test_integration.py +133 -0
  75. smythe-0.2.0/tests/test_llm_planner.py +334 -0
  76. smythe-0.2.0/tests/test_loader.py +321 -0
  77. smythe-0.2.0/tests/test_mcp.py +342 -0
  78. smythe-0.2.0/tests/test_memory.py +154 -0
  79. smythe-0.2.0/tests/test_offline_provider.py +51 -0
  80. smythe-0.2.0/tests/test_openclaw_adapter.py +89 -0
  81. smythe-0.2.0/tests/test_planner.py +67 -0
  82. smythe-0.2.0/tests/test_planner_inventory.py +120 -0
  83. smythe-0.2.0/tests/test_provider.py +505 -0
  84. smythe-0.2.0/tests/test_registry.py +130 -0
  85. smythe-0.2.0/tests/test_router.py +127 -0
  86. smythe-0.2.0/tests/test_skills.py +80 -0
  87. smythe-0.2.0/tests/test_skills_registry.py +219 -0
  88. smythe-0.2.0/tests/test_swarm.py +308 -0
  89. smythe-0.2.0/tests/test_synthesizer.py +214 -0
  90. smythe-0.2.0/tests/test_task.py +35 -0
  91. smythe-0.2.0/tests/test_tool_loop.py +249 -0
  92. smythe-0.2.0/tests/test_tools.py +111 -0
  93. smythe-0.2.0/tests/test_tracer.py +118 -0
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report incorrect or unexpected behavior
4
+ title: "[bug] "
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Summary
10
+
11
+ A clear, one-paragraph description of the bug.
12
+
13
+ ## Reproduction
14
+
15
+ Minimal code that reproduces the issue. A failing test against the smythe
16
+ test suite is ideal.
17
+
18
+ ```python
19
+ # Smallest possible repro
20
+ ```
21
+
22
+ ## Expected behavior
23
+
24
+ What you expected to happen.
25
+
26
+ ## Actual behavior
27
+
28
+ What actually happened. Include the full traceback if there is one.
29
+
30
+ ```
31
+ # Paste traceback here
32
+ ```
33
+
34
+ ## Environment
35
+
36
+ - smythe version (or commit SHA if installed from source):
37
+ - Python version (`python --version`):
38
+ - OS:
39
+ - Provider extras installed (anthropic / openai / gemini / openclaw / none):
40
+ - Model name (e.g. `claude-mythos`, `gpt-4o`, `gemini-3-pro`):
41
+
42
+ ## Additional context
43
+
44
+ Anything else that might help — relevant logs, configuration snippets,
45
+ related issues, hypotheses.
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Security vulnerability
4
+ url: https://github.com/petehottelet/smythe/security/advisories/new
5
+ about: Report a security issue privately via GitHub Security Advisories. Do not open a public issue for security bugs.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: Feature request
3
+ about: Propose a new capability or enhancement
4
+ title: "[feature] "
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Problem
10
+
11
+ What problem are you trying to solve? What use case is currently awkward
12
+ or impossible?
13
+
14
+ ## Proposed solution
15
+
16
+ What you'd like to see. Sketch the API or behavior if you have one in mind.
17
+
18
+ ```python
19
+ # Optional: sketch of the proposed API
20
+ ```
21
+
22
+ ## Alternatives considered
23
+
24
+ Other approaches you thought about, and why this one is preferred.
25
+
26
+ ## Scope and breaking changes
27
+
28
+ - Does this change the public API? If so, how?
29
+ - Are there backward-compatible incremental steps?
30
+ - Roughly how big is this — a single function, a new module, or a multi-sprint
31
+ initiative?
32
+
33
+ ## Additional context
34
+
35
+ Links to relevant issues, prior art in other frameworks (LangGraph, CrewAI,
36
+ AutoGen, etc.), or specs.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: Release checklist
3
+ about: Steps for cutting a release to PyPI
4
+ title: "Release vX.Y.Z"
5
+ labels: roadmap
6
+ ---
7
+
8
+ # Release Checklist
9
+
10
+ ## Preflight
11
+
12
+ - [ ] `pyproject.toml` version has been bumped (PyPI never allows re-uploading a version).
13
+ - [ ] `smythe/__init__.py` `__version__` matches.
14
+ - [ ] `CHANGELOG.md` has a section for this version.
15
+ - [ ] README install instructions mention `pip install smythe`.
16
+ - [ ] Tests pass locally.
17
+ - [ ] Build passes locally with `python -m build`.
18
+ - [ ] Package validates with `python -m twine check dist/*`.
19
+ - [ ] Built wheel installs and imports in a fresh venv.
20
+
21
+ ## GitHub
22
+
23
+ - [ ] `.github/workflows/publish.yml` exists on the default branch.
24
+ - [ ] GitHub environment `pypi` exists (Settings → Environments).
25
+ - [ ] Release notes are drafted.
26
+ - [ ] Git tag matches the package version, e.g. `v0.2.0`.
27
+
28
+ ## PyPI
29
+
30
+ - [ ] Pending/trusted publisher exists for `petehottelet/smythe`.
31
+ - [ ] Publisher workflow is `publish.yml`.
32
+ - [ ] Publisher environment is `pypi`.
33
+ - [ ] Release workflow publishes successfully.
34
+ - [ ] `pip install smythe` works from a clean venv after release.
@@ -0,0 +1,45 @@
1
+ <!-- Thanks for contributing to smythe! Please fill out the sections below. -->
2
+
3
+ ## Summary
4
+
5
+ What does this PR change, and why? One or two sentences focused on the "why"
6
+ rather than the "what".
7
+
8
+ ## Linked issue
9
+
10
+ Closes #<issue-number> <!-- or "Refs #..." if not closing -->
11
+
12
+ ## Type of change
13
+
14
+ - [ ] Bug fix (non-breaking)
15
+ - [ ] New feature (non-breaking)
16
+ - [ ] Breaking change (API or behavior change — call out the migration path)
17
+ - [ ] Documentation only
18
+ - [ ] Test / CI / tooling only
19
+
20
+ ## Testing
21
+
22
+ How did you verify this change?
23
+
24
+ - [ ] Added new tests covering this change
25
+ - [ ] Existing tests cover this change
26
+ - [ ] Manually exercised — describe how:
27
+
28
+ ```
29
+ # Paste relevant test output, or describe the manual run
30
+ ```
31
+
32
+ ## Checklist
33
+
34
+ - [ ] `ruff check smythe/ tests/` passes locally
35
+ - [ ] `pytest tests/` passes locally on at least one supported Python version
36
+ - [ ] [CHANGELOG.md](../CHANGELOG.md) updated under `[Unreleased]` for any
37
+ user-facing change
38
+ - [ ] Public API additions/changes are documented in docstrings and
39
+ [Readme.md](../Readme.md) where appropriate
40
+ - [ ] No "created with X" attribution in commit messages
41
+ - [ ] No emojis in code or commit messages (unless explicitly requested)
42
+
43
+ ## Breaking changes
44
+
45
+ If this is a breaking change, describe the migration path users should follow.
@@ -0,0 +1,49 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.11"
17
+ - run: pip install ruff
18
+ - run: ruff check smythe/ tests/
19
+
20
+ test:
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ matrix:
24
+ python-version: ["3.11", "3.12", "3.13"]
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+
29
+ - name: Set up Python ${{ matrix.python-version }}
30
+ uses: actions/setup-python@v5
31
+ with:
32
+ python-version: ${{ matrix.python-version }}
33
+
34
+ - name: Install dependencies
35
+ run: |
36
+ python -m pip install --upgrade pip
37
+ pip install -e .
38
+ pip install pytest pytest-asyncio pytest-cov
39
+
40
+ - name: Run tests
41
+ run: python -m pytest tests/ -v --cov=smythe --cov-report=term --cov-report=xml
42
+
43
+ - name: Upload coverage report (artifact)
44
+ if: matrix.python-version == '3.11'
45
+ uses: actions/upload-artifact@v4
46
+ with:
47
+ name: coverage-xml
48
+ path: coverage.xml
49
+ if-no-files-found: warn
@@ -0,0 +1,44 @@
1
+ name: Publish to PyPI
2
+
3
+ # Trusted publishing: PyPI's pending publisher is configured to trust
4
+ # exactly this workflow filename (publish.yml) and the `pypi` GitHub
5
+ # environment. No API token — GitHub OIDC via id-token: write.
6
+
7
+ on:
8
+ release:
9
+ types: [published]
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ publish:
17
+ name: Build and publish to PyPI
18
+ runs-on: ubuntu-latest
19
+ environment: pypi
20
+
21
+ permissions:
22
+ id-token: write
23
+ contents: read
24
+
25
+ steps:
26
+ - name: Check out repository
27
+ uses: actions/checkout@v4
28
+
29
+ - name: Set up Python
30
+ uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.11"
33
+
34
+ - name: Install build tools
35
+ run: python -m pip install --upgrade pip build twine
36
+
37
+ - name: Build package
38
+ run: python -m build
39
+
40
+ - name: Check package
41
+ run: python -m twine check dist/*
42
+
43
+ - name: Publish package to PyPI
44
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,31 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ dist/
6
+ build/
7
+ *.egg-info/
8
+ *.egg
9
+ .eggs/
10
+ *.whl
11
+ .venv/
12
+ venv/
13
+ env/
14
+ .env
15
+ *.log
16
+ .mypy_cache/
17
+ .pytest_cache/
18
+ .ruff_cache/
19
+ .tox/
20
+ .coverage
21
+ htmlcov/
22
+ .idea/
23
+ .vscode/
24
+ *.swp
25
+ *.swo
26
+ *~
27
+ .DS_Store
28
+ Thumbs.db
29
+
30
+ # Local working notes (TODOs, project instructions, scratch)
31
+ 00_project_files/
@@ -0,0 +1,198 @@
1
+ # Changelog
2
+
3
+ All notable changes to **smythe** are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
7
+ with the pre-1.0 stability note below.
8
+
9
+ ## Versioning policy (pre-1.0)
10
+
11
+ While the project is on a `0.x` line, the public API is **not yet stable**:
12
+
13
+ - `0.x` minor bumps (e.g. `0.1.0` -> `0.2.0`) MAY include backward-incompatible changes.
14
+ Each minor release will document its breaking changes in this file.
15
+ - `0.x.y` patch bumps (e.g. `0.1.0` -> `0.1.1`) are **non-breaking** and contain only
16
+ bug fixes, documentation, or internal improvements.
17
+ - The first stable release will be `1.0.0`. Until then, pin to a specific minor
18
+ version (`smythe~=0.1.0`) if API stability matters to you.
19
+
20
+ ---
21
+
22
+ ## [Unreleased]
23
+
24
+ Future work tracked in [ROADMAP.md](ROADMAP.md).
25
+
26
+ ---
27
+
28
+ ## [0.2.0] - 2026-07-05
29
+
30
+ First PyPI release. The v0.2 line makes agents real: they use tools, survive
31
+ crashes, and everything they do is visible.
32
+
33
+ ### Added
34
+
35
+ - **Provider tool contract** — neutral tool-calling types (`ToolSpec`, `ToolCall`,
36
+ `ToolResult`, `ChatMessage`) and `Provider.chat()`, mapped to native tool use on
37
+ Anthropic, OpenAI, and Gemini. First milestone of MCP tool support
38
+ (plans/04-mcp-tool-support.md).
39
+ - **MCP tool support** — agents consume MCP servers as tool sources
40
+ (`pip install smythe[mcp]`): `MCPServerSpec` (stdio + streamable HTTP) with
41
+ `env_passthrough` secret handling (variable names in config, values resolved
42
+ from the environment — never serialized), per-server `allowed_tools` with a
43
+ large-toolset warning, per-call timeouts, and cancellation-safe teardown.
44
+ `MCPSkillProvider` grounds capability-based assignment in real tools, and the
45
+ `LLMArchitect` planning prompt now includes an available-agents/tools
46
+ inventory so plans exploit the toolset. Examples: offline filesystem
47
+ (bundled server), GitHub (allowlisted), and generic SaaS over HTTP.
48
+ Docs and threat model: docs/mcp.md.
49
+ - **Tool-calling loop** — nodes whose Swarm has a `tool_runtime` run a bounded
50
+ tool loop: `max_tool_iterations` circuit breaker (per node and per Swarm),
51
+ mid-loop budget enforcement, per-call trace entries, tool failures fed back to
52
+ the model as error results, and `timeout_s` covering the whole loop. Budget
53
+ recording moved into the loop via the new accumulating `Sentinel.add_cost()`;
54
+ `node.metadata["cost_usd"]` is now cumulative across a node's provider calls.
55
+ `ToolRuntime` / `ToolSession` define the interface the MCP runtime implements
56
+ next (plans/04 M2).
57
+ - **Graph export** — `ExecutionGraph.to_mermaid()` (with node-status styling),
58
+ `to_dot()`, and `to_json()` (with per-node cost).
59
+ - **`OfflineProvider`** — deterministic, no-network provider; every example runs
60
+ offline and CI smoke-tests them with API keys stripped.
61
+ - **OpenAI-compatible `base_url`** on `OpenAIProvider` (env: `OPENAI_BASE_URL`) for
62
+ Ollama, LM Studio, vLLM, and other compatible endpoints.
63
+ - **Release workflow** — tag-triggered PyPI publishing via trusted publishing, plus
64
+ README badges and a public [ROADMAP.md](ROADMAP.md).
65
+
66
+ - **Durable, resumable execution** — `Swarm(checkpoint_store=...)` persists the full
67
+ execution state (graph, node results, agents, budget consumed) after every node.
68
+ `swarm.resume(execution_id)` picks up from the last completed node; finished nodes
69
+ are never re-executed and cost accounting continues against the original cap.
70
+ Ships with `FileCheckpointStore` (one JSON file per execution, atomic writes) and a
71
+ `CheckpointStore` ABC for custom backends. Format documented in
72
+ docs/checkpoint-format.md; demonstrated in examples/04_resume_after_crash.py.
73
+
74
+ - **Per-node timeouts** — `Node.timeout_s` (also settable in YAML) caps the wall-clock
75
+ time of a single execution attempt in both executors; timeouts are handled by the
76
+ node's failure policy like any other error.
77
+ - **Concurrency cap** — `AsyncExecutor(max_concurrency=...)` bounds in-flight provider
78
+ calls; exposed as `Swarm(max_concurrency=...)` with a default of 8.
79
+ - **`examples/` directory** — three runnable scripts (YAML quickstart, dynamic LLM
80
+ planning, budget-capped parallel run) that work offline via a built-in demo provider.
81
+
82
+ ### Changed
83
+
84
+ - README aligned with shipped behavior: recursive subgraph decomposition, approval
85
+ gates, and performance-history routing are now explicitly labeled roadmap items.
86
+ - Executor and AsyncExecutor share a single provider-call path
87
+ (`ExecutorBase.acall_node`), removing duplicated prompt-building logic.
88
+
89
+ ### Fixed
90
+
91
+ - Deflaked `test_registry_cache_expires_after_ttl` (deterministic clock instead of
92
+ `time.sleep`).
93
+
94
+ ---
95
+
96
+ ## [0.1.0] - 2026-03-28
97
+
98
+ Initial public release.
99
+
100
+ ### Added — Core runtime
101
+
102
+ - **Task -> Architect -> Graph -> Executor -> Synthesizer pipeline.** The full
103
+ orchestration loop from a `Task` through plan generation, parallel or serial
104
+ execution, and output synthesis.
105
+ - **`ExecutionGraph` DAG model** with first-class topology
106
+ (`SERIAL`, `FORK_JOIN`, `BROADCAST_REDUCE`), per-node status (`PENDING`,
107
+ `RUNNING`, `COMPLETED`, `FAILED`, `SKIPPED`), failure policies
108
+ (`HALT`, `SKIP`, `RETRY`), and dependency edges with cycle, duplicate-ID,
109
+ and unknown-dependency validation.
110
+ - **Three-tier architect routing via `WhiteRabbit`** — deterministic
111
+ (template-based), constrained (LLM with strict topology vocabulary), and
112
+ autonomous (`LLMArchitect`, full freedom). Routes by classifier prompt or
113
+ explicit override.
114
+ - **`Architect` implementations** — `SimpleArchitect` (single-node fallback),
115
+ `DeterministicArchitect` (template-based), `ConstrainedArchitect`
116
+ (LLM with restricted topology vocabulary), `LLMArchitect` (autonomous,
117
+ with JSON-mode planning and context-preserving retries on malformed output).
118
+ - **`AsyncExecutor`** — concurrent DAG execution with topological wave
119
+ scheduling, deadlock detection, and partial-reservation rollback on
120
+ budget exhaustion mid-wave.
121
+ - **`Executor`** — serial DAG execution with the same failure-policy
122
+ semantics as the async executor.
123
+ - **`Sentinel` budget guardrails** — reservation/record/release protocol
124
+ for safe concurrent cost tracking, with hard USD caps and per-node
125
+ cost attribution.
126
+ - **`Synthesizer`** with three strategies: `CONCATENATE` (zero-cost join),
127
+ `STRUCTURED` (JSON shallow-merge), and `LLM_MERGE` (provider-backed
128
+ intelligent synthesis with optional budget and tracer integration).
129
+ - **`Tracer`** — structured per-node spans with start/end/error hooks
130
+ and a JSON-serializable summary for downstream observability.
131
+ - **`Registry` and `Agent`/`AgentProfile`** — persistent agent identities
132
+ with capabilities, persona, and append-only execution history.
133
+ - **`PlannerMemory`** — JSONL-backed outcome store for the architect
134
+ feedback loop (recall surface implemented; closing the loop into
135
+ prompt context is on the roadmap).
136
+ - **YAML pipeline loader** (`Swarm.from_yaml`) — declare a graph and
137
+ agent registry in YAML and execute it directly.
138
+ - **Skills system** (`SkillRef`, `SkillProvider`, `CapabilityMapper`)
139
+ for capability hydration from external skill inventories.
140
+
141
+ ### Added — LLM providers
142
+
143
+ - **`AnthropicProvider`** — async wrapper over the official `anthropic` SDK.
144
+ - **`OpenAIProvider`** — async wrapper over the official `openai` SDK.
145
+ - **`GeminiProvider`** — async wrapper over the official `google-genai` SDK,
146
+ including support for `gemini-3-pro-image-preview` and other Gemini models.
147
+ - **Auto-detection** in `Swarm` — picks the right provider from the model
148
+ name prefix (`claude*`, `gpt*`/`o1`/`o3`/`o4`, `gemini*`).
149
+ - **`OpenClawSkillProvider`** — adapter for OpenClaw `AgentSkills`,
150
+ translating SDK skill objects into `SkillRef`s for capability hydration.
151
+
152
+ ### Added — Testing & CI
153
+
154
+ - **240 passing tests, 3 skipped** across the full suite, including
155
+ dedicated test files for router edge cases, tracer/span lifecycle,
156
+ agent model invariants, and a full pipeline integration suite.
157
+ - **Shared test fixtures** in `tests/helpers.py` (mock providers,
158
+ failing providers, classifier mocks, fixed architects, completed-graph
159
+ builder).
160
+ - **GitHub Actions CI** ([.github/workflows/ci.yml](.github/workflows/ci.yml))
161
+ with `ruff` lint and a `pytest` matrix across Python 3.11 / 3.12 / 3.13.
162
+
163
+ ### Fixed
164
+
165
+ - **Async exception masking** — `AsyncExecutor` cascading failures no
166
+ longer mask the original exception with a `RuntimeError`.
167
+ - **Partial-reservation leak in `AsyncExecutor`** — if `Sentinel.reserve()`
168
+ fails partway through a wave, all previously successful reservations in
169
+ that wave are now released before the exception propagates.
170
+ - **Synthesizer model passthrough** — `LLM_MERGE` synthesis now receives the
171
+ swarm's configured model instead of an empty string.
172
+ - **Direct-graph validation** — `Swarm.execute(graph)` (with a pre-built
173
+ `ExecutionGraph` instead of a `Task`) now runs `graph.validate()` before
174
+ execution.
175
+ - **Executor dependency guard** — `Executor._walk` now raises a clear
176
+ `ValueError` (instead of a `KeyError`) when a node depends on an unknown
177
+ node ID.
178
+ - **`LLMArchitect` retry robustness** — `aplan` now also recovers from
179
+ `TypeError` during LLM-response parsing, not only `ValueError`.
180
+
181
+ ### Documentation
182
+
183
+ - **`Readme.md`** — full pitch, four worked examples (fork-join, broadcast-reduce,
184
+ YAML pipeline, agent registry), API reference for the public surface,
185
+ installation instructions for each provider extra, and an "Async usage"
186
+ section documenting `asyncio.run()` limitations and recommending the
187
+ async APIs (`aplan`, `execute_async`).
188
+ - **`LICENSE`** — MIT.
189
+
190
+ ### Known issues
191
+
192
+ - **`tests/test_skills_registry.py::test_registry_cache_expires_after_ttl`** is
193
+ timing-flaky on Windows under suite load. The test uses a 50ms TTL with a
194
+ 60ms sleep, which is too tight for `time.sleep()` precision on Windows.
195
+ Passes consistently in isolation. Tracked for fix in 0.1.1.
196
+
197
+ [Unreleased]: https://github.com/petehottelet/smythe/compare/v0.1.0...HEAD
198
+ [0.1.0]: https://github.com/petehottelet/smythe/releases/tag/v0.1.0
@@ -0,0 +1,135 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ - Demonstrating empathy and kindness toward other people
21
+ - Being respectful of differing opinions, viewpoints, and experiences
22
+ - Giving and gracefully accepting constructive feedback
23
+ - Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ - Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ - The use of sexualized language or imagery, and sexual attention or advances
31
+ of any kind
32
+ - Trolling, insulting or derogatory comments, and personal or political attacks
33
+ - Public or private harassment
34
+ - Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ - Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the project maintainers via a private GitHub message to
63
+ [@petehottelet](https://github.com/petehottelet) or by opening a confidential
64
+ [security advisory](https://github.com/petehottelet/smythe/security/advisories/new)
65
+ on this repository.
66
+
67
+ All complaints will be reviewed and investigated promptly and fairly.
68
+
69
+ All community leaders are obligated to respect the privacy and security of the
70
+ reporter of any incident.
71
+
72
+ ## Enforcement Guidelines
73
+
74
+ Community leaders will follow these Community Impact Guidelines in determining
75
+ the consequences for any action they deem in violation of this Code of Conduct:
76
+
77
+ ### 1. Correction
78
+
79
+ **Community Impact**: Use of inappropriate language or other behavior deemed
80
+ unprofessional or unwelcome in the community.
81
+
82
+ **Consequence**: A private, written warning from community leaders, providing
83
+ clarity around the nature of the violation and an explanation of why the
84
+ behavior was inappropriate. A public apology may be requested.
85
+
86
+ ### 2. Warning
87
+
88
+ **Community Impact**: A violation through a single incident or series of
89
+ actions.
90
+
91
+ **Consequence**: A warning with consequences for continued behavior. No
92
+ interaction with the people involved, including unsolicited interaction with
93
+ those enforcing the Code of Conduct, for a specified period of time. This
94
+ includes avoiding interactions in community spaces as well as external channels
95
+ like social media. Violating these terms may lead to a temporary or permanent
96
+ ban.
97
+
98
+ ### 3. Temporary Ban
99
+
100
+ **Community Impact**: A serious violation of community standards, including
101
+ sustained inappropriate behavior.
102
+
103
+ **Consequence**: A temporary ban from any sort of interaction or public
104
+ communication with the community for a specified period of time. No public or
105
+ private interaction with the people involved, including unsolicited interaction
106
+ with those enforcing the Code of Conduct, is allowed during this period.
107
+ Violating these terms may lead to a permanent ban.
108
+
109
+ ### 4. Permanent Ban
110
+
111
+ **Community Impact**: Demonstrating a pattern of violation of community
112
+ standards, including sustained inappropriate behavior, harassment of an
113
+ individual, or aggression toward or disparagement of classes of individuals.
114
+
115
+ **Consequence**: A permanent ban from any sort of public interaction within the
116
+ community.
117
+
118
+ ## Attribution
119
+
120
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
121
+ version 2.1, available at
122
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
123
+
124
+ Community Impact Guidelines were inspired by
125
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
126
+
127
+ For answers to common questions about this code of conduct, see the FAQ at
128
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
129
+ [https://www.contributor-covenant.org/translations][translations].
130
+
131
+ [homepage]: https://www.contributor-covenant.org
132
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
133
+ [Mozilla CoC]: https://github.com/mozilla/diversity
134
+ [FAQ]: https://www.contributor-covenant.org/faq
135
+ [translations]: https://www.contributor-covenant.org/translations