Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
50 changes: 50 additions & 0 deletions .specsmith/requirements.json
Original file line number Diff line number Diff line change
Expand Up @@ -2931,5 +2931,55 @@
"test_ids": [
"TEST-335"
]
},
{
"id": "REQ-336",
"title": "specsmith save CLI Command",
"description": "specsmith MUST provide a top-level `save` CLI command that performs a full governance checkpoint in three steps: (1) create a timestamped ESDB backup via ChronoStore.backup(); (2) git-commit all pending governance changes (LEDGER.md, .specsmith/, docs/) with an auto-generated commit message; (3) git-push the current branch to origin. The command MUST exit 0 on success, exit 1 on any step failure, and print a human-readable summary of what was saved. `--json` MUST emit a structured payload with backup_path, commit_hash, and push_ok fields.",
"source": "ARCHITECTURE.md §CI Automation Manager — save/load Commands",
"status": "implemented",
"test_ids": [
"TEST-336"
]
},
{
"id": "REQ-337",
"title": "specsmith load CLI Command",
"description": "specsmith MUST provide a top-level `load` CLI command that pulls the latest governance state from origin: (1) git-pull the current branch; (2) optionally restore the latest ESDB backup when `--restore-backup` is passed; (3) print a status report of what changed. The command MUST exit 0 on success and exit 1 if git-pull fails with an unresolvable conflict. `--json` MUST emit a structured payload with pull_ok, files_changed, and backup_restored fields.",
"source": "ARCHITECTURE.md §CI Automation Manager — save/load Commands",
"status": "implemented",
"test_ids": [
"TEST-337"
]
},
{
"id": "REQ-338",
"title": "specsmith_run Agent Tool with Slash-Command Routing",
"description": "The agent tool registry MUST expose a `specsmith_run(command)` tool that normalises three input forms to `specsmith <args>` and executes via subprocess: (1) slash-command prefix (`/specsmith save`); (2) single-word verb shortcuts (`save`, `load`, `push`, `pull`, `sync`, `audit`, `status`, `watch`, `commit`, `validate`, `doctor`, `run`); (3) full passthrough (`specsmith <args>`). The tool MUST be registered in AVAILABLE_TOOLS and build_tool_registry() with REG-001/REG-002 epistemic claim metadata. Agents MUST use specsmith_run for all governance CLI operations instead of raw run_shell calls.",
"source": "ARCHITECTURE.md §Agent Tool Registry — specsmith_run",
"status": "implemented",
"test_ids": [
"TEST-338"
]
},
{
"id": "REQ-339",
"title": "M005 Agent-Run-Tool Migration",
"description": "The migration framework MUST include migration M005 (version=5) that auto-upgrades existing projects to use the specsmith_run governance command. M005 MUST: (1) write `.specsmith/agent-tools.json` declaring specsmith_run as the primary_governance_command with a full verb_shortcuts list; (2) append a \"Governance commands\" section to AGENTS.md documenting all /specsmith slash-command forms, backing up the original to `.specsmith/agents.md.m005.bak`. Both steps MUST be non-destructive and support `dry_run=True` and `rollback()`. M005 MUST be registered in MigrationRegistry.",
"source": "ARCHITECTURE.md §Migration Framework — M005",
"status": "implemented",
"test_ids": [
"TEST-339"
]
},
{
"id": "REQ-340",
"title": "/specsmith REPL Slash-Command Handler",
"description": "The Nexus REPL (agent/repl.py) MUST handle `/specsmith <args>` as a first-class slash command that passes args verbatim to the specsmith CLI subprocess and streams output directly to the terminal without buffering. The handler MUST gracefully handle subprocess timeout (120 s default) and unexpected exceptions without crashing the REPL. The REPL startup banner MUST advertise the /specsmith command. Invoking `/specsmith` with no args MUST display specsmith --help.",
"source": "ARCHITECTURE.md §Nexus REPL — /specsmith Handler",
"status": "implemented",
"test_ids": [
"TEST-340"
]
}
]
55 changes: 55 additions & 0 deletions .specsmith/testcases.json
Original file line number Diff line number Diff line change
Expand Up @@ -3254,5 +3254,60 @@
"input": "specsmith test-ran TEST-001 --result passed / failed / unknown-id / --json",
"expected_behavior": "testcases.json updated; status transitions correct; ledger entry written; exit codes correct; JSON output valid",
"confidence": 0.95
},
{
"id": "TEST-336",
"title": "specsmith save Performs Backup, Commit, and Push",
"description": "`specsmith save` on a project with pending governance changes MUST create a timestamped backup under .chronomemory/backup/, git-commit all changed files, and git-push to origin. With --json it MUST emit {backup_path, commit_hash, push_ok}. With no pending changes it MUST exit 0 with a 'nothing to commit' message. On push failure it MUST exit 1 with an informative error.",
"requirement_id": "REQ-336",
"type": "cli",
"verification_method": "pytest",
"input": "specsmith save [--json] on project with dirty governance files; repeat with clean repo",
"expected_behavior": "Backup created; git commit recorded; push attempted; exit 0 on success; --json payload valid; clean repo exits 0 with 'nothing to commit'",
"confidence": 0.95
},
{
"id": "TEST-337",
"title": "specsmith load Pulls Latest Governance State",
"description": "`specsmith load` MUST execute git-pull on the current branch and report files changed. With `--restore-backup` it MUST also restore the most recent backup from .chronomemory/backup/. With --json it MUST emit {pull_ok, files_changed, backup_restored}. On merge conflict git-pull it MUST exit 1 with the conflict details.",
"requirement_id": "REQ-337",
"type": "cli",
"verification_method": "pytest",
"input": "specsmith load [--restore-backup] [--json] on project with remote changes",
"expected_behavior": "git-pull executed; files_changed count correct; backup optionally restored; --json payload valid; conflict exits 1",
"confidence": 0.9
},
{
"id": "TEST-338",
"title": "specsmith_run Tool Normalises Slash-Command and Verb Shortcut Forms",
"description": "specsmith_run('/specsmith save') MUST execute `specsmith save`. specsmith_run('save') MUST execute `specsmith save`. specsmith_run('specsmith audit --strict') MUST execute `specsmith audit --strict`. specsmith_run('') MUST execute `specsmith --help`. specsmith_run MUST appear in AVAILABLE_TOOLS and build_tool_registry() and carry epistemic_claims listing side-effect categories.",
"requirement_id": "REQ-338",
"type": "unit",
"verification_method": "pytest",
"input": "specsmith_run('/specsmith save'); specsmith_run('save'); specsmith_run('specsmith audit --strict'); specsmith_run('')",
"expected_behavior": "All three input forms resolve to the correct specsmith subprocess call; empty input triggers --help; tool registered with correct metadata",
"confidence": 0.95
},
{
"id": "TEST-339",
"title": "M005 Migration Writes agent-tools.json and Patches AGENTS.md",
"description": "Running AgentRunToolMigration().run(project_root) MUST create .specsmith/agent-tools.json with primary_governance_command=specsmith_run and the full verb_shortcuts list. It MUST append a Governance commands section to AGENTS.md and write .specsmith/agents.md.m005.bak. dry_run=True MUST report expected changes without writing. rollback() MUST remove agent-tools.json and restore AGENTS.md from backup. M005 MUST appear in MigrationRegistry.all().",
"requirement_id": "REQ-339",
"type": "integration",
"verification_method": "pytest",
"input": "AgentRunToolMigration().run(tmp_path); dry_run=True; rollback()",
"expected_behavior": "agent-tools.json written with correct schema; AGENTS.md patched; backup created; dry_run produces no files; rollback restores state; registry includes v5",
"confidence": 0.95
},
{
"id": "TEST-340",
"title": "/specsmith REPL Handler Streams CLI Output",
"description": "In the Nexus REPL, entering `/specsmith status` MUST invoke `specsmith status` as a subprocess with shell=True, streaming output to the terminal (capture_output=False). `/specsmith` with no args MUST invoke `specsmith --help`. A subprocess timeout MUST print a timeout message without crashing the REPL loop. The REPL startup banner MUST contain the string '/specsmith'.",
"requirement_id": "REQ-340",
"type": "unit",
"verification_method": "pytest",
"input": "NEXUS_BANNER string; mock subprocess.run for /specsmith status; /specsmith with no args; timeout simulation",
"expected_behavior": "Banner contains '/specsmith'; subprocess called with correct args; timeout handled gracefully; REPL loop continues after error",
"confidence": 0.9
}
]
11 changes: 11 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ py -m specsmith migrate list
Only proceed with the requested task once all three steps complete without errors.
If `audit` reports failures, surface them to the user before starting work.

