jovaltus 0.5.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 (60) hide show
  1. jovaltus-0.5.1/.github/workflows/release.yml +67 -0
  2. jovaltus-0.5.1/.gitignore +18 -0
  3. jovaltus-0.5.1/.pre-commit-config.yaml +41 -0
  4. jovaltus-0.5.1/AGENTS.md +86 -0
  5. jovaltus-0.5.1/CHANGELOG.md +70 -0
  6. jovaltus-0.5.1/CLAUDE.md +41 -0
  7. jovaltus-0.5.1/LICENSE +21 -0
  8. jovaltus-0.5.1/PKG-INFO +7 -0
  9. jovaltus-0.5.1/README.md +295 -0
  10. jovaltus-0.5.1/docs/README.md +49 -0
  11. jovaltus-0.5.1/docs/architecture/git-workflow.md +74 -0
  12. jovaltus-0.5.1/docs/architecture/plugin-architecture.md +64 -0
  13. jovaltus-0.5.1/docs/architecture/subagent-dispatch.md +68 -0
  14. jovaltus-0.5.1/docs/features/agent-mode-pipeline.md +50 -0
  15. jovaltus-0.5.1/docs/features/plugin-setup.md +39 -0
  16. jovaltus-0.5.1/docs/principles/error-handling.md +51 -0
  17. jovaltus-0.5.1/docs/principles/naming-conventions.md +64 -0
  18. jovaltus-0.5.1/docs/principles/testing-conventions.md +79 -0
  19. jovaltus-0.5.1/pyproject.toml +47 -0
  20. jovaltus-0.5.1/src/jovaltus/SOUL.md +55 -0
  21. jovaltus-0.5.1/src/jovaltus/__init__.py +64 -0
  22. jovaltus-0.5.1/src/jovaltus/hooks.py +182 -0
  23. jovaltus-0.5.1/src/jovaltus/plugin.yaml +8 -0
  24. jovaltus-0.5.1/src/jovaltus/prompts/implement.md +39 -0
  25. jovaltus-0.5.1/src/jovaltus/prompts/simplify.md +49 -0
  26. jovaltus-0.5.1/src/jovaltus/prompts/verify.md +284 -0
  27. jovaltus-0.5.1/src/jovaltus/schemas.py +162 -0
  28. jovaltus-0.5.1/src/jovaltus/skills/agentic-debugging/SKILL.md +268 -0
  29. jovaltus-0.5.1/src/jovaltus/skills/jovaltus-agent/SKILL.md +118 -0
  30. jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/SKILL.md +146 -0
  31. jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/references/audit-checklist.md +170 -0
  32. jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/references/community-practices.md +75 -0
  33. jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/references/template.md +119 -0
  34. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/SKILL.md +192 -0
  35. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/audit-checklist.md +205 -0
  36. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/document-types.md +217 -0
  37. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/tech-stack-detection.md +215 -0
  38. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/writing-style-guide.md +161 -0
  39. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/api-reference.md.tmpl +70 -0
  40. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/architecture.md.tmpl +99 -0
  41. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/conventions.md.tmpl +99 -0
  42. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/hub-readme.md.tmpl +47 -0
  43. jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/module.md.tmpl +55 -0
  44. jovaltus-0.5.1/src/jovaltus/state.py +168 -0
  45. jovaltus-0.5.1/src/jovaltus/tools.py +493 -0
  46. jovaltus-0.5.1/tests/__init__.py +0 -0
  47. jovaltus-0.5.1/tests/conftest.py +45 -0
  48. jovaltus-0.5.1/tests/evals/__init__.py +1 -0
  49. jovaltus-0.5.1/tests/evals/conftest.py +64 -0
  50. jovaltus-0.5.1/tests/evals/rubrics.py +519 -0
  51. jovaltus-0.5.1/tests/evals/tasks.py +208 -0
  52. jovaltus-0.5.1/tests/evals/test_jovaltus_skills.py +102 -0
  53. jovaltus-0.5.1/tests/integration/conftest.py +20 -0
  54. jovaltus-0.5.1/tests/integration/test_cli.py +113 -0
  55. jovaltus-0.5.1/tests/test_git_utils.py +170 -0
  56. jovaltus-0.5.1/tests/test_schemas.py +45 -0
  57. jovaltus-0.5.1/tests/test_state.py +180 -0
  58. jovaltus-0.5.1/tests/test_sync.py +132 -0
  59. jovaltus-0.5.1/tests/test_tools.py +381 -0
  60. jovaltus-0.5.1/uv.lock +410 -0
