aofire-python-agent 0.1.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 (52) hide show
  1. aofire_python_agent-0.1.0/.github/workflows/fuzz.yml +17 -0
  2. aofire_python_agent-0.1.0/.github/workflows/lint.yml +16 -0
  3. aofire_python_agent-0.1.0/.github/workflows/mutation.yml +40 -0
  4. aofire_python_agent-0.1.0/.github/workflows/taint.yml +16 -0
  5. aofire_python_agent-0.1.0/.github/workflows/test.yml +17 -0
  6. aofire_python_agent-0.1.0/.github/workflows/typecheck.yml +16 -0
  7. aofire_python_agent-0.1.0/.gitignore +15 -0
  8. aofire_python_agent-0.1.0/CLAUDE.md +105 -0
  9. aofire_python_agent-0.1.0/LICENSE +28 -0
  10. aofire_python_agent-0.1.0/PKG-INFO +405 -0
  11. aofire_python_agent-0.1.0/README.md +380 -0
  12. aofire_python_agent-0.1.0/pyproject.toml +77 -0
  13. aofire_python_agent-0.1.0/setup.cfg +4 -0
  14. aofire_python_agent-0.1.0/src/aofire_python_agent.egg-info/PKG-INFO +405 -0
  15. aofire_python_agent-0.1.0/src/aofire_python_agent.egg-info/SOURCES.txt +50 -0
  16. aofire_python_agent-0.1.0/src/aofire_python_agent.egg-info/dependency_links.txt +1 -0
  17. aofire_python_agent-0.1.0/src/aofire_python_agent.egg-info/entry_points.txt +7 -0
  18. aofire_python_agent-0.1.0/src/aofire_python_agent.egg-info/requires.txt +13 -0
  19. aofire_python_agent-0.1.0/src/aofire_python_agent.egg-info/top_level.txt +1 -0
  20. aofire_python_agent-0.1.0/src/python_agent/CLAUDE.md +105 -0
  21. aofire_python_agent-0.1.0/src/python_agent/__init__.py +3 -0
  22. aofire_python_agent-0.1.0/src/python_agent/agent_utils.py +61 -0
  23. aofire_python_agent-0.1.0/src/python_agent/call_graph.py +694 -0
  24. aofire_python_agent-0.1.0/src/python_agent/coding_agent.py +193 -0
  25. aofire_python_agent-0.1.0/src/python_agent/convergence_agent.py +362 -0
  26. aofire_python_agent-0.1.0/src/python_agent/dag_integrity.py +198 -0
  27. aofire_python_agent-0.1.0/src/python_agent/dag_utils.py +181 -0
  28. aofire_python_agent-0.1.0/src/python_agent/discovery_agent.py +348 -0
  29. aofire_python_agent-0.1.0/src/python_agent/divergence_agent.py +302 -0
  30. aofire_python_agent-0.1.0/src/python_agent/ontology.py +270 -0
  31. aofire_python_agent-0.1.0/src/python_agent/planning_agent.py +83 -0
  32. aofire_python_agent-0.1.0/src/python_agent/py.typed +0 -0
  33. aofire_python_agent-0.1.0/src/python_agent/rules.py +383 -0
  34. aofire_python_agent-0.1.0/src/python_agent/tool_guard.py +164 -0
  35. aofire_python_agent-0.1.0/src/python_agent/tools/__init__.py +0 -0
  36. aofire_python_agent-0.1.0/src/python_agent/types.py +38 -0
  37. aofire_python_agent-0.1.0/tests/__init__.py +0 -0
  38. aofire_python_agent-0.1.0/tests/conftest.py +9 -0
  39. aofire_python_agent-0.1.0/tests/test_agent_utils.py +107 -0
  40. aofire_python_agent-0.1.0/tests/test_call_graph.py +1059 -0
  41. aofire_python_agent-0.1.0/tests/test_coding_agent.py +470 -0
  42. aofire_python_agent-0.1.0/tests/test_convergence_agent.py +584 -0
  43. aofire_python_agent-0.1.0/tests/test_dag_integrity.py +430 -0
  44. aofire_python_agent-0.1.0/tests/test_dag_utils.py +290 -0
  45. aofire_python_agent-0.1.0/tests/test_discovery_agent.py +768 -0
  46. aofire_python_agent-0.1.0/tests/test_divergence_agent.py +547 -0
  47. aofire_python_agent-0.1.0/tests/test_fuzz.py +629 -0
  48. aofire_python_agent-0.1.0/tests/test_injection_defense.py +200 -0
  49. aofire_python_agent-0.1.0/tests/test_ontology.py +756 -0
  50. aofire_python_agent-0.1.0/tests/test_planning_agent.py +278 -0
  51. aofire_python_agent-0.1.0/tests/test_rules.py +157 -0
  52. aofire_python_agent-0.1.0/tests/test_tool_guard.py +402 -0
