Skip to content

Commit 0754628

Browse files
tbitcsoz-agent
andcommitted
feat: docs + lifecycle tests + H14 documentation rule
- Fix Rich markup error in phase list (empty style tag) - Fix lifecycle test assertions (audit exit code 0 or 1) - Add 3 lifecycle test suites: new project, import, upgrade migration - Update vscode-extension.md: phase-driven prompts, governance file naming, RTD links - Update governance.md: SESSION-PROTOCOL.md + LIFECYCLE.md references - Add H14 documentation rule to AGENTS.md template (all new projects) - Strengthen H14 in specsmith's own AGENTS.md - 226 tests pass, ruff clean Co-Authored-By: Oz <oz-agent@warp.dev>
1 parent ba31f80 commit 0754628

8 files changed

Lines changed: 542 additions & 21 deletions

File tree

AGENTS.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,15 @@ AGENTS.md is < 200 lines. Run `specsmith upgrade --full` to generate them if nee
6262
- CI: GitHub Actions (3 OS × 3 Python)
6363
- Docs: Read the Docs (specsmith.readthedocs.io)
6464

65-
## Documentation Rule
65+
## Documentation Rule (H14 — Hard Rule)
6666

6767
The Read the Docs site (`docs/site/`) is the authoritative user manual.
68-
When ANY feature is added, changed, or removed:
69-
1. Update the relevant `docs/site/*.md` page(s) in the SAME commit
70-
2. Update `README.md` if it affects the project summary
71-
3. Update `CHANGELOG.md` under [Unreleased]
72-
4. README.md links to RTD for details — do NOT duplicate RTD content in README
68+
Before committing ANY change, verify documentation is current:
69+
1. Check if the change affects user-facing behavior, CLI commands, governance files, or configuration
70+
2. If yes: update the relevant `docs/site/*.md` page(s) in the SAME commit
71+
3. Update `README.md` if it affects the project summary
72+
4. Update `CHANGELOG.md` under [Unreleased]
73+
5. README.md links to RTD for details — do NOT duplicate RTD content in README
74+
6. The VS Code extension docs live in `docs/site/vscode-extension.md` — update when GovernancePanel, SettingsPanel, SessionPanel, or HelpPanel change
75+
76+
This is a hard rule. Undocumented features are governance violations. Never commit code without checking for documentation gaps.

docs/site/governance.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ Every specsmith-governed project has this authority hierarchy — higher files o
2626
4. **docs/ARCHITECTURE.md** — How the system is structured.
2727
5. **docs/TEST_SPEC.md** — How the system is verified.
2828
6. **LEDGER.md** — Sole authority for session state (what's been done, what's next).
29-
7. **docs/WORKFLOW.md** — How work proceeds (milestones, PR expectations).
3029

3130
## AGENTS.md — The Governance Hub
3231

docs/site/vscode-extension.md

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ VS Code's secondary sidebar.
1212
## Requirements
1313

1414
- VS Code 1.85+
15-
- specsmith **v0.3.5+** installed and on PATH
15+
- specsmith **v0.3.6+** installed and on PATH
1616
- At least one LLM provider (API key or local Ollama)
1717