## Session Teardown

At the end of **every** session, always run:

```bash
py -m specsmith kill-session
```

This stops `governance-serve` and any other tracked agent processes.
Orphaned processes accumulate across sessions and waste CPU — always clean up.

## For AI Agents

All governance rules, session state, requirements, and epistemic constraints
Expand Down
86 changes: 80 additions & 6 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -760,10 +760,84 @@ Reads YAML sources and regenerates Markdown artifacts. Does not rewrite the JSON

**CI integration**: The `validate-strict` job in `.github/workflows/ci.yml` runs `specsmith validate --strict --json` on every push and PR. The `sync-check` step runs `specsmith sync --check`. Both block the build on failure.

**Migration**: `scripts/migrate_governance_to_yaml.py` — idempotent script converting an existing Markdown-primary project to YAML-first mode:
1. Remove duplicate REQs from REQUIREMENTS.md
2. Re-sync `.specsmith/` JSON from cleaned Markdown
3. Export JSON to grouped YAML domain files under `docs/requirements/` and `docs/tests/`
4. Write `.specsmith/governance-mode = yaml`
## 32. CI Automation Manager — save/load Commands
Source: `src/specsmith/cli.py` §`save`, `load`; `src/specsmith/ci_manager.py`

Re-running the script on an already-migrated project produces no changes.
Two top-level CLI commands provide a complete governance checkpoint cycle:

