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.
- jovaltus-0.5.1/.github/workflows/release.yml +67 -0
- jovaltus-0.5.1/.gitignore +18 -0
- jovaltus-0.5.1/.pre-commit-config.yaml +41 -0
- jovaltus-0.5.1/AGENTS.md +86 -0
- jovaltus-0.5.1/CHANGELOG.md +70 -0
- jovaltus-0.5.1/CLAUDE.md +41 -0
- jovaltus-0.5.1/LICENSE +21 -0
- jovaltus-0.5.1/PKG-INFO +7 -0
- jovaltus-0.5.1/README.md +295 -0
- jovaltus-0.5.1/docs/README.md +49 -0
- jovaltus-0.5.1/docs/architecture/git-workflow.md +74 -0
- jovaltus-0.5.1/docs/architecture/plugin-architecture.md +64 -0
- jovaltus-0.5.1/docs/architecture/subagent-dispatch.md +68 -0
- jovaltus-0.5.1/docs/features/agent-mode-pipeline.md +50 -0
- jovaltus-0.5.1/docs/features/plugin-setup.md +39 -0
- jovaltus-0.5.1/docs/principles/error-handling.md +51 -0
- jovaltus-0.5.1/docs/principles/naming-conventions.md +64 -0
- jovaltus-0.5.1/docs/principles/testing-conventions.md +79 -0
- jovaltus-0.5.1/pyproject.toml +47 -0
- jovaltus-0.5.1/src/jovaltus/SOUL.md +55 -0
- jovaltus-0.5.1/src/jovaltus/__init__.py +64 -0
- jovaltus-0.5.1/src/jovaltus/hooks.py +182 -0
- jovaltus-0.5.1/src/jovaltus/plugin.yaml +8 -0
- jovaltus-0.5.1/src/jovaltus/prompts/implement.md +39 -0
- jovaltus-0.5.1/src/jovaltus/prompts/simplify.md +49 -0
- jovaltus-0.5.1/src/jovaltus/prompts/verify.md +284 -0
- jovaltus-0.5.1/src/jovaltus/schemas.py +162 -0
- jovaltus-0.5.1/src/jovaltus/skills/agentic-debugging/SKILL.md +268 -0
- jovaltus-0.5.1/src/jovaltus/skills/jovaltus-agent/SKILL.md +118 -0
- jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/SKILL.md +146 -0
- jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/references/audit-checklist.md +170 -0
- jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/references/community-practices.md +75 -0
- jovaltus-0.5.1/src/jovaltus/skills/manage-agents-md/references/template.md +119 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/SKILL.md +192 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/audit-checklist.md +205 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/document-types.md +217 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/tech-stack-detection.md +215 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/references/writing-style-guide.md +161 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/api-reference.md.tmpl +70 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/architecture.md.tmpl +99 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/conventions.md.tmpl +99 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/hub-readme.md.tmpl +47 -0
- jovaltus-0.5.1/src/jovaltus/skills/project-documentation/templates/module.md.tmpl +55 -0
- jovaltus-0.5.1/src/jovaltus/state.py +168 -0
- jovaltus-0.5.1/src/jovaltus/tools.py +493 -0
- jovaltus-0.5.1/tests/__init__.py +0 -0
- jovaltus-0.5.1/tests/conftest.py +45 -0
- jovaltus-0.5.1/tests/evals/__init__.py +1 -0
- jovaltus-0.5.1/tests/evals/conftest.py +64 -0
- jovaltus-0.5.1/tests/evals/rubrics.py +519 -0
- jovaltus-0.5.1/tests/evals/tasks.py +208 -0
- jovaltus-0.5.1/tests/evals/test_jovaltus_skills.py +102 -0
- jovaltus-0.5.1/tests/integration/conftest.py +20 -0
- jovaltus-0.5.1/tests/integration/test_cli.py +113 -0
- jovaltus-0.5.1/tests/test_git_utils.py +170 -0
- jovaltus-0.5.1/tests/test_schemas.py +45 -0
- jovaltus-0.5.1/tests/test_state.py +180 -0
- jovaltus-0.5.1/tests/test_sync.py +132 -0
- jovaltus-0.5.1/tests/test_tools.py +381 -0
- 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,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"
|
jovaltus-0.5.1/AGENTS.md
ADDED
|
@@ -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.
|
jovaltus-0.5.1/CLAUDE.md
ADDED
|
@@ -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.
|
jovaltus-0.5.1/PKG-INFO
ADDED
jovaltus-0.5.1/README.md
ADDED
|
@@ -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
|