1818
```bash
@@ -76,11 +76,34 @@ The 7 AEE phases:
7676

7777
From the CLI:
7878
```bash
79-
specsmith phase # show current phase + checklist
80-
specsmith phase next # advance (checks prerequisites)
81-
specsmith phase set implementation # jump to a phase
79+
specsmith phase show # show current phase + readiness checklist
80+
specsmith phase list # visual pipeline with current phase highlighted
81+
specsmith phase next # advance (checks prerequisites first)
82+
specsmith phase set implementation # jump to a phase (--force to skip checks)
8283
```
8384

85+
### Phase-Driven Prompts
86+
87+
The Actions tab adapts to the current phase. Each phase shows:
88+
89+
- **🤖 AI-Guided button** — starts a comprehensive interactive session for the phase (e.g. "Guide me through requirements gathering")
90+
- **Phase-specific prompts** — only prompts relevant to the current phase (e.g. architecture phase shows "Generate ARCHITECTURE.md" and "Define components")
91+
- **Always-available prompts** — audit, upgrade, and ledger update are always shown
92+
93+
This means the extension actively guides you through the AEE lifecycle rather than showing a static list of actions.
94+
95+
### Governance File Naming
96+
97+
specsmith v0.3.7+ uses clearer governance file names:
98+
99+
| Old Name | New Name | Purpose |
100+
|----------|----------|---------|
101+
| `WORKFLOW.md` | `SESSION-PROTOCOL.md` | How agent sessions work (proposals, ledger format) |
102+
| *(new)* | `LIFECYCLE.md` | Phase-aware project lifecycle roadmap |
103+
| `docs/WORKFLOW.md` | *(removed)* | Replaced by the phase system + LIFECYCLE.md |
104+
105+
Old projects are automatically migrated when you run `specsmith upgrade`.
106+
84107
---
85108

86109
## Settings Panel — 6 Tabs
@@ -102,6 +125,7 @@ Open with `Ctrl+Shift+G` or the `📖` toolbar icon.
102125

103126
### Tab: Files
104127
- Governance file status table: scaffold.yml, AGENTS.md, REQUIREMENTS.md, TEST_SPEC.md, ARCHITECTURE.md, LEDGER.md
128+
- Governance files use new naming: SESSION-PROTOCOL.md, LIFECYCLE.md (replaces old WORKFLOW.md)
105129
- ✓ / ✗ indicators with line counts
106130
- **Add** buttons for missing files — choose AI-generated or template
107131
- **Open** buttons for existing files
@@ -115,8 +139,10 @@ Open with `Ctrl+Shift+G` or the `📖` toolbar icon.
115139
- System info panel (lazy-loaded): OS, CPU, cores, RAM, GPU, disk
116140

117141
### Tab: Actions & AI
118-
- Quick actions grid: audit --fix, validate, doctor, epistemic-audit, stress-test, export, req list, req gaps
119-
- AI Prompt Palette: 10 pre-written prompts sent to the active agent session
142+
- Quick actions grid: audit --fix, validate, doctor, epistemic-audit, stress-test, export, req list, req gaps, lifecycle status
143+
- **🤖 AI-Guided Session** button — launches a comprehensive interactive session for the current AEE phase
144+
- **Phase Prompts** — prompts change dynamically based on the current lifecycle phase (inception, architecture, requirements, etc.)
145+
- **Always Available** prompts — audit, upgrade, ledger update (available in every phase)
120146

121147
### Tab: Execution
122148
- **Execution profile selector**`🔒 safe` (read-only), `⚙ standard` (default), `🔓 open`, `⚠ admin`
@@ -269,10 +295,17 @@ model dropdown and select from the **Installed** group, or `specsmith ollama lis
269295

270296
---
271297

298+
## Learn More
299+
300+
- **[AEE Primer (Full Guide)](aee-primer.md)** — Applied Epistemic Engineering from zero to productive
301+
- **[epistemic Library Reference](epistemic-library.md)** — standalone Python library for belief engineering
302+
- **[Governance Model](governance.md)** — the closed-loop workflow, file hierarchy, modular governance
303+
- **[CLI Commands](commands.md)** — every specsmith command with options and examples
304+
- **[Project Types](project-types.md)** — all 35+ project types with tools and governance rules
305+
- **[Importing Projects](importing.md)** — how detection works, merge behavior, type inference
306+
272307
## Links
273308