**`specsmith save`** (REQ-336):
1. Create a timestamped ESDB backup via `ChronoStore.backup()` (written to `.chronomemory/backup/<timestamp>/`)
2. `git add` all governance files and `git commit` with an auto-generated message
3. `git push` the current branch to origin
- `--json` emits `{backup_path, commit_hash, push_ok}`
- Exits 0 on success; exits 1 on any step failure

**`specsmith load`** (REQ-337):
1. `git pull` the current branch from origin
2. Optionally restore the latest ESDB backup when `--restore-backup` is passed
3. Print a summary of files changed
- `--json` emits `{pull_ok, files_changed, backup_restored}`
- Exits 1 on unresolvable merge conflict

**`specsmith ci watch`**:
Uses `gh run watch --exit-status` (native blocking for GitHub) or exponential-backoff polling (other platforms, starting at 10 s, capped at 60 s). Eliminates busy-wait `time.sleep` loops.

## 33. Agent Tool Registry — specsmith_run
Source: `src/specsmith/agent/tools.py` §`specsmith_run`, `AVAILABLE_TOOLS`, `build_tool_registry`

`specsmith_run(command)` is the canonical agent tool for all specsmith governance operations (REQ-338). It normalises three input forms:

| Input form | Example | Resolved command |
|---|---|---|
| Slash prefix | `/specsmith save` | `specsmith save` |
| Verb shortcut | `save` | `specsmith save` |
| Full passthrough | `specsmith audit --strict` | `specsmith audit --strict` |

Verb shortcuts: `audit`, `commit`, `doctor`, `load`, `pull`, `push`, `run`, `save`, `status`, `sync`, `validate`, `watch`.

Registered in `AVAILABLE_TOOLS` and `build_tool_registry()` with REG-001/REG-002 epistemic claims:
- `invokes specsmith CLI; may write to .specsmith/ and .chronomemory/`
- `save/push/commit modify git history`
- `load/pull may overwrite local governance state`

**Architecture invariant (I10):** Agents MUST use `specsmith_run` for all governance CLI operations. Direct `run_shell('specsmith ...')` calls are prohibited when `specsmith_run` is available in the tool registry.

## 34. Migration Framework — M005 Agent-Run-Tool Migration
Source: `src/specsmith/migrations/m005_agent_run_tool.py`; `src/specsmith/migrations/__init__.py`

M005 (version=5) is the auto-upgrade migration that registers `specsmith_run` as the primary governance command for existing projects (REQ-339).

**Step 1 — Write `.specsmith/agent-tools.json`:**
```json
{
"schema_version": 1,
"primary_governance_command": "specsmith_run",
"slash_prefix": "/specsmith",
"verb_shortcuts": ["audit", "commit", "doctor", "load", ...]
}
```

**Step 2 — Patch `AGENTS.md`:**
Appends a "Governance commands (specsmith_run / /specsmith)" section documenting all slash-command forms and verb shortcuts. Original `AGENTS.md` is backed up to `.specsmith/agents.md.m005.bak` before modification.

Both steps support `dry_run=True` (reports what would change without writing) and `rollback()` (restores backup, removes `agent-tools.json`). M005 is registered in `MigrationRegistry` and runs automatically via `specsmith migrate-project`.

## 35. Nexus REPL — /specsmith Slash-Command Handler
Source: `src/specsmith/agent/repl.py` §`/specsmith` handler

The Nexus REPL (`specsmith run`) handles `/specsmith <args>` as a first-class slash command (REQ-340):

```
nexus> /specsmith save
nexus> /specsmith audit --strict
nexus> /specsmith status
```

Implementation:
- `command == '/specsmith'` branch intercepts the input before the broker
- Invokes `subprocess.run(f'specsmith {sm_args}', shell=True, capture_output=False)` — output streams directly to terminal
- Timeout: 120 s; graceful error handling (no REPL crash)
- Empty `/specsmith` (no args) shows `specsmith --help`
- Startup banner advertises the command: `"Use /specsmith <args> to run any specsmith CLI command directly."`

