Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d03db6e
feat(zoo-code): add portable asset lifecycle
tbitcs Jul 15, 2026
efdce80
fix(zoo-code): complete portable asset lifecycle
tbitcs Jul 15, 2026
b17d0a5
feat(zoo-code): register lifecycle commands
tbitcs Jul 15, 2026
2a84e40
test(zoo-code): cover portable asset lifecycle
tbitcs Jul 15, 2026
5e8f378
chore(release): bump version to 0.22.4
tbitcs Jul 15, 2026
21dad1c
chore(release): update fallback version
tbitcs Jul 15, 2026
fec5e2b
docs(zoo-code): document portable integration lifecycle
tbitcs Jul 15, 2026
266da83
fix(release): preserve project metadata in version bump
tbitcs Jul 15, 2026
6b804ff
test(zoo-code): verify CLI command registration
tbitcs Jul 15, 2026
6a083b3
docs(zoo-code): adopt packaged setup workflow
tbitcs Jul 15, 2026
6cebcbd
style(zoo-code): apply formatter-clean lifecycle implementation
tbitcs Jul 15, 2026
8272073
style(zoo-code): publish ruff-formatted lifecycle module
tbitcs Jul 15, 2026
56b02c3
docs(release): add 0.22.4 changelog
tbitcs Jul 15, 2026
bcb29c8
style(zoo-code): format tests with project width
tbitcs Jul 15, 2026
f1beb7c
style(zoo-code): format module with project width
tbitcs Jul 15, 2026
687dea7
chore(lint): scope Callable compatibility exception
tbitcs Jul 15, 2026
0eb6f54
ci: repair v0.22.4 release metadata
tbitcs Jul 15, 2026
27ee03a
fix(release): align project schema version
tbitcs Jul 15, 2026
c1cf024
fix(release): align embedded schema version
tbitcs Jul 15, 2026
e339b24
fix(config): expose schema without wildcard imports
tbitcs Jul 15, 2026
56071cd
fix(config): re-export _TYPE_LABELS from _config_schema for cli.py im…
tbitcs Jul 15, 2026
eff9e69
fix(ci): resolve ruff I001 import sorting and legacy TEST_SPEC.md ref…
tbitcs Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/SPECSMITH.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description: |
through governance, traceability, and automated compliance checking.

type: python
version: 0.22.3
version: 0.22.4
license: MIT
author: Layer1 Labs
url: https://github.com/layer1labs/specsmith
Expand Down
26 changes: 26 additions & 0 deletions docs/releases/0.22.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Specsmith 0.22.4 — 2026-07-15

## Added

- Universal Zoo Code lifecycle commands: `specsmith zoo-code setup`, `doctor`, and `uninstall`.
- Managed global Specsmith rules, slash commands, and skills under the Zoo Code global directory.
- Safe backup and adoption of unmanaged files at reserved Specsmith paths.
- Managed manifests, stale-asset removal, and migration from the earlier v1 marker.
- Project MCP merging that preserves unrelated servers.
- Recognition and removal of generic Specsmith rule duplicates from project `.roo` directories while preserving customized files.
- `--scope`, `--global-roo`, `ROO_GLOBAL_DIR`, `--dry-run`, and `--preserve-existing` controls.
- Cross-platform lifecycle tests and CLI registration coverage.

## Changed

- Specsmith is now the canonical distribution point for reusable Zoo Code integration assets.
- Project repositories retain ownership of project-specific rules, commands, skills, custom modes, and provider/model configuration.
- Package revision advanced from 0.22.3 to 0.22.4.

## Safety

- Uninstall removes only marker-owned global assets.
- Customized workspace files are preserved.
- The `specsmith-governance` MCP entry is removed only when it still matches the managed value.

Closes issue #307.
30 changes: 30 additions & 0 deletions docs/site/zoo-code-assets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Portable Zoo Code integration

Specsmith is the canonical distribution point for reusable Zoo Code rules, slash commands, skills, and MCP configuration. Project repositories retain only project-specific `.roo` assets and model/provider settings.

## Install or update

```bash
pipx upgrade specsmith
cd /path/to/project
specsmith zoo-code setup --project-dir .
specsmith zoo-code doctor --project-dir .
```

By default, setup installs reusable Specsmith assets under `~/.roo`, merges the `specsmith-governance` MCP server into `.roo/mcp.json`, and removes recognized generic Specsmith rule duplicates from the workspace.

Use `ROO_GLOBAL_DIR` or `--global-roo` to override the global Zoo Code directory. Use `--scope global` or `--scope project` to operate on one side only. `--dry-run` previews changes. `--preserve-existing` refuses to adopt an unmanaged file at a reserved Specsmith path.