@@ -0,0 +1,67 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v[0-9]+.[0-9]+.[0-9]+'
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ build-and-publish:
14
+ name: Build, check, and publish to PyPI
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.11'
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v5
27
+
28
+ - name: Install dependencies
29
+ run: uv sync --dev
30
+
31
+ - name: Lint (ruff)
32
+ run: uv run ruff check .
33
+
34
+ - name: Run tests
35
+ run: uv run pytest --ignore=tests/integration/
36
+
37
+ - name: Type check (mypy)
38
+ run: uv run mypy src/jovaltus
39
+
40
+ - name: Extract version from tag
41
+ id: version
42
+ run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
43
+
44
+ - name: Verify pyproject version matches tag
45
+ run: |
46
+ PYPROJECT_VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
47
+ TAG_VERSION="${{ steps.version.outputs.version }}"
48
+ if [ "$PYPROJECT_VERSION" != "$TAG_VERSION" ]; then
49
+ echo "❌ pyproject.toml version ($PYPROJECT_VERSION) != tag version ($TAG_VERSION)"
50
+ exit 1
51
+ fi
52
+ echo "✅ Version $PYPROJECT_VERSION matches tag v$TAG_VERSION"
53
+
54
+ - name: Build package
55
+ run: uv build
56
+
57
+ - name: Publish to PyPI
58
+ uses: pypa/gh-action-pypi-publish@release/v1
59
+
60
+ - name: Create GitHub Release
61
+ uses: softprops/action-gh-release@v2
62
+ with:
63
+ name: "v${{ steps.version.outputs.version }}"
64
+ files: dist/*
65
+ draft: false
66
+ prerelease: false
67
+ generate_release_notes: true
@@ -0,0 +1,18 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+
6
+ # Virtual environment
7
+ .venv/
8
+ .uv/
9
+
10
+ # OS
11
+ .DS_Store
12
+
13
+ # IDE
14
+ .vscode/
15
+ .idea/
16
+
17
+ # Eval results
18
+ eval_results/
@@ -0,0 +1,41 @@
1
+ # Pre-commit hooks for Jovaltus
2
+ # Order: ruff lint → mypy strict → ruff format
3
+ #
4
+ # ruff check — lint verification (must pass)
5
+ # mypy --strict — type checking (must pass)
6
+ # ruff format — auto-format (runs after all checks pass)
7
+ #
8
+ # Install: pre-commit install
9
+ # Run all: pre-commit run --all-files
10
+
11
+ repos:
12
+ - repo: https://github.com/astral-sh/ruff-pre-commit
13
+ rev: v0.15.21
14
+ hooks:
15
+ # ── Stage 1: Lint check (must pass) ──────────────────────────
16
+ - id: ruff
17
+ name: ruff check (lint)
18
+ args: [--fix]
19
+ types_or: [python, pyi]
20
+ description: "ruff check — lint validation (commit blocked on failure)"
21
+
22
+ - repo: https://github.com/pre-commit/mirrors-mypy
23
+ rev: v1.16.1
24
+ hooks:
25
+ # ── Stage 2: Type check (must pass) ──────────────────────────
26
+ - id: mypy
27
+ name: mypy strict check
28
+ args: [--strict, --no-site-packages]
29
+ exclude: ^tests/
30
+ types_or: [python, pyi]
31
+ additional_dependencies: []
32
+ description: "mypy --strict — type checking (commit blocked on failure)"
33
+
34
+ - repo: https://github.com/astral-sh/ruff-pre-commit
35
+ rev: v0.15.21
36
+ hooks:
37
+ # ── Stage 3: Auto-format (runs after all checks pass) ────────
38
+ - id: ruff-format
39
+ name: ruff format (auto-format)
40
+ types_or: [python, pyi]
41
+ description: "ruff format — auto-format staged files"
@@ -0,0 +1,86 @@
1
+ # Jovaltus — Hermes Plugin Agent Mode
2
+
3
+ ## Build & Test
4
+
5
+ - `uv run pytest -v` — Run full test suite (68 tests, ~3.6s)
6
+ - `uv run ruff check .` — Lint (zero warnings)
7
+ - `uv run ruff format --check .` — Format check (auto-format with `ruff format .`)
8
+ - `uv run mypy --strict --no-site-packages *.py` — Type check (zero errors)
9
+ - All tests pass before commit. No lint, format, or type warnings.
10
+
11
+ ## Pre-commit Hooks (v0.5.0)
12
+
13
+ Three hooks run on every `git commit` in this order:
14
+
15
+ 1. **ruff check — lint** (must pass, blocks commit on failure)
16
+ 2. **mypy --strict — type check** (must pass, blocks commit on failure)
17
+ 3. **ruff format — auto-format** (reformats staged files after checks pass)
18
+
19
+ Install: `pre-commit install` (already done)
20
+ Run manually: `pre-commit run --all-files`
21
+
22
+ ## Project Structure
23
+
24
+ - `plugin.yaml` + `__init__.py` — Hermes plugin entry (root dir IS the package)
25
+ - `tools.py` — Three tool handler factories (implement, verify, simplify)
26
+ - Dual-mode: task_id for stateful pipeline, before/after for stateless commit mode
27
+ - `schemas.py` — Tool JSON schemas (what the LLM sees)
28
+ - verify/simplify schemas include optional before/after params
29
+ - `state.py` — Thread-safe in-memory task state
30
+ - `git_utils.py` — Git subprocess wrappers (list args, no shell=True)
31
+ - New in v0.2.0: remote update utilities (fetch, pull, ahead/behind check)
32
+ - `SOUL.md` — Bundled agent identity file; applied to profile via `setup`
33
+ - `prompts/*.md` — Subagent system prompts (editable without touching Python)
34
+ - `skills/jovaltus-agent/SKILL.md` — Agent Mode workflow definition
35
+ - `tests/` — 68 pytest tests across 7 test files + conftest.py
36
+
37
+ ## Key Constraints
38
+
39
+ - All handler functions must accept `(args: dict, **kwargs)` and return JSON string
40
+ - All git commands use list args (no `shell=True`)
41
+ - State uses `threading.Lock` for thread safety
42
+ - Handler factories capture `ctx` in `register()` — closures, not class instances
43
+ - Prompt files loaded at factory creation time, not at handler invocation
44
+ - Plugin skills are namespaced (`jovaltus:jovaltus-agent`), loaded via `skill_view()`
45
+
46
+ ## Documentation
47
+
48
+ - `docs/features/` — User-visible behaviour in BDD format (Given/When/Then)
49
+ - `docs/architecture/` — Module boundaries and design principles
50
+ - `docs/principles/` — Code conventions with source evidence
51
+ - Every doc claim traces to source file + line range. `[INFERRED]` marks unverifiable claims.
52
+
53
+ ## CLI Commands (v0.3.0)
54
+
55
+ - `hermes jovaltus setup` — Create profile, install bundled skills, apply SOUL.md
56
+ - Interactive prompts with TTY detection (falls back to safe defaults)
57
+ - Creates `jovaltus-agent` profile if missing
58
+ - Installs bundled skills to global skills directory
59
+ - Optionally writes `SOUL.md` to profile directory
60
+ - Persists installation state to `~/.hermes/jovaltus_state.json`
61
+ - `hermes jovaltus status` — Show installation state per profile
62
+ - Displays profile name, installation mode, and last updated timestamp
63
+ - `hermes jovaltus update --check` — Check for remote updates against origin
64
+ - `hermes jovaltus update` — Pull latest changes
65
+ - Detects and removes stale bundled skills (interactive)
66
+ - Refreshes all bundled skills
67
+ - Re-applies SOUL.md where previously installed
68
+ - Refreshes timestamps
69
+
70
+ ## Workflow
71
+
72
+ ### Stateful Pipeline (task_id mode)
73
+
74
+ 1. User confirms requirements (Phase 0)
75
+ 2. Main agent calls `jovaltus_implement` → handler spawns implement subagent
76
+ 3. Main agent calls `jovaltus_verify(task_id)` → handler spawns verification subagent
77
+ 4. Main agent calls `jovaltus_simplify(task_id)` → handler spawns simplifier subagent
78
+
79
+ ### Stateless Commit Mode
80
+
81
+ For verify and simplify tools, pass `before` (and optionally `after`) commit hashes
82
+ instead of `task_id` to skip pipeline state and operate on any commit range:
83
+ - `jovaltus_verify(before=<hash>)` → verifies before..HEAD
84
+ - `jovaltus_verify(before=<hash>, after=<hash>)` → verifies exact range
85
+ - `jovaltus_simplify(before=<hash>)` → simplifies before..HEAD
86
+ - `task_id` and `before` are mutually exclusive
@@ -0,0 +1,70 @@
1
+ # Changelog
2
+
3
+ All notable changes to the **Jovaltus** Hermes plugin are documented here.
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
+
8
+ ---
9
+
10
+ ## v0.3.2 — 2026-07-11
11
+
12
+ ### Changed
13
+
14
+ - **Architecture**: plugin CLI commands registered from the default profile (like caelterra) instead of requiring a dedicated profile — `hermes jovaltus setup/status/update` work from any terminal after `hermes plugins install`
15
+ - **`setup` flow simplified**: removed `_link_plugin_to_profile()` — plugin stays in default profile, no profile-plugin linking needed
16
+
17
+ ---
18
+
19
+ ## v0.3.1 — 2026-07-11
20
+
21
+ ### Added
22
+
23
+ - **Auto-link plugin to profile on `setup`** (`_link_plugin_to_profile()`) — detects the installed plugin in either global `~/.hermes/plugins/` or profile plugins dir and ensures it's accessible from `jovaltus-agent` profile
24
+ - **Better error message on `setup`** — suggests installing from outside the repo if plugin isn't found
25
+
26
+ ---
27
+
28
+ ## v0.3.0 — 2026-07-11
29
+
30
+ ### Added
31
+
32
+ - **State management** (`~/.hermes/jovaltus_state.json`) — JSON file tracking installation mode (Skills only vs Skills + SOUL.md) and last updated timestamp per profile
33
+ - **CLI: `status`** — shows Jovaltus installation status for the jovaltus-agent profile
34
+ - **Interactive prompts** (`_prompt_yes_no()`) with TTY detection — falls back to defaults in non-interactive environments
35
+ - **Profile sync on `update`** — after pulling latest code, refreshes SOUL.md and timestamps for tracked profiles, even when already up to date (handles state drift)
36
+ - **Stale skill detection** — compares `~/.hermes/skills/` against bundled skills after update, interactively removes orphaned skills
37
+ - **TypedDict return types** in `git_utils.py` — `FetchResult`, `AheadBehind`, `PullResult`, `CommitResult`
38
+ - **`_is_skill_dir()` helper** — factorised directory check pattern
39
+ - **`_get_bundled_skill_names()`** — scan bundled skills
40
+ - **`_remove_installed_skill()` / `_remove_stale_skills()`** — stale skill cleanup workflow
41
+
42
+ ### Changed
43
+
44
+ - `setup` now uses interactive prompts for skill and SOUL.md installation (defaults: skills=yes, SOUL.md=yes, overwrite=no)
45
+ - `setup` persists installation state to `~/.hermes/jovaltus_state.json`
46
+ - `update` now re-applies SOUL.md for tracked profiles, removes stale skills, and refreshes all bundled skills
47
+ - `update` refreshes skills and SOUL.md even when already up to date (fixes state drift)
48
+ - `_install_bundled_skill()` renamed to `_install_bundled_skills()` — handles multiple bundled skills
49
+ - `git_utils.py` return types migrated to TypedDict for better type safety
50
+
51
+ ### Added (tests)
52
+
53
+ - 8 new tests covering state management (load/save/set), profile sync (SOUL.md, skills-only, missing profiles), and stale skill detection
54
+
55
+ ---
56
+
57
+ ## v0.2.0 — 2026-07-09
58
+
59
+ ### Added
60
+
61
+ - Profile + SOUL.md setup via `hermes jovaltus setup`
62
+ - Update checking via `hermes jovaltus update --check`/`hermes jovaltus update`
63
+ - Git utilities for remote operations (fetch, pull, ahead/behind check)
64
+ - Bundled skill registration
65
+
66
+ ---
67
+
68
+ ## v0.1.0 — 2026-07-09
69
+
70
+ Initial release. Jovaltus Agent Mode — automated development pipeline (Plan → Implement → Verify → Simplify) as a Hermes plugin.
@@ -0,0 +1,41 @@
1
+ # Jovaltus — Hermes Plugin Agent Mode
2
+
3
+ ## Build & Test
4
+
5
+ - `uv run pytest -v` — Run full test suite (25 tests, ~1.2s)
6
+ - `uv run python3 -m py_compile *.py tests/*.py` — Type/syntax check
7
+ - All tests pass before commit. No lint warnings.
8
+
9
+ ## Project Structure
10
+
11
+ - `plugin.yaml` + `__init__.py` — Hermes plugin entry (root dir IS the package)
12
+ - `tools.py` — Three tool handler factories (implement, verify, simplify)
13
+ - `schemas.py` — Tool JSON schemas (what the LLM sees)
14
+ - `state.py` — Thread-safe in-memory task state
15
+ - `git_utils.py` — Git subprocess wrappers (list args, no shell=True)
16
+ - `prompts/*.md` — Subagent system prompts (editable without touching Python)
17
+ - `skills/jovaltus-agent/SKILL.md` — Agent Mode workflow definition
18
+ - `tests/` — 25 pytest tests across 4 test files + conftest.py
19
+
20
+ ## Key Constraints
21
+
22
+ - All handler functions must accept `(args: dict, **kwargs)` and return JSON string
23
+ - All git commands use list args (no `shell=True`)
24
+ - State uses `threading.Lock` for thread safety
25
+ - Handler factories capture `ctx` in `register()` — closures, not class instances
26
+ - Prompt files loaded at factory creation time, not at handler invocation
27
+ - Plugin skills are namespaced (`jovaltus:jovaltus-agent`), loaded via `skill_view()`
28
+
29
+ ## Documentation
30
+
31
+ - `docs/features/` — User-visible behaviour in BDD format (Given/When/Then)
32
+ - `docs/architecture/` — Module boundaries and design principles
33
+ - `docs/principles/` — Code conventions with source evidence
34
+ - Every doc claim traces to source file + line range. `[INFERRED]` marks unverifiable claims.
35
+
36
+ ## Workflow
37
+
38
+ 1. User confirms requirements (Phase 0)
39
+ 2. Main agent calls `jovaltus_implement` → handler spawns implement subagent
40
+ 3. Main agent calls `jovaltus_verify(task_id)` → handler spawns verification subagent
41
+ 4. Main agent calls `jovaltus_simplify(task_id)` → handler spawns simplifier subagent
jovaltus-0.5.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lai Tsz Kin (Sunny Lai)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: jovaltus
3
+ Version: 0.5.1
4
+ Summary: Jovaltus Agent Mode — Hermes plugin for automated development pipeline
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: fabricium>=0.1.1
@@ -0,0 +1,295 @@
1
+ # Jovaltus — Hermes Plugin for Agent Mode
2
+
3
+ > **Jovaltus** is a Hermes Agent plugin that transforms the main agent into an intelligent development orchestrator. Designed for quick bug fixes and small-to-medium features, it provides a structured four-phase pipeline — Plan → Implement → Verify & Fix → Simplify — while keeping the workflow invisible to the user.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Jovaltus takes a single user request and runs it through an automated quality pipeline. The user only participates in Phase 0 (requirement clarification). Everything else — implementation, adversarial verification, code simplification — is handled autonomously by subagents.
10
+
11
+ ```
12
+ User Request
13
+
14
+ ├── Phase 0: Planning (Main Agent)
15
+ │ Round-based clarification → Checklist → User confirmation
16
+
17
+ ├── Phase 1: Implement (Subagent)
18
+ │ Writes code. Reports BLOCKED if stuck.
19
+
20
+ ├── Phase 2: Verify & Fix (Subagent)
21
+ │ Adversarial testing. Finds problems, fixes them, repeats until clean.
22
+
23
+ └── Phase 3: Simplify (Subagent)
24
+ Structural cleanup. No behaviour changes.
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Architecture
30
+
31
+ ### Three-Layer Design
32
+
33
+ | Layer | What It Does | Why |
34
+ |-------|-------------|-----|
35
+ | **Skill** (documents) | Describes what each phase should do. No tool names. | LLM reads this + tool schemas, figures out the flow itself. |
36
+ | **Tool Handler** (thin Python) | Records state, reads system prompt from file, spawns subagent via `ctx.dispatch_tool("delegate_task", ...)`. Returns immediately. | One tool call per phase. No manual `delegate_task` from the main agent. Prompt lives in its own file. |
37
+ | **Subagent prompt** (markdown) | The system prompt injected into each subagent. Lives in `prompts/*.md`. | Editable without touching Python. Each subagent reads its own prompt. |
38
+
39
+ ### One Tool Call Per Phase
40
+
41
+ The main agent calls ONE tool per phase. That tool handler:
42
+
43
+ 1. Records state (git hash, task_id)
44
+ 2. Reads the system prompt from `prompts/<phase>.md`
45
+ 3. Spawns a subagent via `ctx.dispatch_tool("delegate_task", ...)` with the prompt as goal
46
+ 4. Returns immediately — the subagent runs in the background
47
+
48
+ The subagent self-commits when done. Its result arrives as a message
49
+ the main agent reads to decide the next phase.
50
+
51
+ ---
52
+
53
+ ## The Four Phases
54
+
55
+ ### Phase 0: Planning (Main Agent)
56
+
57
+ The only phase the user interacts with.
58
+
59
+ ```
60
+ User: "Build a login page"
61
+
62
+ ├── Step 1: Round-based clarification (1-3 questions per round, multiple choice)
63
+ │ Scope → Business flow → Constraints → Business value
64
+
65
+ ├── Step 2: Decompose into a business requirement checklist
66
+
67
+ ├── Step 3: Web search for latest information (avoids knowledge cut-off)
68
+
69
+ └── Step 4: User confirms the plan
70
+ "Don't start implementing until the user says yes."
71
+ ```
72
+
73
+ ### Phase 1: Implement
74
+
75
+ ```
76
+ Main agent calls jovaltus_implement
77
+ └─ Handler:
78
+ 1. Records start_hash, creates task
79
+ 2. Reads prompts/implement.md
80
+ 3. ctx.dispatch_tool("delegate_task", {
81
+ goal: implement prompt,
82
+ toolsets: [terminal, file]
83
+ })
84
+ 4. Returns {task_id, start_hash}
85
+
86
+ Subagent works in background:
87
+ • Reads context from handler
88
+ • Writes code (full read/write access)
89
+ • Does NOT verify, does NOT simplify
90
+ • Reports BLOCKED if genuinely stuck
91
+ • git add -A && git commit when done
92
+ ```
93
+
94
+ **Tool permissions**: `terminal`, `file` (full read/write).
95
+ **Red lines**: ❌ No touching irrelevant files. ❌ No self-verification. ❌ No self-simplification.
96
+
97
+ ### Phase 2: Verify & Fix
98
+
99
+ ```
100
+ Main agent calls jovaltus_verify(task_id)
101
+ └─ Handler:
102
+ 1. Looks up task, computes diff (start_hash → HEAD)
103
+ 2. Reads prompts/verify.md
104
+ 3. ctx.dispatch_tool("delegate_task", {
105
+ goal: verify prompt,
106
+ context: diff output,
107
+ toolsets: [terminal, file]
108
+ })
109
+ 4. Returns {task_id, diff_summary}
110
+
111
+ Subagent works in background (with write access):
112
+ • Runs the code
113
+ • Tries to break it (adversarial mindset)
114
+ • Finds bugs → fixes them directly → re-verifies
115
+ • Loops until all tests pass
116
+ • git add -A && git commit when done
117
+ ```
118
+
119
+ **Mindset**: Adversarial. Not "does it work?" but "how can I break this?"
120
+ **Write access**: The subagent can fix what it finds — no read-only reporting. This is the Fable 5 closed-loop model.
121
+
122
+ ### Phase 3: Simplify
123
+
124
+ ```
125
+ Main agent calls jovaltus_simplify(task_id)
126
+ └─ Handler:
127
+ 1. Looks up task, computes clean diff
128
+ 2. Reads prompts/simplify.md
129
+ 3. ctx.dispatch_tool("delegate_task", {
130
+ goal: simplify prompt,
131
+ context: clean diff,
132
+ toolsets: [terminal, file]
133
+ })
134
+ 4. Returns {task_id, diff_summary}
135
+
136
+ Subagent works in background:
137
+ • No behaviour changes
138
+ • Structural priorities: extract duplicates > delete dead code > flatten nesting > improve naming
139
+ • Mandatory grep evidence before deleting anything
140
+ • git add -A && git commit when done
141
+ ```
142
+
143
+ **Value hierarchy**: Extract duplicates → Delete dead code → Flatten nesting → Improve naming.
144
+ **Safety**: Every deletion requires grep evidence. Behaviour must be strictly preserved.
145
+
146
+ ---
147
+
148
+ ## Installation and Usage
149
+
150
+ ### Step 1: Install the Plugin
151
+
152
+ ```bash
153
+ pip install jovaltus && hermes plugins enable jovaltus
154
+ ```
155
+
156
+ > `fabricium` 會作為依賴自動安裝。
157
+
158
+ ### Step 2: Setup
159
+
160
+ ```bash
161
+ # 一鍵安裝 — 互動式 prompts (TTY detection, 非互動環境用預設值)
162
+ hermes jovaltus setup
163
+ ```
164
+
165
+ Setup 會:
166
+
167
+ 1. 建立 `jovaltus-agent` profile(如不存在)
168
+ 2. 安裝 bundled skills 到 global skills 目錄
169
+ 3. 寫入 SOUL.md(可選,預設 yes)
170
+ 4. 記錄安裝狀態至 `~/.hermes/jovaltus_state.json`
171
+
172
+ ### Step 3: 啟用 Plugin
173
+
174
+ ```bash
175
+ hermes plugins enable jovaltus
176
+ ```
177
+
178
+ ### Step 4: 建立 Profile
179
+
180
+ ```bash
181
+ # 一鍵建立 jovaltus-agent profile
182
+ hermes jovaltus setup
183
+ ```
184
+
185
+ > Profile 建立後,編輯 `~/.hermes/profiles/jovaltus-agent/config.yaml`,
186
+ > 確認 model 設定與 root config 一致(若無則複製貼上):
187
+ > ```yaml
188
+ > model:
189
+ > default: deepseek-v4-flash
190
+ > provider: deepseek
191
+ > ```
192
+ > 若不確定 root 設定,執行:`grep -A2 "^model:" ~/.hermes/config.yaml`
193
+
194
+ ### Step 4: 連結 Plugin 到 Profile
195
+
196
+ ```bash
197
+ # 將 plugin 原始碼連結到 profile 的 plugins 目錄
198
+ ln -s /Users/tszkinlai/uniterra/jovaltus ~/.hermes/profiles/jovaltus-agent/plugins/jovaltus
199
+ ```
200
+
201
+ > **為什麼需要這步?** 當使用 `hermes -p <profile>` 啟動 session 時,
202
+ > Hermes 只掃描 profile 目錄底下的 plugins,不會掃描全域 `~/.hermes/plugins/`。
203
+ > 因此 plugin 必須存在於 profile 的 plugins 子目錄中才會被載入。
204
+
205
+ ### Step 5: 確認安裝
206
+
207
+ ```bash
208
+ # 啟動 session 並測試工具是否可用
209
+ hermes -p jovaltus-agent
210
+
211
+ # 在 session 中輸入:
212
+ # 「list all tools whose name starts with jovaltus」
213
+ #
214
+ # 應該看到:
215
+ # - jovaltus_implement
216
+ # - jovaltus_verify
217
+ # - jovaltus_simplify
218
+ ```
219
+
220
+ ### 日常使用
221
+
222
+ ```bash
223
+ # 查詢安裝狀態
224
+ hermes jovaltus status
225
+
226
+ # 檢查更新
227
+ hermes jovaltus update --check
228
+
229
+ # 套用更新(自動清理過時 skill、同步 SOUL.md)
230
+ hermes jovaltus update
231
+
232
+ # 在任何專案目錄下啟動
233
+ cd /projects/app-alpha
234
+ hermes -p jovaltus-agent
235
+
236
+ # Profile 不綁定目錄 — 同一 profile 可在不同 project 使用
237
+ cd /projects/app-beta
238
+ hermes -p jovaltus-agent
239
+ ```
240
+
241
+ ### 疑難排解
242
+
243
+ | 問題 | 解法 |
244
+ |------|------|
245
+ | `Unknown toolset 'jovaltus'` | Plugin 未正確載入。檢查 Step 4 的 symlink 是否存在 |
246
+ | 工具列表沒有 `jovaltus_*` | 確認 profile config 有 `plugins.enabled: [jovaltus]` |
247
+ | `No inference provider configured` | Profile config 缺少 model 設定。參考 Step 3 補上 |
248
+ | 401 Authentication Error | 確認 profile 的 `.env` 有 API key。複製 root 的:`grep DEEPSEEK ~/.hermes/.env >> ~/.hermes/profiles/jovaltus-agent/.env` |
249
+
250
+ ---
251
+
252
+ ## Project Structure
253
+
254
+ ```
255
+ jovaltus/
256
+ ├── README.md # Proposal + usage
257
+ ├── plugin.yaml # Hermes plugin manifest
258
+ ├── __init__.py # register() — creates handler closures, mounts everything
259
+ ├── schemas.py # Tool JSON schemas (what the LLM sees)
260
+ ├── tools.py # Tool handler factories (capture ctx, spawn subagents)
261
+ ├── state.py # In-memory task state
262
+ ├── git_utils.py # Git subprocess wrappers
263
+ ├── skills/
264
+ │ └── jovaltus-agent/
265
+ │ └── SKILL.md # Agent Mode workflow (no tool names)
266
+ └── prompts/
267
+ ├── implement.md # Implement subagent system prompt
268
+ ├── verify.md # Verification subagent system prompt
269
+ └── simplify.md # Simplifier subagent system prompt
270
+ ```
271
+
272
+ ---
273
+
274
+ ## Technical Decisions
275
+
276
+ | Aspect | Decision |
277
+ |--------|----------|
278
+ | **Profile** | `jovaltus-agent`, separate from any other mode |
279
+ | **Plugin sharing** | GitHub repo + `hermes plugins install` |
280
+ | **Profile init** | Plugin provides `hermes jovaltus setup` CLI command (`ctx.register_cli_command`) |
281
+ | **Profile binding** | Not directory-bound — same profile works across projects |
282
+ | **Pipeline control** | Skill document guides main agent. Each phase = one tool call. |
283
+ | **Git tracking** | Tool handler records start_hash. Subagent self-commits when done. |
284
+ | **Subagent spawning** | Tool handler calls `ctx.dispatch_tool("delegate_task", ...)` with prompt from file |
285
+ | **System prompts** | Stored in `prompts/*.md`, read by handler at call time |
286
+ | **Verify loop** | Verification subagent has write access and runs a self-contained loop |
287
+ | **Simplify input** | Handler computes clean diff (start vs HEAD, no intermediate commits) |
288
+ | **Skill style** | Describes *what* to do, never names tools other than the three plugin tools |
289
+ | **Plugin skills** | Read-only, namespaced (`"jovaltus:jovaltus-agent"`), loaded via `skill_view()` |
290
+
291
+ ---
292
+
293
+ ## License
294
+
295
+ MIT