**Architecture invariant (I11):** The `/specsmith` handler MUST precede the broker branch in the REPL dispatch loop so governance commands bypass the LLM preflight path entirely.
40 changes: 40 additions & 0 deletions docs/REQUIREMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2346,3 +2346,43 @@
- **Source:** ARCHITECTURE.md §Governance CLI
- **Test_Ids:** ['TEST-335']

## REQ-336. specsmith save CLI Command
- **ID:** REQ-336
- **Title:** specsmith save CLI Command
- **Description:** specsmith MUST provide a top-level `save` CLI command that performs a full governance checkpoint in three steps: (1) create a timestamped ESDB backup via ChronoStore.backup(); (2) git-commit all pending governance changes (LEDGER.md, .specsmith/, docs/) with an auto-generated commit message; (3) git-push the current branch to origin. The command MUST exit 0 on success, exit 1 on any step failure, and print a human-readable summary of what was saved. `--json` MUST emit a structured payload with backup_path, commit_hash, and push_ok fields.
- **Status:** implemented
- **Source:** ARCHITECTURE.md §CI Automation Manager — save/load Commands
- **Test_Ids:** ['TEST-336']

## REQ-337. specsmith load CLI Command
- **ID:** REQ-337
- **Title:** specsmith load CLI Command
- **Description:** specsmith MUST provide a top-level `load` CLI command that pulls the latest governance state from origin: (1) git-pull the current branch; (2) optionally restore the latest ESDB backup when `--restore-backup` is passed; (3) print a status report of what changed. The command MUST exit 0 on success and exit 1 if git-pull fails with an unresolvable conflict. `--json` MUST emit a structured payload with pull_ok, files_changed, and backup_restored fields.
- **Status:** implemented
- **Source:** ARCHITECTURE.md §CI Automation Manager — save/load Commands
- **Test_Ids:** ['TEST-337']

## REQ-338. specsmith_run Agent Tool with Slash-Command Routing
- **ID:** REQ-338
- **Title:** specsmith_run Agent Tool with Slash-Command Routing
- **Description:** The agent tool registry MUST expose a `specsmith_run(command)` tool that normalises three input forms to `specsmith <args>` and executes via subprocess: (1) slash-command prefix (`/specsmith save`); (2) single-word verb shortcuts (`save`, `load`, `push`, `pull`, `sync`, `audit`, `status`, `watch`, `commit`, `validate`, `doctor`, `run`); (3) full passthrough (`specsmith <args>`). The tool MUST be registered in AVAILABLE_TOOLS and build_tool_registry() with REG-001/REG-002 epistemic claim metadata. Agents MUST use specsmith_run for all governance CLI operations instead of raw run_shell calls.
- **Status:** implemented
- **Source:** ARCHITECTURE.md §Agent Tool Registry — specsmith_run
- **Test_Ids:** ['TEST-338']

## REQ-339. M005 Agent-Run-Tool Migration
- **ID:** REQ-339
- **Title:** M005 Agent-Run-Tool Migration
- **Description:** The migration framework MUST include migration M005 (version=5) that auto-upgrades existing projects to use the specsmith_run governance command. M005 MUST: (1) write `.specsmith/agent-tools.json` declaring specsmith_run as the primary_governance_command with a full verb_shortcuts list; (2) append a "Governance commands" section to AGENTS.md documenting all /specsmith slash-command forms, backing up the original to `.specsmith/agents.md.m005.bak`. Both steps MUST be non-destructive and support `dry_run=True` and `rollback()`. M005 MUST be registered in MigrationRegistry.
- **Status:** implemented
- **Source:** ARCHITECTURE.md §Migration Framework — M005
- **Test_Ids:** ['TEST-339']

## REQ-340. /specsmith REPL Slash-Command Handler
- **ID:** REQ-340
- **Title:** /specsmith REPL Slash-Command Handler
- **Description:** The Nexus REPL (agent/repl.py) MUST handle `/specsmith <args>` as a first-class slash command that passes args verbatim to the specsmith CLI subprocess and streams output directly to the terminal without buffering. The handler MUST gracefully handle subprocess timeout (120 s default) and unexpected exceptions without crashing the REPL. The REPL startup banner MUST advertise the /specsmith command. Invoking `/specsmith` with no args MUST display specsmith --help.
- **Status:** implemented
- **Source:** ARCHITECTURE.md §Nexus REPL — /specsmith Handler
- **Test_Ids:** ['TEST-340']

Loading
Loading