@@ -0,0 +1,17 @@
1
+ name: Fuzz
2
+ on:
3
+ schedule:
4
+ - cron: "0 6 * * 1"
5
+ push:
6
+ tags: ["v*"]
7
+ workflow_dispatch:
8
+ jobs:
9
+ fuzz:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.11"
16
+ - run: pip install -e ".[dev]"
17
+ - run: pytest tests/test_fuzz.py --hypothesis-profile=ci -v
@@ -0,0 +1,16 @@
1
+ name: Lint
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+ jobs:
8
+ lint:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.11"
15
+ - run: pip install -e ".[dev]"
16
+ - run: flake8 --max-complexity=5 src/ tests/
@@ -0,0 +1,40 @@
1
+ name: Mutation
2
+ on:
3
+ schedule:
4
+ - cron: "0 6 * * 1"
5
+ push:
6
+ tags: ["v*"]
7
+ workflow_dispatch:
8
+ jobs:
9
+ mutmut:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ module:
15
+ - coding_agent
16
+ - planning_agent
17
+ - discovery_agent
18
+ - divergence_agent
19
+ - convergence_agent
20
+ - ontology
21
+ - dag_utils
22
+ - dag_integrity
23
+ - tool_guard
24
+ - call_graph
25
+ - rules
26
+ - types
27
+ name: ${{ matrix.module }}
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.11"
33
+ - run: pip install -e ".[dev]" "mutmut<3"
34
+ - name: mutmut ${{ matrix.module }}
35
+ run: |
36
+ mutmut run \
37
+ --paths-to-mutate=src/python_agent/${{ matrix.module }}.py \
38
+ --runner="python -m pytest" \
39
+ || true
40
+ mutmut results
@@ -0,0 +1,16 @@
1
+ name: Taint Analysis
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+ jobs:
8
+ taint:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.11"
15
+ - run: pip install -e ".[dev]"
16
+ - run: aofire-call-graph src/python_agent/
@@ -0,0 +1,17 @@
1
+ name: Tests (570)
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.11"
15
+ - run: pip install -e ".[dev]"
16
+ - run: pytest --cov --cov-branch --cov-report=term-missing
17
+ - run: pytest tests/test_fuzz.py
@@ -0,0 +1,16 @@
1
+ name: Type Check
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+ jobs:
8
+ typecheck:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.11"
15
+ - run: pip install -e ".[dev]"
16
+ - run: mypy --strict src/
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ .eggs/
8
+ *.egg
9
+ .coverage
10
+ htmlcov/
11
+ .mutmut-cache
12
+ .pytest_cache/
13
+ .dag-key
14
+ .hypothesis/
15
+ *.bak
@@ -0,0 +1,105 @@
1
+ # Python Agent — Project Instructions
2
+
3
+ ## Python Standards
4
+
5
+ All Python code must meet these standards before commit:
6
+
7
+ 1. **flake8 clean** — zero warnings, default rules
8
+ 2. **McCabe Cyclomatic Complexity <= 5** — `flake8 --max-complexity=5`
9
+ 3. **100% branch coverage** — `pytest --cov --cov-branch --cov-report=term-missing`
10
+ 4. **pytest** for all tests, **pytest-mock** for mocking
11
+ 5. **pyflakes clean** (included in flake8)
12
+ 6. **Mutation testing with mutmut** — 100% kill rate required
13
+ - Use mutmut v2 (`pip install 'mutmut<3'`). v3's test mapping doesn't work with non-standard layouts.
14
+ - Configure in `pyproject.toml`: `paths_to_mutate`, `runner` (must use `.venv/bin/python`).
15
+ - The only acceptable survivors are the `if __name__` guard. Everything else must be killed — no exceptions for "cosmetic" code like help strings or log messages.
16
+ - Surviving mutants = test gaps. Write targeted tests to kill them.
17
+ - **mutmut wraps mutated strings in `XX...XX`.** To kill string mutants, assert `"XX" not in output` rather than only checking for substrings (which still match inside the wrapped version).
18
+ 7. **Fuzz testing with hypothesis** — all functions that accept external inputs
19
+ - External inputs: user CLI args, SDK messages/results, keyboard input, filesystem paths.
20
+ - Every such function must have a `@given(...)` test verifying:
21
+ a. **No unhandled exceptions** — any valid-typed input must not crash.
22
+ b. **Return type contract** — return type matches the function's contract.
23
+ c. **Invariants** — domain-specific rules (e.g., `remaining_budget <= max_budget`).
24
+ - Hypothesis profiles in `tests/conftest.py`: `ci` = 200 examples, `dev` = 50.
25
+ - Fuzz tests go in `tests/test_fuzz.py`, separate from example-based tests.
26
+ - Use `io.StringIO` for stdout capture in fuzz tests (hypothesis doesn't support pytest's `capsys` fixture).
27
+ - Run: `.venv/bin/pytest tests/test_fuzz.py` or with profile: `--hypothesis-profile=ci`.
28
+ 8. **mypy --strict** — zero errors
29
+ - Run: `.venv/bin/mypy --strict src/`
30
+ - All function signatures must have type annotations (parameters and return types).
31
+ - Use `Annotated` types from `python_agent.types` for constrained strings.
32
+ - Use `Literal` types for enum-like fields (not plain `str`).
33
+ - Use Pydantic `BaseModel` for data structures (not dataclasses).
34
+ - Add `# type: ignore[<code>]` with specific error codes only for third-party libraries without stubs.
35
+ 9. **Call graph taint analysis** — no unguarded source-to-sink paths
36
+ - Run: `.venv/bin/aofire-call-graph src/`
37
+ - Traces data flow from external inputs (CLI args, keyboard, file reads, JSON parsing, SDK responses) through the call graph to dangerous sinks (eval, subprocess, file writes, prompt injection).
38
+ - Each finding tagged with a CWE code. Use `--sarif` for CI integration.
39
+ - Fix findings by adding sanitizers: `frame_data()` for prompts, Pydantic validation for data, `tool_guard` for commands.
40
+ 10. **Functional test gap analysis** — final step after all other checks pass
41
+ - Read every source function and every test. For each function, enumerate all code paths and identify which are not exercised by any test.
42
+ - Focus on: integration between components, error propagation, boundary conditions, multi-step flows, and real usage edge cases.
43
+ - Write tests to close the gaps found. Iterate until no meaningful gaps remain.
44
+ - This step catches what coverage and mutation testing miss: tests that exist but don't verify the right thing, interactions between functions, and untested error paths.
45
+
46
+ ### Venv
47
+
48
+ Always use the project venv. Execute Python through `.venv/bin/python3`,
49
+ `.venv/bin/pytest`, `.venv/bin/flake8`, etc. Never use the system Python.
50
+
51
+ ### Before Committing
52
+
53
+ ```bash
54
+ .venv/bin/flake8 --max-complexity=5
55
+ .venv/bin/mypy --strict src/
56
+ .venv/bin/pytest --cov --cov-branch --cov-report=term-missing
57
+ ```
58
+
59
+ The only acceptable uncovered line is the `if __name__` guard (`sys.exit`).
60
+
61
+ ## Correctness
62
+
63
+ These are foundational. They apply to all code in all languages.
64
+
65
+ - **No one writes correct code — not humans, not AI.** Confidence without evidence is the most dangerous state. The cost of catching a bug grows exponentially the later it's found. Verify now, not later.
66
+ - **A programmer's critical job is proving their code is correct.** Trust nothing without verification.
67
+ - **Failure handling code that is never tested is a liability.** It can generate new errors when it finally runs. When writing functions with failure paths, discuss whether those paths are reachable under test. If not, discuss the cost of making them testable (e.g., dependency injection so tests can supply fakes).
68
+ - **Prefer parameters over hardcoded values.** Enables dependency injection and testability.
69
+ - **An accidental fix is not a fix — it's a clue.** Ask WHY a change affects behavior before shipping it.
70
+ - **Trace symptoms to code paths, not external theories.** When debugging, grep for what produces the output, trace the loop, ask "what are we not exiting and why?" Step UP in abstraction, don't drill down into speculation.
71
+
72
+ ## Testing Philosophy
73
+
74
+ These are non-negotiable. They come from hard experience across multiple projects.
75
+
76
+ - **Tests are part of the implementation, not a follow-up.** Code without tests is not done.
77
+ - **Both sides of every conditional.** Not "the important ones" — ALL of them.
78
+ - **Every test MUST have a meaningful assertion.** Never write a test that calls a function and unconditionally passes. Never write `assert len(x) > 0` when you can assert on the actual value.
79
+ - **Test from multiple angles.** Unit test + functional test on the same path catches different bugs.
80
+ - **Reproduce runtime bugs in tests first.** Write a test that triggers the failure (red), fix the code (green), commit both together.
81
+ - **If unsure what to assert, discuss it first.** "What should this test verify?" is always the right question.
82
+ - **The branch coverage analysis itself finds bugs.** Enumerating every conditional and verifying both sides are exercised catches things tests alone miss.
83
+ - **Mutation testing is the proof.** If a mutant survives, the test is broken.
84
+
85
+ ## Production vs Prototype
86
+
87
+ Two modes, hard boundary between them:
88
+
89
+ - **Production code:** Full standards, thoroughly tested, no shortcuts.
90
+ - **Prototype code:** Only when the path forward is unclear. Define the questions it answers upfront. When answered, reimplement from scratch to production standards. Never evolve a prototype into production code.
91
+
92
+ ## Working Style
93
+
94
+ - Trunk-based development: commit directly to `main`, push after each group of changes.
95
+ - Don't suggest breaks or stopping.
96
+ - When you catch a mistake or unintended change — stop. Understand what changed and why before moving on. Don't rationalize differences away.
97
+ - Never check files into the wrong repo by drifting directories. Stay in this project dir; use absolute paths for anything outside it.
98
+ - Always check if a target file exists before `mv`/`cp`/`Write`. Lost uncommitted work is gone forever.
99
+ - Never hide unexpected messages or errors — fix the source, not the reporter.
100
+ - Revert failed experiments immediately. Only keep changes you have high confidence are correct.
101
+
102
+ ## Git
103
+
104
+ - Commit after every group of code changes. Don't wait to be asked.
105
+ - Use the git user.name and user.email configured on the system.
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Ed Hodapp
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,405 @@
1
+ Metadata-Version: 2.4
2
+ Name: aofire-python-agent
3
+ Version: 0.1.0
4
+ Summary: Claude-powered Python coding and planning agents with enforced quality standards
5
+ Author-email: Ed Hodapp <ed@hodapp.com>
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/edhodapp/python-agent
8
+ Project-URL: Repository, https://github.com/edhodapp/python-agent
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: claude-agent-sdk
13
+ Requires-Dist: pydantic>=2.12
14
+ Provides-Extra: dev
15
+ Requires-Dist: flake8-pyproject; extra == "dev"
16
+ Requires-Dist: hypothesis; extra == "dev"
17
+ Requires-Dist: mutmut<3; extra == "dev"
18
+ Requires-Dist: mypy; extra == "dev"
19
+ Requires-Dist: pydantic>=2.12; extra == "dev"
20
+ Requires-Dist: pytest; extra == "dev"
21
+ Requires-Dist: pytest-asyncio; extra == "dev"
22
+ Requires-Dist: pytest-cov; extra == "dev"
23
+ Requires-Dist: pytest-mock; extra == "dev"
24
+ Dynamic: license-file
25
+
26
+ # aofire-python-agent
27
+
28
+ [![Lint](https://github.com/edhodapp/python-agent/actions/workflows/lint.yml/badge.svg)](https://github.com/edhodapp/python-agent/actions/workflows/lint.yml)
29
+ [![Type Check](https://github.com/edhodapp/python-agent/actions/workflows/typecheck.yml/badge.svg)](https://github.com/edhodapp/python-agent/actions/workflows/typecheck.yml)
30
+ [![Tests (570)](https://github.com/edhodapp/python-agent/actions/workflows/test.yml/badge.svg)](https://github.com/edhodapp/python-agent/actions/workflows/test.yml)
31
+ [![Taint Analysis](https://github.com/edhodapp/python-agent/actions/workflows/taint.yml/badge.svg)](https://github.com/edhodapp/python-agent/actions/workflows/taint.yml)
32
+ [![Fuzz](https://github.com/edhodapp/python-agent/actions/workflows/fuzz.yml/badge.svg)](https://github.com/edhodapp/python-agent/actions/workflows/fuzz.yml)
33
+ [![Mutation](https://github.com/edhodapp/python-agent/actions/workflows/mutation.yml/badge.svg)](https://github.com/edhodapp/python-agent/actions/workflows/mutation.yml)
34
+
35
+ Claude-powered Python agents with ontology-driven project planning,
36
+ autonomous code generation, and defense-in-depth security hardening.
37
+
38
+ The pipeline takes a project from idea to production code through
39
+ structured ontology exploration, branching solution candidates, and
40
+ an autonomous coding agent that enforces 10 quality gates before
41
+ every commit.
42
+
43
+ **BSD 3-Clause.** Python 3.11+. Requires the
44
+ [Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk-python).
45
+
46
+ ## What This Is
47
+
48
+ A monorepo containing six CLI tools and a shared ontology framework:
49
+
50
+ | Tool | Mode | Purpose |
51
+ |------|------|---------|
52
+ | `aofire-discovery-agent` | Interactive | Build a domain ontology through conversation |
53
+ | `aofire-divergence-agent` | Autonomous | Generate N candidate solution architectures |
54
+ | `aofire-convergence-agent` | Interactive | Compare, select, and refine candidates |
55
+ | `aofire-coding-agent` | Autonomous | Write production-quality code with Sonnet/Opus escalation |
56
+ | `aofire-planning-agent` | Interactive | Freeform project design (no ontology) |
57
+ | `aofire-call-graph` | Analysis | Source-to-sink taint analysis with CWE tagging |
58
+
59
+ Plus shared infrastructure:
60
+
61
+ | Module | Purpose |
62
+ |--------|---------|
63
+ | `ontology.py` | 16 Pydantic models: entities, relationships, modules, DAG |
64
+ | `types.py` | `Annotated` + `Literal` shared type definitions |
65
+ | `dag_utils.py` | DAG persistence with HMAC integrity signing |
66
+ | `dag_integrity.py` | HMAC verification + injection pattern scanning |
67
+ | `tool_guard.py` | `can_use_tool` callback: Bash blocklist + path confinement |
68
+ | `rules.py` | System prompts with `frame_data()` content framing |
69
+
70
+ ## Install
71
+
72
+ ```bash
73
+ pip install aofire-python-agent
74
+ ```
75
+
76
+ For development (includes test/analysis tools):
77
+
78
+ ```bash
79
+ git clone https://github.com/edhodapp/python-agent.git
80
+ cd python-agent
81
+ python3 -m venv .venv
82
+ .venv/bin/pip install -e ".[dev]"
83
+ ```
84
+
85
+ ## The Ontology Pipeline
86
+
87
+ ```
88
+ aofire-discovery-agent --> aofire-divergence-agent --> aofire-convergence-agent --> aofire-coding-agent
89
+ (interactive) (autonomous) (interactive) (autonomous)
90
+ Build domain Generate N Compare, select, Write code to
91
+ ontology solution candidates accept, refine production standards
92
+ ```
93
+
94
+ All state is saved to an **ontology DAG** (a JSON file). Each node is a
95
+ complete ontology snapshot. Each edge records a design decision. You can
96
+ backtrack to any prior state and explore a different path.
97
+
98
+ ### Step 1: Discovery
99
+
100
+ Build a domain ontology interactively. The agent asks questions about
101
+ your domain and constructs entities, relationships, and constraints.
102
+
103
+ ```bash
104
+ aofire-discovery-agent "A URL shortener service" --dag-file shortener.json
105
+ ```
106
+
107
+ Example session:
108
+
109
+ ```
110
+ Planner: I'll help you design a URL shortener. Who are the users?
111
+
112
+ > Anyone can follow a link. Registered users create short URLs.
113
+
114
+ [Agent proposes entities: User, ShortURL, relationship: User owns ShortURL]
115
+
116
+ > show
117
+ Entities (2):
118
+ user: User [username, api_key]
119
+ short_url: ShortURL [slug, target_url, click_count]
120
+ Relationships (1):
121
+ user --owns--> short_url (one_to_many)
122
+ Open Questions (2):
123
+ [open] q1: Storage backend?
124
+ [open] q2: Slug format?
125
+
126
+ > save initial domain model
127
+ Saved snapshot: 20260401T120000...
128
+
129
+ > quit
130
+ ```
131
+
132
+ Commands: `show`, `save [label]`, `back`, `quit`/`exit`/`done`
133
+
134
+ Options:
135
+ - `--dag-file PATH` -- DAG JSON file (default: `ontology.json`)
136
+ - `-m MODEL` -- model (default: `claude-opus-4-6`)
137
+
138
+ ### Step 2: Divergence
139
+
140
+ Autonomously generate multiple solution candidates. The agent identifies
141
+ key architectural decision points, then generates one complete solution
142
+ per strategy.
143
+
144
+ ```bash
145
+ aofire-divergence-agent --dag-file shortener.json -n 3
146
+ ```
147
+
148
+ ```
149
+ Identifying 3 strategies...
150
+ Generating candidate: monolith-sqlite...
151
+ Created: monolith-sqlite
152
+ Generating candidate: microservices-postgres...
153
+ Created: microservices-postgres
154
+ Generating candidate: serverless-dynamo...
155
+ Created: serverless-dynamo
156
+
157
+ Done. 3 candidates. Cost: $0.1234
158
+ ```
159
+
160
+ Each candidate fills in the solution domain: modules, classes, functions,
161
+ data models, external dependencies, and test strategies. The DAG now has
162
+ three branching children.
163
+
164
+ Options:
165
+ - `--dag-file PATH` -- DAG JSON file (required)
166
+ - `-n N` -- number of candidates (default: 3)
167
+ - `-m MODEL` -- model (default: `claude-sonnet-4-6`)
168
+ - `--max-budget USD` -- spending cap (default: 5.0)
169
+
170
+ ### Step 3: Convergence
171
+
172
+ Compare candidates, select one, and refine it interactively. The LLM
173
+ has context of all candidates and assists with comparisons.
174
+
175
+ ```bash
176
+ aofire-convergence-agent --dag-file shortener.json
177
+ ```
178
+
179
+ ```
180
+ > list
181
+ 1. monolith-sqlite: Entities (2), Modules (4)...
182
+ 2. microservices-postgres: Entities (2), Modules (6)...
183
+ 3. serverless-dynamo: Entities (2), Modules (5)...
184
+
185
+ > compare monolith-sqlite and microservices-postgres on complexity
186
+ [LLM explains trade-offs between the two approaches]
187
+
188
+ > select 1
189
+ Selected: monolith-sqlite
190
+
191
+ > show
192
+ [Full ontology: entities, relationships, modules with classes/functions]
193
+
194
+ > accept
195
+ Accepted: monolith-sqlite. You can now refine.
196
+
197
+ > Add rate limiting to the API module
198
+ [LLM proposes ontology update with new RateLimiter class]
199
+
200
+ > save final design
201
+ > quit
202
+ ```
203
+
204
+ Commands: `list`, `select <n>`, `back`, `show`, `accept`, `save [label]`.
205
+ Any other text goes to the LLM (e.g., "compare", "explain", "refine").
206
+
207
+ Options:
208
+ - `--dag-file PATH` -- DAG JSON file (required)
209
+ - `-m MODEL` -- model (default: `claude-opus-4-6`)
210
+
211
+ ### Step 4: Coding
212
+
213
+ The coding agent writes code, runs all quality checks, and iterates until
214
+ everything passes. Starts with Sonnet for cost efficiency; automatically
215
+ escalates to Opus if it gets stuck.
216
+
217
+ ```bash
218
+ aofire-coding-agent "Implement the URL shortener from the accepted design" -d ./shortener --dag-file shortener.json
219
+ ```
220
+
221
+ Pass `--dag-file` to give the coding agent the ontology as structured design
222
+ context. The agent sees entities, module specs, function signatures, and test
223
+ strategies from the accepted design.
224
+
225
+ The agent's workflow (11 steps):
226
+ 1. Read existing code
227
+ 2. Write/modify code
228
+ 3. flake8 (complexity <= 5)
229
+ 4. mypy --strict
230
+ 5. pytest (100% branch coverage)
231
+ 6. Iterate on failures
232
+ 7. mutmut (100% kill rate)
233
+ 8. Fuzz tests for external-input functions
234
+ 9. aofire-call-graph taint analysis
235
+ 10. Functional test gap analysis
236
+ 11. Commit
237
+
238
+ If the agent can't fix an issue (e.g., needs a `# type: ignore`), it
239
+ presents grouped findings for user approval rather than silently
240
+ suppressing.
241
+
242
+ Options:
243
+ - `-d DIR` -- project directory (default: `.`)
244
+ - `-m MODEL` -- initial model (default: `claude-sonnet-4-6`)
245
+ - `--max-turns N` -- step limit (default: 30)
246
+ - `--max-budget USD` -- spending cap (default: 5.0)
247
+ - `--dag-file PATH` -- ontology DAG JSON file for design context (optional)
248
+
249
+ ### Backtracking
250
+
251
+ Re-run convergence on the same DAG to navigate back and try a different
252
+ branch. All intermediate states are preserved:
253
+
254
+ ```bash
255
+ aofire-convergence-agent --dag-file shortener.json
256
+ > back
257
+ > select 2
258
+ > accept
259
+ ```
260
+
261
+ ## Standalone Planning Agent
262
+
263
+ For freeform project design without the ontology pipeline:
264
+
265
+ ```bash
266
+ aofire-planning-agent "A CLI tool that converts CSV to JSON with schema validation"
267
+ ```
268
+
269
+ Uses Opus by default. Produces a structured markdown plan. Type `quit` to end.
270
+
271
+ ## Static Analysis: aofire-call-graph
272
+
273
+ Source-to-sink taint analysis using Python's `ast` module. Traces data
274
+ flow from external inputs through the call graph to dangerous sinks.
275
+ Each finding tagged with a CWE code.
276
+
277
+ ```bash
278
+ aofire-call-graph src/python_agent/ # text report
279
+ aofire-call-graph src/python_agent/ --sarif # SARIF JSON for CI
280
+ aofire-call-graph src/python_agent/ --include-sanitized # show all paths
281
+ ```
282
+
283
+ Sources detected: `input()`, `json.loads`, `open()`, `.model_validate()`,
284
+ `.parse_args()`, `.query()` (SDK responses).
285
+
286
+ Sinks detected: `eval`/`exec`, `subprocess`/`os.system`, `.write()`,
287
+ `.query()` (prompt injection), `print()` (info exposure).
288
+
289
+ Suppress acknowledged findings with mandatory comments:
290
+ ```python
291
+ # taint: ignore[CWE-200] -- Interactive agent displays LLM output to user
292
+ async def run(description: str, model: str) -> None:
293
+ ```
294
+
295
+ ## Security Hardening
296
+
297
+ Defense-in-depth across all agents:
298
+
299
+ | Layer | Defense | Protects Against |
300
+ |-------|---------|-----------------|
301
+ | 1 | `frame_data()` content framing | Prompt injection via embedded data |
302
+ | 2 | HMAC-SHA256 DAG integrity | File tampering between sessions |
303
+ | 3 | Pydantic `BaseModel` validation | Malformed data at construction |
304
+ | 4 | `can_use_tool` callback (tool guard) | Dangerous Bash commands + path escape |
305
+ | 5 | Injection pattern scanner | Common injection phrases in text fields |
306
+ | 6 | Framing escape detection | `</ontology-data>` breakout attempts |
307
+ | 7 | Call graph taint analysis | Unguarded source-to-sink data flows |
308
+ | 8 | Taint suppressions with mandatory comments | Acknowledged risks with audit trail |
309
+ | 9 | User approval workflow | Silent suppression by autonomous agent |
310
+
311
+ The coding agent's tool guard blocks: `curl`, `wget`, `ssh`, `sudo`,
312
+ `rm -rf /`, `dd`, `mkfs`, `chmod 777`, `chown`, `pkill`, writes to
313
+ `/etc`, `~/.ssh`, `~/.bashrc`. File operations confined to project
314
+ directory.
315
+
316
+ ## The Ontology Format
317
+
318
+ 16 Pydantic models capturing both problem and solution domains:
319
+
320
+ **Problem domain:** Entity, Property, PropertyType, Relationship,
321
+ DomainConstraint
322
+
323
+ **Solution domain:** ModuleSpec, ClassSpec, FunctionSpec, DataModel,
324
+ ExternalDependency
325
+
326
+ **Planning state:** OpenQuestion (unresolved decisions)
327
+
328
+ **DAG:** DAGNode (ontology snapshots), DAGEdge (design decisions),
329
+ OntologyDAG (the full versioned graph)
330
+
331
+ Type constraints enforced via `Annotated` types: `SafeId` (alphanumeric,
332
+ max 100 chars), `ShortName` (max 100 chars), `Description` (max 2000
333
+ chars). Enum fields use `Literal` types: `PropertyKind`, `Cardinality`,
334
+ `ModuleStatus`, `Priority`.
335
+
336
+ ## Quality Standards
337
+
338
+ All code produced by these agents (and the agents themselves) meets:
339
+
340
+ 1. **flake8 clean** with `--max-complexity=5`
341
+ 2. **mypy --strict** with zero errors
342
+ 3. **100% branch coverage** via pytest (570 tests)
343
+ 4. **100% mutant kill rate** via mutmut v2
344
+ 5. **Fuzz testing** via hypothesis on all external-input functions
345
+ 6. **Call graph taint analysis** with CWE tagging
346
+ 7. **Functional test gap analysis** as final verification step
347
+ 8. **Prompt injection hardening** across all agents
348
+
349
+ See `CLAUDE.md` for the complete coding standards.
350
+
351
+ ## Project Status
352
+
353
+ **Version:** 0.1.0
354
+
355
+ **What works:**
356
+ - Full ontology pipeline: discovery, divergence, convergence
357
+ - Autonomous coding agent with Sonnet/Opus escalation
358
+ - All security hardening layers active
359
+ - 570 tests, 14 source files, all quality gates pass
360
+ - aofire-call-graph reports clean (no unguarded taint paths)
361
+
362
+ **What's next:**
363
+ - Wire coding agent to consume ontology nodes as implementation specs
364
+ - End-to-end pipeline test (idea to running code)
365
+ - CI setup (GitHub Actions)
366
+ - Performance requirements as soft ontology constraints (advisory, not blocking)
367
+ - Tier 2 hardening: coding agent command audit log by default
368
+
369
+ ## Development
370
+
371
+ ```bash
372
+ python3 -m venv .venv
373
+ .venv/bin/pip install -e ".[dev]"
374
+
375
+ # Full quality gate
376
+ .venv/bin/flake8 --max-complexity=5 src/ tests/
377
+ .venv/bin/mypy --strict src/
378
+ .venv/bin/pytest --cov --cov-branch --cov-report=term-missing
379
+ .venv/bin/mutmut run
380
+ .venv/bin/pytest tests/test_fuzz.py --hypothesis-profile=ci
381
+ .venv/bin/aofire-call-graph src/python_agent/
382
+ ```
383
+
384
+ ## Local PyPI with devpi
385
+
386
+ ```bash
387
+ # Setup (first time)
388
+ pip install devpi-server devpi-client
389
+ devpi-server --init && devpi-server --start --port 3141
390
+ devpi use http://localhost:3141
391
+ devpi user -c myuser password=
392
+ devpi login myuser
393
+ devpi index -c dev bases=root/pypi
394
+ devpi use myuser/dev
395
+
396
+ # Publish
397
+ devpi upload
398
+
399
+ # Install from local index
400
+ pip install aofire-python-agent -i http://localhost:3141/myuser/dev/+simple/
401
+ ```
402
+
403
+ ## License
404
+
405
+ BSD 3-Clause. See [LICENSE](LICENSE).