274309
- [GitHub: specsmith-vscode](https://github.com/BitConcepts/specsmith-vscode)
275310
- [GitHub: specsmith](https://github.com/BitConcepts/specsmith)
276-
- [specsmith CLI reference](commands.md)
277-
- [Agentic client overview](agent-client.md)
278-
- [AEE Workflow Phases](commands.md#specsmith-phase)
311+
- [specsmith Documentation (RTD)](https://specsmith.readthedocs.io)

src/specsmith/cli.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3467,11 +3467,10 @@ def phase_list(project_dir: str) -> None:
34673467
"\u2192 implementation \u2192 verification \u2192 release\n"
34683468
)
34693469
for i, p in enumerate(PHASES, 1):
3470-
marker = "[bold cyan]\u25b6[/bold cyan]" if p.key == current else " "
3471-
style = "bold cyan" if p.key == current else ""
3472-
console.print(
3473-
f" {marker} {i}. {p.emoji} [{style}]{p.label:<20s}[/{style}] {p.description}"
3474-
)
3470+
is_cur = p.key == current
3471+
marker = "[bold cyan]\u25b6[/bold cyan]" if is_cur else " "
3472+
label = f"[bold cyan]{p.label:<20s}[/bold cyan]" if is_cur else f"{p.label:<20s}"
3473+
console.print(f" {marker} {i}. {p.emoji} {label} {p.description}")
34753474
console.print(f"\n Current: [bold]{current}[/bold]")
34763475

34773476

src/specsmith/templates/agents.md.j2

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,18 @@ Focus work on artifacts appropriate for this phase. Run `specsmith phase show` t
166166

167167
---
168168

169+
## Documentation Rule (H14)
170+
171+
Before committing ANY change, verify documentation is current:
172+
1. Check if the change affects user-facing behavior, CLI commands, governance files, or configuration
173+
2. If yes: update the relevant documentation (README.md, docs/, CHANGELOG.md) in the SAME commit
174+
3. Never commit code changes without checking for documentation gaps
175+
4. When adding a feature: document it. When changing behavior: update the docs. When removing: note it.
176+
177+
This is a hard rule. Undocumented features are governance violations.
178+
179+
---
180+
169181
## Epistemic Governance (AEE)
170182

171183
This project follows Applied Epistemic Engineering (AEE) principles. Every proposal MUST:
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# SPDX-License-Identifier: MIT
2+
# Copyright (c) 2026 BitConcepts, LLC. All rights reserved.
3+
"""Sandbox lifecycle test: import existing project and walk lifecycle.
4+
5+
Creates a realistic project, imports it, then verifies governance files
6+
and phase tracking work correctly for imported projects.
7+
"""
8+
9+
from __future__ import annotations
10+
11+
from pathlib import Path
12+
from textwrap import dedent
13+
14+
import yaml
15+
from click.testing import CliRunner
16+
17+
from specsmith.cli import main
18+
19+
20+
def _create_test_project(root: Path) -> None:
21+
"""Build a minimal Python project with no governance."""
22+
(root / "pyproject.toml").write_text(
23+
dedent("""\
24+
[build-system]
25+
requires = ["setuptools>=68.0"]
26+
build-backend = "setuptools.build_meta"
27+
[project]
28+
name = "importme"
29+
version = "1.0.0"
30+
requires-python = ">=3.10"
31+
dependencies = ["click>=8.1"]
32+
[project.scripts]
33+
importme = "importme.cli:main"
34+
[tool.setuptools.packages.find]
35+
where = ["src"]
36+
"""),
37+
encoding="utf-8",
38+
)
39+
src = root / "src" / "importme"
40+
src.mkdir(parents=True)
41+
(src / "__init__.py").write_text('__version__ = "1.0.0"\n', encoding="utf-8")
42+
(src / "cli.py").write_text(
43+
dedent("""\
44+
import click
45+
46+
@click.command()
47+
def main():
48+
click.echo("hello")
49+
"""),
50+
encoding="utf-8",
51+
)
52+
tests = root / "tests"
53+
tests.mkdir()
54+
(tests / "test_cli.py").write_text(
55+
dedent("""\
56+
from importme.cli import main
57+
from click.testing import CliRunner
58+
59+
def test_main():
60+
r = CliRunner().invoke(main)
61+
assert r.exit_code == 0
62+
"""),
63+
encoding="utf-8",
64+
)
65+
(root / "README.md").write_text("# importme\nA test project.\n", encoding="utf-8")
66+
(root / ".gitignore").write_text("__pycache__/\n", encoding="utf-8")
67+
68+
69+
class TestLifecycleImport:
70+
"""Import an existing project and verify lifecycle setup."""
71+
72+
def test_import_sets_inception_phase(self, tmp_path: Path) -> None:
73+
root = tmp_path / "importme"
74+
root.mkdir()
75+
_create_test_project(root)
76+
77+
runner = CliRunner()
78+
r = runner.invoke(main, ["import", "--project-dir", str(root), "--yes"])
79+
assert r.exit_code == 0, f"Import failed: {r.output}"
80+
81+
# Phase should be inception
82+
assert (root / "scaffold.yml").exists()
83+
with open(root / "scaffold.yml") as f:
84+
cfg = yaml.safe_load(f)
85+
assert cfg.get("aee_phase") == "inception"
86+
87+
def test_import_creates_governance_files(self, tmp_path: Path) -> None:
88+
root = tmp_path / "importme"
89+
root.mkdir()
90+
_create_test_project(root)
91+
92+
runner = CliRunner()
93+
runner.invoke(main, ["import", "--project-dir", str(root), "--yes"])
94+
95+
# New governance files
96+
gov = root / "docs" / "governance"
97+
assert (gov / "SESSION-PROTOCOL.md").exists()
98+
assert (gov / "LIFECYCLE.md").exists()
99+
assert (gov / "RULES.md").exists()
100+
101+
# Old names should NOT exist
102+
assert not (gov / "WORKFLOW.md").exists()
103+
assert not (root / "docs" / "WORKFLOW.md").exists()
104+
105+
def test_import_then_phase_operations(self, tmp_path: Path) -> None:
106+
root = tmp_path / "importme"
107+
root.mkdir()
108+
_create_test_project(root)
109+
110+
runner = CliRunner()
111+
runner.invoke(main, ["import", "--project-dir", str(root), "--yes"])
112+
113+
# Phase show
114+
r = runner.invoke(main, ["phase", "show", "--project-dir", str(root)])
115+
assert r.exit_code == 0, f"phase show failed: {r.output}\n{r.exception}"
116+
assert "Inception" in r.output
117+
118+
# Phase list
119+
r = runner.invoke(main, ["phase", "list", "--project-dir", str(root)])
120+
assert r.exit_code == 0, f"phase list failed: {r.output}\n{r.exception}"
121+
assert "inception" in r.output
122+
123+
# Advance with --force
124+
r = runner.invoke(main, ["phase", "next", "--force", "--project-dir", str(root)])
125+
assert r.exit_code == 0
126+
assert "Architecture" in r.output
127+
128+
with open(root / "scaffold.yml") as f:
129+
cfg = yaml.safe_load(f)
130+
assert cfg["aee_phase"] == "architecture"
131+
132+
def test_import_audit_includes_phase_readiness(self, tmp_path: Path) -> None:
133+
root = tmp_path / "importme"
134+
root.mkdir()
135+
_create_test_project(root)
136+
137+
runner = CliRunner()
138+
runner.invoke(main, ["import", "--project-dir", str(root), "--yes"])
139+
140+
r = runner.invoke(main, ["audit", "--project-dir", str(root)])
141+
# Audit may exit 1 (issues found) but must not crash
142+
assert r.exit_code in (0, 1), f"audit crashed: {r.exception}"
143+
# Audit should include phase readiness info
144+
assert "Phase" in r.output or "phase" in r.output

0 commit comments

Comments
 (0)