mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-05 04:11:53 +00:00
feat(governance): add prompt versioning, rollback --list, and state backup
- governance/index.js: archive filenames now include ISO timestamp for deterministic sorting (<base>_<ts>_<hash>.md); write .meta.json sidecar on every archive with proposalId, author, reason, and archivedAt - governance/index.js: add listPromptVersions(target) — returns archived versions for a prompt sorted newest-first with sidecar metadata surfaced - cmd-rollback.mjs: add --list flag to list available versions without restoring (delegates to listPromptVersions) - cli-parser.mjs: add --list and --output flags - lib.mjs: pass list flag to cmdRollback; add backup command dispatch - cmd-backup.mjs: new torch-lock backup command — snapshots .scheduler-memory/memory-store.json and scheduler run state to .torch/backups/<timestamp>/; supports --output override and --list - docs/prompt-versioning.md: comprehensive guide to the full proposal → apply → list-versions → rollback workflow, state backup and restore procedure, and storage location reference - test/governance.test.mjs: 7 scenario-based tests (SCN-proposal-create, SCN-proposal-list, SCN-proposal-reject, SCN-archive-naming, SCN-version-list, SCN-rollback-latest, SCN-rollback-hash) https://claude.ai/code/session_01Ndq2D72Kp77BYo4owD63uY
This commit is contained in:
7 files changed
+914
-47
No files matched your search
@@ -0,0 +1,290 @@
|
||||
# Prompt Versioning and State Backup
|
||||
|
||||
This document describes how TORCH manages agent prompt versions and runtime state backups — two distinct but complementary systems.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
| Concern | Mechanism | Storage location |
|
||||
|---------|-----------|-----------------|
|
||||
| Prompt change control | Governance proposals | `src/proposals/` |
|
||||
| Prompt version archive | Applied-proposal archive | `.torch/prompt-history/` |
|
||||
| Prompt rollback | `torch-lock rollback` | Reads `.torch/prompt-history/`, falls back to git |
|
||||
| State snapshot | `torch-lock backup` | `.torch/backups/<timestamp>/` |
|
||||
|
||||
---
|
||||
|
||||
## 1. Prompt Versioning
|
||||
|
||||
### How it works
|
||||
|
||||
Every agent prompt lives in `src/prompts/daily/<agent>.md` or `src/prompts/weekly/<agent>.md`. These are the canonical sources of truth.
|
||||
|
||||
When a change is proposed and applied through the governance system, TORCH automatically archives the **old** content before overwriting the file. The archive is stored in:
|
||||
|
||||
```
|
||||
.torch/prompt-history/<subpath>/<basename>_<timestamp>_<sha256>.md
|
||||
```
|
||||
|
||||
A sidecar metadata file is written alongside each archive:
|
||||
|
||||
```
|
||||
.torch/prompt-history/<subpath>/<basename>_<timestamp>_<sha256>.meta.json
|
||||
```
|
||||
|
||||
The sidecar records who made the change, why, and when — making the archive self-documenting.
|
||||
|
||||
### Filename format
|
||||
|
||||
```
|
||||
audit-agent_2026-01-15T00-00-00-000Z_a3f5b19c....md
|
||||
│ │ │
|
||||
│ │ └─ SHA-256 of old content
|
||||
│ └─ ISO timestamp (colons/dots replaced with dashes)
|
||||
└─ Prompt base name
|
||||
```
|
||||
|
||||
This naming scheme ensures versions sort lexicographically by time with no reliance on filesystem mtime.
|
||||
|
||||
---
|
||||
|
||||
## 2. Proposal Workflow (Create → Apply → Rollback)
|
||||
|
||||
### Step 1 — Create a proposal
|
||||
|
||||
```bash
|
||||
torch-lock proposal create \
|
||||
--agent <agent-name> \
|
||||
--target src/prompts/daily/<agent>.md \
|
||||
--content /path/to/new-content.md \
|
||||
--reason "Add missing EXIT CRITERIA section"
|
||||
```
|
||||
|
||||
This writes the proposal to `src/proposals/<timestamp>_<agent>/`:
|
||||
- `meta.json` — author, target, reason, status
|
||||
- `new.md` — proposed new content
|
||||
- `change.diff` — git diff against current file
|
||||
|
||||
The target path must be within `src/prompts/daily/` or `src/prompts/weekly/`.
|
||||
|
||||
### Step 2 — List pending proposals
|
||||
|
||||
```bash
|
||||
torch-lock proposal list
|
||||
# or filter by status:
|
||||
torch-lock proposal list --status pending
|
||||
```
|
||||
|
||||
### Step 3 — Inspect a proposal
|
||||
|
||||
```bash
|
||||
torch-lock proposal show --id <proposal-id>
|
||||
```
|
||||
|
||||
### Step 4 — Apply the proposal
|
||||
|
||||
```bash
|
||||
torch-lock proposal apply --id <proposal-id>
|
||||
```
|
||||
|
||||
Before writing the new content, TORCH:
|
||||
1. Validates the proposal passes all invariant checks (required contract headers)
|
||||
2. Archives the **current** file content to `.torch/prompt-history/`
|
||||
3. Writes the new content to the target path
|
||||
4. Attempts a `git add` + `git commit` automatically
|
||||
|
||||
A proposal can only be applied when its status is `pending`.
|
||||
|
||||
### Step 5 — Reject a proposal (optional alternative)
|
||||
|
||||
```bash
|
||||
torch-lock proposal reject --id <proposal-id> --reason "Does not preserve EXIT CRITERIA pattern"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Listing Available Versions
|
||||
|
||||
To see what archived versions exist for a prompt:
|
||||
|
||||
```bash
|
||||
torch-lock rollback --target src/prompts/daily/audit-agent.md --list
|
||||
```
|
||||
|
||||
Output (JSON array, newest first):
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"filename": "audit-agent_2026-02-20T12-00-00-000Z_a3f5b19c.md",
|
||||
"archivedAt": "2026-02-20T12:00:00.000Z",
|
||||
"hash": "a3f5b19c...",
|
||||
"proposalId": "2026-02-20T12-00-00-000Z_prompt-fixer-agent",
|
||||
"author": "prompt-fixer-agent",
|
||||
"reason": "Add missing EXIT CRITERIA section"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Rolling Back a Prompt
|
||||
|
||||
### Restore the most recent version
|
||||
|
||||
```bash
|
||||
torch-lock rollback --target src/prompts/daily/audit-agent.md
|
||||
# same as:
|
||||
torch-lock rollback --target src/prompts/daily/audit-agent.md --strategy latest
|
||||
```
|
||||
|
||||
### Restore a specific version by hash fragment
|
||||
|
||||
```bash
|
||||
torch-lock rollback --target src/prompts/daily/audit-agent.md --strategy a3f5b19c
|
||||
```
|
||||
|
||||
Any unique fragment of the hash or timestamp in the filename works as a strategy value.
|
||||
|
||||
### Fallback to git
|
||||
|
||||
If no local archive exists, TORCH falls back to git:
|
||||
|
||||
```bash
|
||||
# Restores the HEAD version from git (useful if .torch/ was lost)
|
||||
torch-lock rollback --target src/prompts/daily/audit-agent.md --strategy latest
|
||||
```
|
||||
|
||||
Or specify an explicit git commit SHA:
|
||||
|
||||
```bash
|
||||
torch-lock rollback --target src/prompts/daily/audit-agent.md --strategy <git-sha>
|
||||
```
|
||||
|
||||
The fallback uses `git checkout <commit> -- <target>`, which overwrites the file in the working tree.
|
||||
|
||||
---
|
||||
|
||||
## 5. State Backup
|
||||
|
||||
Agent runtime state lives outside of git in two places:
|
||||
|
||||
| File | Contents |
|
||||
|------|----------|
|
||||
| `.scheduler-memory/memory-store.json` | Agent long-term memory |
|
||||
| `task-logs/daily/.scheduler-run-state.json` | Scheduler lock deferral state |
|
||||
|
||||
### Create a snapshot
|
||||
|
||||
```bash
|
||||
torch-lock backup
|
||||
```
|
||||
|
||||
This writes a timestamped directory under `.torch/backups/`:
|
||||
|
||||
```
|
||||
.torch/backups/
|
||||
└── 2026-02-20T12-00-00-000Z/
|
||||
├── backup-manifest.json
|
||||
├── .scheduler-memory__memory-store.json
|
||||
└── task-logs__daily__.scheduler-run-state.json
|
||||
```
|
||||
|
||||
`backup-manifest.json` records what was captured, what was skipped (if a file was missing), the git commit at backup time, and the ISO timestamp.
|
||||
|
||||
### Write to a custom directory
|
||||
|
||||
```bash
|
||||
torch-lock backup --output /path/to/my-backup-dir
|
||||
```
|
||||
|
||||
### List existing backups
|
||||
|
||||
```bash
|
||||
torch-lock backup --list
|
||||
```
|
||||
|
||||
Output (JSON array, newest first):
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "2026-02-20T12-00-00-000Z",
|
||||
"createdAt": "2026-02-20T12:00:00.000Z",
|
||||
"gitCommit": "a3f5b19...",
|
||||
"captured": [
|
||||
".scheduler-memory/memory-store.json",
|
||||
"task-logs/daily/.scheduler-run-state.json"
|
||||
],
|
||||
"backupDir": "/path/to/TORCH/.torch/backups/2026-02-20T12-00-00-000Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Restore from a backup
|
||||
|
||||
Restoration is a manual copy. From your project root:
|
||||
|
||||
```bash
|
||||
# Restore memory store
|
||||
cp .torch/backups/<id>/.scheduler-memory__memory-store.json .scheduler-memory/memory-store.json
|
||||
|
||||
# Restore scheduler run state
|
||||
cp .torch/backups/<id>/task-logs__daily__.scheduler-run-state.json task-logs/daily/.scheduler-run-state.json
|
||||
```
|
||||
|
||||
There is intentionally no automated restore command — restoring memory state is a significant operation that should be a deliberate human decision.
|
||||
|
||||
### Recommended backup cadence
|
||||
|
||||
The `backup-agent` (weekly) can be configured to run `torch-lock backup` as part of the weekly cycle. Alternatively, add it to your CI pipeline or cron schedule. Backups are cheap (two small JSON files) and idempotent.
|
||||
|
||||
---
|
||||
|
||||
## 6. What Is and Is Not Versioned
|
||||
|
||||
| Artifact | Version tracked | How |
|
||||
|----------|----------------|-----|
|
||||
| `src/prompts/daily/*.md` | Yes | Proposal archive + git history |
|
||||
| `src/prompts/weekly/*.md` | Yes | Proposal archive + git history |
|
||||
| `.scheduler-memory/memory-store.json` | Snapshot only | `torch-lock backup` |
|
||||
| `task-logs/daily/.scheduler-run-state.json` | Snapshot only | `torch-lock backup` |
|
||||
| `src/proposals/*/` | Permanent record | On-disk (not archived further) |
|
||||
| `torch-config.json` | Git history | Standard git |
|
||||
|
||||
---
|
||||
|
||||
## 7. Storage Locations Reference
|
||||
|
||||
```
|
||||
.torch/
|
||||
├── prompt-history/ # Prompt archive (created on first proposal apply)
|
||||
│ └── src/prompts/daily/
|
||||
│ ├── audit-agent_<ts>_<hash>.md # Archived prompt content
|
||||
│ └── audit-agent_<ts>_<hash>.meta.json # Archive metadata
|
||||
└── backups/ # State snapshots
|
||||
└── <timestamp>/
|
||||
├── backup-manifest.json
|
||||
├── .scheduler-memory__memory-store.json
|
||||
└── task-logs__daily__.scheduler-run-state.json
|
||||
|
||||
src/proposals/
|
||||
└── <timestamp>_<agent>/ # One directory per proposal
|
||||
├── meta.json
|
||||
├── new.md
|
||||
└── change.diff
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Removing TORCH
|
||||
|
||||
The `.torch/` directory (prompt history + backups) and `src/proposals/` are removed by `torch-lock remove`. See [docs/removal.md](removal.md) for the full removal procedure.
|
||||
|
||||
If you want to preserve the prompt history or state backups before removing TORCH, copy `.torch/` to a safe location first:
|
||||
|
||||
```bash
|
||||
cp -r .torch/ ~/torch-archive-$(date +%Y%m%d)/
|
||||
torch-lock remove
|
||||
```
|
||||
Reference in new issue
Block a user