## Safety

Existing unmanaged files at reserved global paths are backed up before adoption. Customized workspace files are preserved and reported. Setup removes stale assets only when they carry a Specsmith managed marker. Uninstall removes only managed assets and removes the MCP entry only when it still matches the Specsmith-managed value.

## Remove

```bash
specsmith zoo-code uninstall --project-dir .
```

## Repository ownership boundary

Specsmith owns reusable global rules, commands, skills, lifecycle manifests, migration, doctor, uninstall, and the standard MCP merge. Individual repositories own project-specific rules, commands, skills, custom modes, provider configuration, and local model routing.
58 changes: 33 additions & 25 deletions docs/site/zoo-code-roo.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
# Zoo Code / Roo Code Integration

Specsmith integrates with Zoo Code / Roo Code through a repo-local `.roo/` directory and the Specsmith MCP governance server.
Specsmith integrates with Zoo Code / Roo Code through reusable global assets, a repo-local `.roo/` directory, and the Specsmith MCP governance server.

## What belongs in the repository
## Setup

Project-local integration files:
Install or upgrade Specsmith with pipx, then configure the active project:

| File | Purpose |
|---|---|
| `.roo/mcp.json` | Registers the `specsmith-governance` MCP server for this repo. |
| `.roo/specsmith-rules.md` | Mandatory rules for governed Zoo/Roo sessions. |
| `.roo/modes.local.json` | Reference mode-to-model mapping for this project. |
| `.roo/global-settings.copy-to-zoo-code.json` | Copyable global provider/model settings for Zoo Code. |
```bash
pipx upgrade specsmith
cd /path/to/project
specsmith zoo-code setup --project-dir .
specsmith zoo-code doctor --project-dir .
```

The setup command installs reusable Specsmith rules, slash commands, and skills under `~/.roo`. It also merges the `specsmith-governance` MCP server into the project `.roo/mcp.json` without removing unrelated servers.

Use `--global-roo PATH` or `ROO_GLOBAL_DIR` to override the global directory. `--scope global` and `--scope project` limit the operation. `--dry-run` previews changes, and `--preserve-existing` refuses to replace unmanaged files at reserved Specsmith paths.

Zoo Code global settings are not automatically loaded from a repository. Keep copyable global settings in the project as a reference, then copy them into Zoo Code global/user settings manually.
## Ownership boundary

Specsmith owns reusable global governance assets and their setup, migration, doctor, and uninstall lifecycle. Repositories should contain only project-specific rules, commands, skills, custom modes, and provider/model settings.

Existing generic Specsmith rules duplicated inside a project are removed only when they match a recognized legacy asset or carry a Specsmith managed marker. Customized project files are preserved and reported.

## MCP setup

The repo-local MCP config should look like this:
The generated repo-local MCP entry is:

```json
{
Expand Down Expand Up @@ -49,7 +57,7 @@ The MCP server exposes governance tools such as:
Every Zoo/Roo session should follow this sequence:

```text
read AGENTS.md + .roo/specsmith-rules.md
read AGENTS.md and applicable global/project rules
call governance_checkpoint
call governance_phase
call governance_req_list
Expand All @@ -60,7 +68,7 @@ run verification
seal meaningful decisions
```

Do not edit files unless `governance_preflight` returns `accepted`.
Do not edit files unless `governance_preflight` returns `accepted` or the request is classified as a permitted environment-only operation.

## Local model routing

Expand All @@ -82,18 +90,18 @@ Recommended role mapping:

The model that writes a patch must not be the only model that approves it.

## Operator setup checklist
## Operator checklist

1. Start the local model router if using local models.
2. Copy `.roo/global-settings.copy-to-zoo-code.json` into Zoo Code global settings, adapting field names to the current extension version.
3. Ensure Zoo/Roo sees `.roo/mcp.json` for the active workspace.
4. Start a session by asking the agent to read `.roo/specsmith-rules.md` and call `governance_checkpoint`.
5. Run governed tasks using the role split: Architect -> Code -> Debug/Tool -> Review.
1. Start the local model router when using local models.
2. Run `specsmith zoo-code setup --project-dir .`.
3. Run `specsmith zoo-code doctor --project-dir .`.
4. Reload the editor so Zoo Code discovers the final rules, commands, skills, and MCP configuration.
5. Start governed work with `/specsmith-intake` or the appropriate project-specific command.

## Safe defaults
## Remove managed integration state

```bash
specsmith zoo-code uninstall --project-dir .
```

- Architect mode plans and reads; it should not directly edit production code.
- Code mode implements accepted preflight tasks.
- Debug/Tool mode runs safe commands and parses logs.
- Review mode critiques diffs against requirements, tests, and prior decisions.
- Specsmith blocks or escalates work when confidence, phase, or scope checks fail.
Uninstall removes only marker-owned global assets and removes the MCP entry only when it still matches the Specsmith-managed value. Unmanaged and customized files are preserved.
76 changes: 14 additions & 62 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"

[project]
name = "specsmith"
version = "0.22.3"
description = "AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, and Aider."
version = "0.22.4"
description = "AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, Aider, and Zoo Code."
readme = "README.md"
license = "MIT"
requires-python = ">=3.10"
Expand All @@ -32,20 +32,16 @@ classifiers = [
"Topic :: Software Development :: Code Generators",
"Topic :: Software Development :: Build Tools",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Topic :: Scientific/Engineering :: Information Analysis",
"Topic :: Software Development :: Code Generators",
]

dependencies = [
"click>=8.1",
# `specsmith esdb enable` verifies Ed25519 license signatures in every install.
"cryptography>=42.0",
"jinja2>=3.1",
"pyyaml>=6.0",
"pydantic>=2.0",
"rich>=13.0",
# chronomemory is now an OPTIONAL commercial dep (specsmith[esdb]).
# The free SQLite backend is built-in and requires no extra install.
# To unlock ChronoStore: pip install specsmith[esdb] + specsmith esdb enable
]

[project.optional-dependencies]
Expand All @@ -57,36 +53,22 @@ dev = [
"pre-commit>=3.0",
"types-pyyaml>=6.0",
]
# ESDB commercial backend — requires a valid license from licensing@layer1labs.ai
# Install: pip install specsmith[esdb]
# Activate: specsmith esdb enable --key-file /path/to/your.esdb.key
# Terms: https://github.com/layer1labs/specsmith/blob/develop/COMMERCIAL-LICENSE.md
esdb = [
"chronomemory>=0.2.7", # proprietary commercial — ChronoMemory terms only (not SQLite free tier)
"chronomemory>=0.2.7",
]
docs = [
"mkdocs>=1.6",
"mkdocs-material>=9.5",
]
# LLM provider extras for specsmith run (agentic client)
anthropic = ["anthropic>=0.56"]
openai = ["openai>=1.0"]
# gemini: supports both the new google-genai SDK (GA May 2025, recommended)
# and the legacy google-generativeai SDK (deprecated Nov 2025, fallback).
# The provider auto-detects which is installed.
gemini = ["google-genai>=1.0"]
mistral = ["openai>=1.0"] # Mistral uses the openai SDK pointed at api.mistral.ai
mistral = ["openai>=1.0"]
gui = ["PySide6>=6.6"]
# AG2 agent shell (Planner/Builder/Verifier over Ollama)
ag2 = ["ag2[ollama]"]
# Optional semantic backend for `specsmith history search --semantic` (REQ-135).
# Falls back gracefully to keyword matching if these are not installed.
history-semantic = ["sentence-transformers>=2.2", "numpy>=1.24"]
# Optional whisper-cpp wrapper for the voice agent input (REQ-141).
voice = ["whisper-cpp-python>=0.2"]
# Install all optional LLM providers
agent = ["anthropic>=0.56", "openai>=1.0"]
# Convenience bundle: everything EXCEPT esdb (commercial license required separately)
all = [
"anthropic>=0.56",
"openai>=1.0",
Expand All @@ -95,7 +77,6 @@ all = [
"ruff>=0.4",
"mypy>=1.10",
]
# Compatibility extra: cryptography is now part of every supported installation.
license-verify = []

[project.scripts]
Expand Down Expand Up @@ -123,29 +104,19 @@ line-length = 100
select = ["E", "F", "W", "I", "UP", "B", "SIM"]

[tool.ruff.lint.per-file-ignores]
# Long rule text and install command strings in documentation modules
"src/specsmith/toolrules.py" = ["E501"]
"src/specsmith/tool_installer.py" = ["E501"]
# One-shot rebuild scripts contain literal REQ description strings that are
# intentionally long; wrapping them would damage readability of the source
# of truth they reconstruct.
"src/specsmith/commands/zoo_code_assets.py" = ["E501", "UP035"]
"scripts/rebuild_requirements_json.py" = ["E501"]
"scripts/rebuild_requirements_md.py" = ["E501"]
# Compliance package: regulation description strings and HTML templates are
# intentionally long; wrapping would damage readability.
"src/specsmith/compliance/_compat.py" = ["E501"]
"src/specsmith/compliance/regulations.py" = ["E501"]
"src/specsmith/compliance/reporter.py" = ["E501"]
"src/specsmith/compliance/evidence.py" = ["E501"]
# CI manager: error message strings are intentionally descriptive
"src/specsmith/ci_manager.py" = ["E501"]
# Context orchestrator: tier descriptions are intentionally descriptive
"src/specsmith/context_orchestrator.py" = ["E501"]
# Skills module: skill body strings contain markdown content with long lines
"src/specsmith/skills/*.py" = ["E501"]
# MCP server module: tool schema description strings are long but cannot be split
"src/specsmith/mcp_server.py" = ["E501"]
# Migration files: rule description strings and template content
"src/specsmith/migrations/m001_governance_yaml.py" = ["E501"]
"src/specsmith/migrations/m004_ledger_esdb.py" = ["E501"]

Expand All @@ -154,49 +125,38 @@ python_version = "3.10"
strict = true
warn_return_any = true
warn_unused_configs = true
# GUI package requires PySide6, an optional extra not available in the mypy
# environment. Exclude it from type-checking to avoid false positives.
exclude = ["src/specsmith/gui"]

# Optional extras — installed by the user, not in the dev environment.
# Ignore missing stubs rather than failing type-check for absent packages.
[[tool.mypy.overrides]]
module = [
"anthropic",
"anthropic.*",
"autogen", # AG2 agent shell — optional extra
"autogen",
"autogen.*",
"openai",
"openai.*",
"google",
"google.*",
"yaml",
"yaml.*",
"keyring", # optional OS credential store; stubs not published
"keyring",
"keyring.*",
"numpy", # optional [history-semantic] extra (REQ-135)
"numpy",
"numpy.*",
"sentence_transformers", # optional [history-semantic] extra (REQ-135)
"sentence_transformers",
"sentence_transformers.*",
"whisper_cpp_python", # optional [voice] extra (REQ-141)
"whisper_cpp_python.*",
"chronomemory", # git dep — no published stubs yet
"whisper_cpp_python",
"chronomemory",
"chronomemory.*",
"tomllib", # stdlib in 3.11+; not available when checking against python_version=3.10
"tomli", # optional 3.10 backport; not installed in the dev environment
"tomllib",
"tomli",
]
ignore_missing_imports = true

# epistemic library has pre-existing strict-mypy issues unrelated to specsmith changes
[[tool.mypy.overrides]]
module = ["epistemic", "epistemic.*"]
ignore_errors = true

# Modules that use dynamic typing patterns incompatible with strict mypy.
# These are correct at runtime; the Any-heavy urllib, json.loads, etc. patterns
# are the source of most errors here. Exclude from strict type checking.
# REQ-111: shrunk this list as part of the pre-1.0 cleanup; broker, safety,
# console_utils, and indexer have been graduated to strict mypy.
[[tool.mypy.overrides]]
module = [
"specsmith.ollama_cmds",
Expand All @@ -218,12 +178,9 @@ module = [
"specsmith.toolrules",
"specsmith.tool_installer",
"specsmith.commands.intelligence",
# glossa-lab AI pattern ports — urllib/json-heavy, Any patterns expected
"specsmith.agent.hf_leaderboard",
"specsmith.agent.llm_client",
# pre-existing openai SDK overload mismatch, not introduced by our changes
"specsmith.agent.chat_runner",
# New modules — dynamic/Any-heavy patterns; will be typed in 1.x cleanup
"specsmith.compliance.checker",
"specsmith.compliance.evidence",
"specsmith.compliance.reporter",
Expand All @@ -238,12 +195,7 @@ module = [
"specsmith.ci_manager",
"specsmith.context_orchestrator",
"specsmith.session_store",
# MCP server: lazy in-function imports and dynamic Any patterns
"specsmith.mcp_server",
# ESDB package: conditional chronomemory stubs in except ImportError branch
# produce type[_Stub] vs type[ChronoRecord] assignment errors that are
# correct at runtime but cannot be expressed statically without TYPE_CHECKING.
# specsmith.esdb.* covers bridge.py and _license.py sub-modules too.
"specsmith.esdb",
"specsmith.esdb.*",
]
Expand Down
2 changes: 1 addition & 1 deletion src/specsmith/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
try:
__version__: str = _pkg_version("specsmith")
except PackageNotFoundError: # running from source without install
__version__ = "0.22.3" # fallback: keep in sync with pyproject.toml
__version__ = "0.22.4" # fallback: keep in sync with pyproject.toml
Loading