uv-suite 0.29.0 → 0.30.0
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.
- package/LICENSE +21 -0
- package/README.md +58 -35
- package/agents/claude-code/anti-slop-guard.md +14 -1
- package/agents/claude-code/architect.md +30 -4
- package/agents/claude-code/cartographer.md +18 -6
- package/agents/claude-code/eval-writer.md +7 -2
- package/agents/claude-code/reviewer.md +5 -1
- package/agents/claude-code/spec-writer.md +30 -7
- package/agents/generate.py +88 -0
- package/bin/cli.js +51 -48
- package/hooks/auto-checkpoint-helper.sh +2 -2
- package/hooks/auto-checkpoint.sh +3 -3
- package/hooks/auto-restore-on-start.sh +2 -2
- package/hooks/checkpoint-helper.sh +40 -35
- package/hooks/git-context.sh +41 -0
- package/hooks/lite-mode-inject.sh +26 -0
- package/hooks/session-end-helper.sh +2 -2
- package/hooks/session-end.sh +2 -2
- package/hooks/session-label-nag.sh +2 -2
- package/hooks/session-meta.sh +18 -1
- package/hooks/session-review-reminder.sh +2 -2
- package/hooks/session-start.sh +16 -0
- package/hooks/slop-grep.sh +12 -31
- package/hooks/uv-out-best.sh +20 -0
- package/hooks/uv-out-collect.sh +52 -0
- package/hooks/uv-out-notify.sh +28 -0
- package/hooks/uv-out-pointer.sh +16 -0
- package/hooks/uv-out-session.sh +24 -0
- package/hooks/watchtower-notify.sh +45 -0
- package/hooks/watchtower-send.sh +4 -0
- package/install.sh +93 -42
- package/package.json +2 -2
- package/personas/auto.json +35 -1
- package/personas/professional.json +41 -1
- package/personas/spike.json +27 -2
- package/personas/sport.json +39 -1
- package/settings.json +6 -2
- package/skills/architect/SKILL.md +109 -8
- package/skills/architect/specialists/distributed-systems.md +84 -0
- package/skills/architect/specialists/full-stack.md +92 -0
- package/skills/architect/specialists/llm-ai-engineering.md +86 -0
- package/skills/architect/specialists/ml-systems.md +81 -0
- package/skills/commit/SKILL.md +5 -2
- package/skills/confirm/SKILL.md +3 -3
- package/skills/investigate/SKILL.md +14 -4
- package/skills/lite/SKILL.md +45 -0
- package/skills/qa/SKILL.md +274 -0
- package/skills/review/SKILL.md +187 -8
- package/skills/review/specialists/api-contract.md +122 -0
- package/skills/review/specialists/architecture-trace.md +64 -0
- package/skills/review/specialists/data-migration.md +113 -0
- package/skills/review/specialists/maintainability.md +138 -0
- package/skills/review/specialists/performance.md +115 -0
- package/skills/review/specialists/security.md +132 -0
- package/skills/review/specialists/testing.md +109 -0
- package/skills/session/SKILL.md +87 -0
- package/skills/session/operations/auto.md +22 -0
- package/skills/session/operations/checkpoint.md +43 -0
- package/skills/session/operations/end.md +35 -0
- package/skills/session/operations/init.md +16 -0
- package/skills/session/operations/restore.md +16 -0
- package/skills/spec/SKILL.md +40 -1
- package/skills/test/SKILL.md +89 -0
- package/skills/test/specialists/eval.md +46 -0
- package/skills/test/specialists/integration.md +42 -0
- package/skills/test/specialists/unit.md +39 -0
- package/skills/understand/SKILL.md +118 -0
- package/skills/understand/modes/repo.md +38 -0
- package/skills/understand/modes/stack.md +41 -0
- package/skills/uv-help/SKILL.md +43 -20
- package/uv.sh +36 -3
- package/watchtower/Dockerfile +9 -0
- package/watchtower/README.md +78 -0
- package/watchtower/app/__init__.py +0 -0
- package/watchtower/app/__pycache__/__init__.cpython-314.pyc +0 -0
- package/watchtower/app/__pycache__/db.cpython-314.pyc +0 -0
- package/watchtower/app/__pycache__/main.cpython-314.pyc +0 -0
- package/watchtower/app/__pycache__/models.cpython-314.pyc +0 -0
- package/watchtower/app/db.py +85 -0
- package/watchtower/app/main.py +45 -0
- package/watchtower/app/models.py +49 -0
- package/watchtower/app/routers/__init__.py +0 -0
- package/watchtower/app/routers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/watchtower/app/routers/__pycache__/control.cpython-314.pyc +0 -0
- package/watchtower/app/routers/__pycache__/ingest.cpython-314.pyc +0 -0
- package/watchtower/app/routers/__pycache__/query.cpython-314.pyc +0 -0
- package/watchtower/app/routers/__pycache__/stream.cpython-314.pyc +0 -0
- package/watchtower/app/routers/control.py +144 -0
- package/watchtower/app/routers/ingest.py +102 -0
- package/watchtower/app/routers/query.py +84 -0
- package/watchtower/app/routers/stream.py +30 -0
- package/watchtower/app/services/__init__.py +0 -0
- package/watchtower/app/services/__pycache__/__init__.cpython-314.pyc +0 -0
- package/watchtower/app/services/__pycache__/checkpoint.cpython-314.pyc +0 -0
- package/watchtower/app/services/__pycache__/tmux.cpython-314.pyc +0 -0
- package/watchtower/app/services/checkpoint.py +107 -0
- package/watchtower/app/services/tmux.py +54 -0
- package/watchtower/docker-compose.yml +22 -0
- package/watchtower/events.json +10344 -45
- package/watchtower/{auto-checkpoint-runner.js → legacy/auto-checkpoint-runner.js} +29 -2
- package/watchtower/requirements.txt +3 -0
- package/watchtower/schema.sql +43 -0
- package/watchtower/static/dashboard.html +449 -0
- package/agents/claude-code/devops.md +0 -50
- package/agents/claude-code/security.md +0 -75
- package/agents/codex/anti-slop-guard.toml +0 -12
- package/agents/codex/architect.toml +0 -11
- package/agents/codex/cartographer.toml +0 -16
- package/agents/codex/devops.toml +0 -8
- package/agents/codex/eval-writer.toml +0 -11
- package/agents/codex/prototype-builder.toml +0 -10
- package/agents/codex/reviewer.toml +0 -16
- package/agents/codex/security.toml +0 -14
- package/agents/codex/spec-writer.toml +0 -11
- package/agents/codex/test-writer.toml +0 -13
- package/agents/cursor/anti-slop-guard.mdc +0 -22
- package/agents/cursor/architect.mdc +0 -24
- package/agents/cursor/cartographer.mdc +0 -28
- package/agents/cursor/devops.mdc +0 -16
- package/agents/cursor/eval-writer.mdc +0 -21
- package/agents/cursor/prototype-builder.mdc +0 -25
- package/agents/cursor/reviewer.mdc +0 -26
- package/agents/cursor/security.mdc +0 -20
- package/agents/cursor/spec-writer.mdc +0 -27
- package/agents/cursor/test-writer.mdc +0 -28
- package/agents/portable/anti-slop-guard.md +0 -71
- package/agents/portable/architect.md +0 -83
- package/agents/portable/cartographer.md +0 -64
- package/agents/portable/devops.md +0 -56
- package/agents/portable/eval-writer.md +0 -70
- package/agents/portable/prototype-builder.md +0 -70
- package/agents/portable/reviewer.md +0 -79
- package/agents/portable/security.md +0 -63
- package/agents/portable/spec-writer.md +0 -89
- package/agents/portable/test-writer.md +0 -56
- package/hooks/context-warning.sh +0 -4
- package/skills/auto-checkpoint/SKILL.md +0 -47
- package/skills/checkpoint/SKILL.md +0 -105
- package/skills/map-codebase/SKILL.md +0 -54
- package/skills/map-stack/SKILL.md +0 -121
- package/skills/restore/SKILL.md +0 -55
- package/skills/security-review/SKILL.md +0 -87
- package/skills/session-end/SKILL.md +0 -100
- package/skills/session-init/SKILL.md +0 -45
- package/skills/slop-check/SKILL.md +0 -40
- package/skills/write-evals/SKILL.md +0 -34
- package/skills/write-tests/SKILL.md +0 -54
- /package/watchtower/{auto-checkpoint-prompt.md → legacy/auto-checkpoint-prompt.md} +0 -0
- /package/watchtower/{dashboard.html → legacy/dashboard.html} +0 -0
- /package/watchtower/{server.js → legacy/server.js} +0 -0
- /package/watchtower/{snapshot-manager.js → legacy/snapshot-manager.js} +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Utsav Anand
|
|
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.
|
package/README.md
CHANGED
|
@@ -38,7 +38,31 @@ Label this session (Enter to skip — you'll be reminded):
|
|
|
38
38
|
priority [low/med/high]: high
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
Skip any field with Enter. If you skip the name, `/session
|
|
41
|
+
Skip any field with Enter. If you skip the name, `/session init` will be suggested every few prompts until you label it. Set `UVS_NO_PROMPT=1` to suppress prompts entirely.
|
|
42
|
+
|
|
43
|
+
## Start here
|
|
44
|
+
|
|
45
|
+
After `uvs claude pro`, pick the path that matches what you're doing. Each path names the first skill to run and the canonical next steps.
|
|
46
|
+
|
|
47
|
+
### Existing codebase (you didn't write this)
|
|
48
|
+
1. `/understand` — builds a knowledge graph + architecture overview in `uv-out/map-codebase.md`. Other skills (`/architect`, `/review`, `/review --security`) read it automatically.
|
|
49
|
+
2. `/session checkpoint` — captures your baseline understanding so `/session restore` can bring it back next session.
|
|
50
|
+
3. Then: `/review` on the current diff, or `/spec` for the next feature.
|
|
51
|
+
|
|
52
|
+
### New project (you're starting from scratch)
|
|
53
|
+
1. `/spec` — converts your idea into a structured spec in `uv-out/specs/`.
|
|
54
|
+
2. `/architect` — breaks the spec into Acts with cycle budgets. Reads the spec automatically.
|
|
55
|
+
3. Then: implement Act by Act. Use `/test` and `/review` per Act.
|
|
56
|
+
|
|
57
|
+
### Reviewing a PR
|
|
58
|
+
1. `/review [branch-name]` — reads diff + `CLAUDE.md` + `DANGER-ZONES.md` + prior `uv-out/` artifacts.
|
|
59
|
+
2. `/review --security` if the diff touches auth, payments, data access, or external inputs.
|
|
60
|
+
|
|
61
|
+
### Shipping
|
|
62
|
+
1. `/session checkpoint` to capture state.
|
|
63
|
+
2. `/commit` — runs review, tests, commits, optionally opens a PR.
|
|
64
|
+
|
|
65
|
+
Picking a persona (Spike / Sport / Professional / Auto) is a separate axis from picking a first skill — see [Personas](#personas) below for which mode fits which situation.
|
|
42
66
|
|
|
43
67
|
## Sessions and Watchtower
|
|
44
68
|
|
|
@@ -46,7 +70,7 @@ Each `uvs` launch generates a `UVS_SESSION_ID` and writes metadata to `.uv-suite
|
|
|
46
70
|
|
|
47
71
|
- **Concurrent terminals don't collide.** Two `uvs` launches in the same repo run as distinct sessions with separate names, checkpoints, and dashboard rows.
|
|
48
72
|
- **`uvs watch` shows them all.** The Watchtower dashboard at `localhost:4200` streams every tool call across every session in real time — labeled by your name, sorted by priority (high to top, low dimmed), color-coded by persona.
|
|
49
|
-
- **Per-session checkpoints.** `/checkpoint` writes to `uv-out/checkpoints/<sid>/`, and `/restore` auto-picks the current session's latest. Pass a session id prefix or name to restore from a different one.
|
|
73
|
+
- **Per-session checkpoints.** `/session checkpoint` writes to `uv-out/checkpoints/<sid>/`, and `/session restore` auto-picks the current session's latest. Pass a session id prefix or name to restore from a different one.
|
|
50
74
|
- **Status line shows it all.** The Claude Code status bar shows session name, persona, priority, and elapsed time continuously.
|
|
51
75
|
|
|
52
76
|
### Watchtower at a glance
|
|
@@ -104,50 +128,48 @@ Human gates After each End only Every Act Final output
|
|
|
104
128
|
|
|
105
129
|
## Skills (slash commands)
|
|
106
130
|
|
|
131
|
+
12 skills. Each `skills/<name>/SKILL.md` is a thin orchestrator that dispatches to agents.
|
|
132
|
+
|
|
107
133
|
| Command | What it does |
|
|
108
134
|
|---|---|
|
|
109
|
-
| `/
|
|
110
|
-
| `/map-stack [dir]` | Map multiple services and their connections |
|
|
135
|
+
| `/understand [dir]` | Map a codebase or whole stack — auto-detects repo vs stack |
|
|
111
136
|
| `/spec [requirements]` | Write a technical specification |
|
|
112
137
|
| `/architect [spec]` | Design architecture, decompose into Acts |
|
|
138
|
+
| `/test [file]` | Write tests or evals: `--unit` / `--integration` / `--eval` ([DeepEval](https://github.com/confident-ai/deepeval) compatible) |
|
|
139
|
+
| `/review` | Multi-specialist code review; add `--security` (OWASP via Semgrep/Gitleaks/Trivy) or `--slop` (anti-slop audit) |
|
|
113
140
|
| `/prototype [concept]` | Build a static React prototype |
|
|
114
|
-
| `/
|
|
115
|
-
| `/write-evals [prompt]` | Write AI/LLM evaluation cases ([DeepEval](https://github.com/confident-ai/deepeval) compatible) |
|
|
116
|
-
| `/review` | Code review: correctness, security, performance, slop |
|
|
117
|
-
| `/slop-check` | Detect 6 categories of AI-generated slop |
|
|
118
|
-
| `/security-review` | OWASP audit, dependency scan, secret detection |
|
|
141
|
+
| `/qa` | Browser QA via Playwright MCP |
|
|
119
142
|
| `/investigate` | Systematic root-cause debugging |
|
|
120
|
-
| `/commit` | Review → test →
|
|
121
|
-
| `/checkpoint
|
|
122
|
-
| `/restore [sid-prefix\|name]` | Load the latest checkpoint for the current (or named) session |
|
|
123
|
-
| `/session-init [name\|--kind\|--purpose\|--priority]` | Label or relabel the current session |
|
|
143
|
+
| `/commit` | Review → test → commit (and optionally PR) |
|
|
144
|
+
| `/session init\|checkpoint\|restore\|end\|auto` | Session lifecycle — label, checkpoint, restore, end, or auto-checkpoint |
|
|
124
145
|
| `/confirm [on\|off\|<n>]` | Toggle reframe-and-confirm for prompts over `<n>` words |
|
|
125
146
|
| `/uv-help` | List every skill, agent, hook, guardrail, and persona |
|
|
126
147
|
|
|
127
148
|
## Hooks (lifecycle automation)
|
|
128
149
|
|
|
129
|
-
Fire automatically on Claude Code events. You never invoke these.
|
|
150
|
+
Fire automatically on Claude Code events. You never invoke these. ~26 scripts live in `hooks/`.
|
|
130
151
|
|
|
131
152
|
| Hook | Fires on | What it does |
|
|
132
153
|
|---|---|---|
|
|
133
154
|
| auto-lint | File write | Runs prettier, ruff, or gofmt |
|
|
134
|
-
| slop-grep | File write |
|
|
135
|
-
| doc-slop-grep | File write | Catches vague adjectives in markdown |
|
|
155
|
+
| slop-grep | File edit/write | Ambient slop detection on sport / professional / auto personas |
|
|
156
|
+
| doc-slop-grep | File edit/write | Catches vague adjectives in markdown on the spike persona |
|
|
136
157
|
| danger-zone-check | File edit | Warns if file is in DANGER-ZONES.md |
|
|
137
158
|
| block-destructive | Bash command | Blocks `rm -rf /`, force push to main, `DROP TABLE` |
|
|
138
159
|
| confirm-prompt | UserPromptSubmit | For prompts over the threshold, requires Claude to restate before any work starts |
|
|
139
|
-
| session-label-nag | UserPromptSubmit | Reminds you to run `/session
|
|
160
|
+
| session-label-nag | UserPromptSubmit | Reminds you to run `/session init` every Nth prompt while the session has no name |
|
|
140
161
|
| context-warning | PostToolUse | Warns when context usage crosses thresholds |
|
|
141
162
|
| watchtower-send | All events | Forwards every event (with session metadata) to `localhost:4200` |
|
|
142
163
|
| session-start | SessionStart | Records start time, fires bootstrap event with session metadata |
|
|
143
164
|
| session-timer | PostToolUse | Reminders at 45 / 90 / 180 minutes |
|
|
144
165
|
| session-end | Stop | Shows duration, today's total, reflection prompt |
|
|
145
166
|
| session-review-reminder | Stop | Nudges you to review uncommitted changes |
|
|
167
|
+
| uv-out-* | Session events | Manage session-scoped artifacts under `uv-out/sessions/<sid>/` |
|
|
146
168
|
| status-line | Continuous | Renders session label, persona, priority, and timer in the Claude Code status bar |
|
|
147
169
|
|
|
148
170
|
## Agents
|
|
149
171
|
|
|
150
|
-
|
|
172
|
+
8 agents. The canonical definitions are `agents/claude-code/*.md`. The Cursor (`.mdc`) and Codex (`.toml`) variants are generated from those by `agents/generate.py` at install — they're not hand-maintained.
|
|
151
173
|
|
|
152
174
|
| Agent | Subsystem | Model | Cycle Budget |
|
|
153
175
|
|---|---|---|---|
|
|
@@ -159,8 +181,6 @@ Fire automatically on Claude Code events. You never invoke these.
|
|
|
159
181
|
| Eval Writer | Acts | Opus | 2 |
|
|
160
182
|
| Anti-Slop Guard | Guard | Opus | 1 |
|
|
161
183
|
| Prototype Builder | Acts | Sonnet | 3 |
|
|
162
|
-
| DevOps | Acts | Opus | 2 |
|
|
163
|
-
| Security | Guard | Opus | 1 |
|
|
164
184
|
|
|
165
185
|
## Artifacts
|
|
166
186
|
|
|
@@ -168,11 +188,11 @@ Agents write persistent output to `uv-out/`. Each agent reads prior artifacts au
|
|
|
168
188
|
|
|
169
189
|
| Output | Read by |
|
|
170
190
|
|---|---|
|
|
171
|
-
| `uv-out/map-codebase.md` | /architect, /review, /
|
|
172
|
-
| `uv-out/specs/*.md` | /architect, /
|
|
173
|
-
| `uv-out/architecture/*.md` | /review, /
|
|
174
|
-
| `uv-out/review-*.md` | /slop
|
|
175
|
-
| `uv-out/checkpoints/<sid>/*.md` | /restore |
|
|
191
|
+
| `uv-out/map-codebase.md` | /architect, /review, /review --security |
|
|
192
|
+
| `uv-out/specs/*.md` | /architect, /test, /test --eval |
|
|
193
|
+
| `uv-out/architecture/*.md` | /review, /test, /review --slop |
|
|
194
|
+
| `uv-out/review-*.md` | /review --slop, /review --security |
|
|
195
|
+
| `uv-out/checkpoints/<sid>/*.md` | /session restore |
|
|
176
196
|
|
|
177
197
|
## Integrations
|
|
178
198
|
|
|
@@ -190,13 +210,13 @@ Agents write persistent output to `uv-out/`. Each agent reads prior artifacts au
|
|
|
190
210
|
```
|
|
191
211
|
.claude/
|
|
192
212
|
settings.json Permissions and hooks (seeded from your persona on first install)
|
|
193
|
-
agents/
|
|
194
|
-
skills/
|
|
195
|
-
hooks/
|
|
213
|
+
agents/ 8 agent definitions (canonical .md)
|
|
214
|
+
skills/ 12 slash commands
|
|
215
|
+
hooks/ ~26 hook scripts
|
|
196
216
|
rules/ 6 anti-slop guardrails (Pro / Auto only)
|
|
197
217
|
personas/ 4 persona configs
|
|
198
|
-
.codex/agents/
|
|
199
|
-
.cursor/rules/
|
|
218
|
+
.codex/agents/ 8 Codex agent definitions (generated from .claude/agents)
|
|
219
|
+
.cursor/rules/ 8 Cursor rule definitions (generated from .claude/agents)
|
|
200
220
|
AGENTS.md Codex instruction file
|
|
201
221
|
DANGER-ZONES.md Risky areas (commit this)
|
|
202
222
|
.uv-suite-state/ Session metadata + counters (gitignored)
|
|
@@ -210,13 +230,16 @@ uv-out/ Agent output artifacts (gitignored)
|
|
|
210
230
|
|
|
211
231
|
| Document | What it covers |
|
|
212
232
|
|---|---|
|
|
213
|
-
| [
|
|
233
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Working on UV Suite — adding skills/agents/hooks, running the tests |
|
|
214
234
|
| [personas.md](personas.md) | 4 personas, 7 knobs, when to use each |
|
|
215
|
-
| [practices.md](practices.md) | Working principles (honesty, parallelism, scope, completion) |
|
|
235
|
+
| [knowledge/practices.md](knowledge/practices.md) | Working principles (honesty, parallelism, scope, completion) |
|
|
216
236
|
| [acts-methodology.md](acts-methodology.md) | Acts delivery framework with worked examples |
|
|
217
|
-
| [
|
|
218
|
-
| [
|
|
219
|
-
| [landscape.md](landscape.md) | Open source tools and references for each agent |
|
|
237
|
+
| [knowledge/human-in-the-loop.md](knowledge/human-in-the-loop.md) | Cycle budgets, intervention types, learning loops |
|
|
238
|
+
| [knowledge/sharing-and-standards.md](knowledge/sharing-and-standards.md) | Danger zones, team standards, sharing levels |
|
|
239
|
+
| [research/landscape.md](research/landscape.md) | Open source tools and references for each agent |
|
|
240
|
+
| [research/comparison.md](research/comparison.md) | UV Suite vs gstack vs Claude Code built-in — feature comparison + prompt-depth deep dive |
|
|
241
|
+
| [research/tool-comparison.md](research/tool-comparison.md) | Claude Code vs Cursor vs Codex — how UV Suite works across all three |
|
|
242
|
+
| [research/best-practices.md](research/best-practices.md) | Subagent patterns, remote sessions, sharing with engineers, cost optimization |
|
|
220
243
|
|
|
221
244
|
## License
|
|
222
245
|
|
|
@@ -19,7 +19,20 @@ You are the **Anti-Slop Guard** — your job is to catch AI-generated low-qualit
|
|
|
19
19
|
|
|
20
20
|
## Artifact Output
|
|
21
21
|
|
|
22
|
-
Write the slop report to
|
|
22
|
+
Write the slop report to `<session-output-dir>/review --slop/report.md`, where
|
|
23
|
+
`<session-output-dir>` is the path printed in the "Session output directory" section of
|
|
24
|
+
your context (e.g. `uv-out/sessions/<sid>/`). Create the directory if needed. Stamp the
|
|
25
|
+
top with provenance frontmatter:
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
---
|
|
29
|
+
session: <sid from the output dir path>
|
|
30
|
+
skill: slop-check
|
|
31
|
+
created: <ISO 8601 timestamp>
|
|
32
|
+
---
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Summarize findings in the conversation.
|
|
23
36
|
|
|
24
37
|
## What You Scan For
|
|
25
38
|
|
|
@@ -16,8 +16,21 @@ effort: high
|
|
|
16
16
|
|
|
17
17
|
You are the **Architect** — your job is to design systems and break work into deliverable Acts.
|
|
18
18
|
|
|
19
|
+
**Hard precondition: you design only from a curated spec** (problem statement, requirements,
|
|
20
|
+
success criteria). If no spec was provided or found, **stop and ask** the user to run
|
|
21
|
+
`/spec` or describe the problem so a spec can be drafted first. Never design from a vague
|
|
22
|
+
one-liner and never invent requirements — designing without a spec is a failure, not a fallback.
|
|
23
|
+
|
|
19
24
|
## Output Format
|
|
20
25
|
|
|
26
|
+
### 0. Design Constraints
|
|
27
|
+
Write these to `<session-output-dir>/architecture/constraints.md` FIRST, before any design.
|
|
28
|
+
Record the factors the design is right-sized against (from the spec's non-functional
|
|
29
|
+
requirements or gathered from the user): scale (users/RPS/data, now + ~12mo), team size &
|
|
30
|
+
expertise, availability target, consistency/CAP priority, security & privacy/compliance,
|
|
31
|
+
and fault tolerance / cost of failure. Every later decision must be justifiable against
|
|
32
|
+
these — they are what make "this is over-engineered" a checkable claim.
|
|
33
|
+
|
|
21
34
|
### 1. Architecture Decision Record
|
|
22
35
|
For each key decision, document:
|
|
23
36
|
- **Decision:** What you chose
|
|
@@ -51,11 +64,24 @@ For each key decision, document:
|
|
|
51
64
|
|
|
52
65
|
## Artifact Output
|
|
53
66
|
|
|
54
|
-
Write all output
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
Write all output under `<session-output-dir>/architecture/`, where `<session-output-dir>`
|
|
68
|
+
is the path printed in the "Session output directory" section of your context
|
|
69
|
+
(e.g. `uv-out/sessions/<sid>/`):
|
|
70
|
+
- `<session-output-dir>/architecture/constraints.md` — the Design Constraints the design is right-sized against (write this FIRST, before designing)
|
|
71
|
+
- `<session-output-dir>/architecture/decisions.md` — architecture decision records
|
|
72
|
+
- `<session-output-dir>/architecture/acts-plan.md` — Acts breakdown with tasks and cycle budgets
|
|
73
|
+
|
|
74
|
+
Create the directory if needed. Stamp the top of each file with provenance frontmatter:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
---
|
|
78
|
+
session: <sid from the output dir path>
|
|
79
|
+
skill: architect
|
|
80
|
+
created: <ISO 8601 timestamp>
|
|
81
|
+
---
|
|
82
|
+
```
|
|
57
83
|
|
|
58
|
-
|
|
84
|
+
Summarize the design in the conversation.
|
|
59
85
|
|
|
60
86
|
### 4. Task Dependency Graph
|
|
61
87
|
Mermaid diagram showing parallelism opportunities.
|
|
@@ -88,12 +88,24 @@ Produce all 6 sections (Architecture Overview, Tech Stack, Dependency Graph, Bus
|
|
|
88
88
|
|
|
89
89
|
## Artifact Output
|
|
90
90
|
|
|
91
|
-
Write all output
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
Write all output under `<session-output-dir>`, the path printed in the "Session output
|
|
92
|
+
directory" section of your context (e.g. `uv-out/sessions/<sid>/`). Create it if needed.
|
|
93
|
+
|
|
94
|
+
The calling skill names the output file — `<session-output-dir>/map-codebase.md` for
|
|
95
|
+
single-codebase mapping, `<session-output-dir>/map-stack.md` for multi-service stack
|
|
96
|
+
mapping. Follow the file named in the task; default to `map-codebase.md` if unspecified.
|
|
97
|
+
|
|
98
|
+
- The written analysis goes in that file, stamped with provenance frontmatter:
|
|
99
|
+
```yaml
|
|
100
|
+
---
|
|
101
|
+
session: <sid from the output dir path>
|
|
102
|
+
skill: map-codebase # or map-stack
|
|
103
|
+
created: <ISO 8601 timestamp>
|
|
104
|
+
---
|
|
105
|
+
```
|
|
106
|
+
- `<session-output-dir>/graphify-out/` — Graphify outputs if used (graph.html, graph.json, GRAPH_REPORT.md)
|
|
107
|
+
|
|
108
|
+
After writing, tell the human one line — "Artifacts written to `<the file you wrote>`" — and summarize key findings in the conversation.
|
|
97
109
|
|
|
98
110
|
## Rules
|
|
99
111
|
|
|
@@ -46,14 +46,19 @@ You are the **Eval Writer** — your job is to write evaluations that verify AI/
|
|
|
46
46
|
|
|
47
47
|
## Artifact Output
|
|
48
48
|
|
|
49
|
-
Write
|
|
49
|
+
Write eval artifacts to `<session-output-dir>/evals/`, where `<session-output-dir>` is the
|
|
50
|
+
path printed in the "Session output directory" section of your context (e.g.
|
|
51
|
+
`uv-out/sessions/<sid>/`). Create the directory if needed. Match the project's eval
|
|
52
|
+
framework format (DeepEval preferred). If you also add runnable evals into the project's
|
|
53
|
+
own eval suite, do that in the project tree as usual — only the artifact copy goes under
|
|
54
|
+
the session directory.
|
|
50
55
|
|
|
51
56
|
## Grading Rubric (be this specific)
|
|
52
57
|
|
|
53
58
|
```yaml
|
|
54
59
|
grading:
|
|
55
60
|
type: "llm_judge"
|
|
56
|
-
model: "claude-haiku-4-5"
|
|
61
|
+
model: "claude-haiku-4-5-20251001"
|
|
57
62
|
rubric: |
|
|
58
63
|
Score 1 (pass) if ALL of:
|
|
59
64
|
- Agent declines the out-of-scope request
|
|
@@ -65,7 +65,11 @@ You are the **Reviewer** — your job is to catch bugs, security issues, perform
|
|
|
65
65
|
|
|
66
66
|
## Artifact Output
|
|
67
67
|
|
|
68
|
-
Write
|
|
68
|
+
Write your report under `<session-output-dir>`, the path printed in the "Session output
|
|
69
|
+
directory" section of your context (e.g. `uv-out/sessions/<sid>/`). Use the filename the
|
|
70
|
+
calling task names — `review/state.md` for a code review, `investigate/report.md` for an
|
|
71
|
+
investigation. Stamp the top with provenance frontmatter (`session`, `skill`, `created`).
|
|
72
|
+
Create the directory if needed. Summarize key findings in the conversation.
|
|
69
73
|
|
|
70
74
|
## Common Findings (be this specific)
|
|
71
75
|
|
|
@@ -62,19 +62,42 @@ Unit, integration, e2e, load?
|
|
|
62
62
|
|
|
63
63
|
## Artifact Output
|
|
64
64
|
|
|
65
|
-
Write the spec to
|
|
65
|
+
Write the spec to `<session-output-dir>/specs/[feature-name]-spec.md`, where
|
|
66
|
+
`<session-output-dir>` is the path printed in the "Session output directory" section of
|
|
67
|
+
your context (e.g. `uv-out/sessions/<sid>/`). Create the directory if needed.
|
|
68
|
+
|
|
69
|
+
Stamp the top of the spec with provenance frontmatter so it stays attributable if moved:
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
---
|
|
73
|
+
session: <sid from the output dir path>
|
|
74
|
+
skill: spec
|
|
75
|
+
created: <ISO 8601 timestamp>
|
|
76
|
+
---
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then the `# Spec: [Feature Name]` heading and the rest of the template. Summarize the spec in the conversation.
|
|
66
80
|
|
|
67
81
|
## Process
|
|
68
82
|
|
|
69
|
-
1.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
1. **Ground in the existing codebase first.** Read the prior `uv-out/` artifacts loaded by
|
|
84
|
+
the skill — the codebase map (`map-codebase.md`/`map-stack.md`), prior specs, and
|
|
85
|
+
architecture decisions. Reference real modules, files, patterns, and conventions from
|
|
86
|
+
the map; reuse what exists; build on prior specs instead of re-specifying them. If no
|
|
87
|
+
map is present, say so and note that `/understand` would produce a better-grounded spec.
|
|
88
|
+
2. Parse the input into discrete requirements
|
|
89
|
+
3. Separate functional vs non-functional
|
|
90
|
+
4. Identify gaps — list as open questions, don't invent answers
|
|
91
|
+
5. Propose a high-level solution that fits the existing architecture (detailed design is
|
|
92
|
+
the Architect's job) — name the specific modules/files it touches
|
|
93
|
+
6. Define measurable success criteria
|
|
94
|
+
7. Flag risks and assumptions
|
|
75
95
|
|
|
76
96
|
## Rules
|
|
77
97
|
|
|
98
|
+
- **Ground every section in the real codebase.** The Proposed Solution, API Contract, and
|
|
99
|
+
Data Model sections must reference actual modules/types/endpoints from the map — not
|
|
100
|
+
generic placeholders. If you're inventing names because there's no map, flag it.
|
|
78
101
|
- Scale the spec to the task. A bug fix needs 1 page, not 10.
|
|
79
102
|
- Flag ambiguity as open questions — don't fill gaps with assumptions.
|
|
80
103
|
- If requirements conflict (e.g., "fast response" vs "comprehensive validation"), list both in Risks and propose which to prioritize.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate Cursor (.mdc) and Codex (.toml) agent files from the canonical
|
|
3
|
+
Claude Code agent definitions in agents/claude-code/*.md.
|
|
4
|
+
|
|
5
|
+
Single source of truth: edit agents/claude-code/<name>.md, then install.sh (or
|
|
6
|
+
`python3 agents/generate.py <cursor|codex> <dest-dir>`) regenerates the others.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 agents/generate.py cursor /path/to/.cursor/rules
|
|
10
|
+
python3 agents/generate.py codex /path/to/.codex/agents
|
|
11
|
+
"""
|
|
12
|
+
import glob
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
CANONICAL = os.path.join(os.path.dirname(os.path.abspath(__file__)), "claude-code")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def parse(md, fallback_name):
|
|
21
|
+
m = re.match(r"^---\n(.*?)\n---\n(.*)$", md, re.S)
|
|
22
|
+
fm, body = (m.group(1), m.group(2).strip()) if m else ("", md.strip())
|
|
23
|
+
|
|
24
|
+
def field(key):
|
|
25
|
+
mm = re.search(rf"^{key}:\s*(.*)$", fm, re.M)
|
|
26
|
+
return mm.group(1).strip() if mm else ""
|
|
27
|
+
|
|
28
|
+
# description is usually a folded scalar (`description: >` then indented lines)
|
|
29
|
+
desc = field("description")
|
|
30
|
+
if desc in (">", "|", ">-", "|-", ""):
|
|
31
|
+
lines = fm.splitlines()
|
|
32
|
+
idx = next((i for i, l in enumerate(lines) if l.startswith("description:")), None)
|
|
33
|
+
if idx is not None:
|
|
34
|
+
collected = []
|
|
35
|
+
for l in lines[idx + 1:]:
|
|
36
|
+
if re.match(r"^\s+\S", l):
|
|
37
|
+
collected.append(l.strip())
|
|
38
|
+
else:
|
|
39
|
+
break
|
|
40
|
+
desc = " ".join(collected) or desc
|
|
41
|
+
desc = desc.strip().strip('"')
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
"name": field("name") or fallback_name,
|
|
45
|
+
"desc": desc,
|
|
46
|
+
"model": field("model"),
|
|
47
|
+
"has_write": ("Write" in fm or "Edit" in fm),
|
|
48
|
+
"body": body,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def to_mdc(a):
|
|
53
|
+
desc = a["desc"].replace('"', '\\"')
|
|
54
|
+
return f'---\ndescription: "{desc}"\nglobs: ""\nalwaysApply: false\n---\n\n{a["body"]}\n'
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def to_toml(a):
|
|
58
|
+
effort = "high" if a["model"] == "opus" else "medium"
|
|
59
|
+
sandbox = "workspace-write" if a["has_write"] else "read-only"
|
|
60
|
+
desc = a["desc"].replace("\\", "\\\\").replace('"', '\\"')
|
|
61
|
+
body = a["body"].replace("\\", "\\\\").replace('"""', '\\"\\"\\"')
|
|
62
|
+
return (
|
|
63
|
+
f'name = "{a["name"]}"\n'
|
|
64
|
+
f'description = "{desc}"\n'
|
|
65
|
+
f'model_reasoning_effort = "{effort}"\n'
|
|
66
|
+
f'sandbox_mode = "{sandbox}"\n\n'
|
|
67
|
+
f'developer_instructions = """\n{body}\n"""\n'
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def main():
|
|
72
|
+
if len(sys.argv) != 3 or sys.argv[1] not in ("cursor", "codex"):
|
|
73
|
+
sys.exit("usage: generate.py <cursor|codex> <dest-dir>")
|
|
74
|
+
fmt, dest = sys.argv[1], sys.argv[2]
|
|
75
|
+
os.makedirs(dest, exist_ok=True)
|
|
76
|
+
ext = ".mdc" if fmt == "cursor" else ".toml"
|
|
77
|
+
render = to_mdc if fmt == "cursor" else to_toml
|
|
78
|
+
n = 0
|
|
79
|
+
for path in sorted(glob.glob(os.path.join(CANONICAL, "*.md"))):
|
|
80
|
+
name = os.path.splitext(os.path.basename(path))[0]
|
|
81
|
+
a = parse(open(path).read(), name)
|
|
82
|
+
open(os.path.join(dest, name + ext), "w").write(render(a))
|
|
83
|
+
n += 1
|
|
84
|
+
print(f"generated {n} {fmt} agents -> {dest}")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
main()
|
package/bin/cli.js
CHANGED
|
@@ -34,6 +34,7 @@ function usage() {
|
|
|
34
34
|
Monitoring:
|
|
35
35
|
uvs watch Start Watchtower dashboard (open browser)
|
|
36
36
|
uvs watch --bg Start Watchtower in background
|
|
37
|
+
uvs watch --legacy Start the legacy Node Watchtower (no Docker/Postgres)
|
|
37
38
|
|
|
38
39
|
Personas:
|
|
39
40
|
spike Research & docs (Opus, max effort)
|
|
@@ -295,59 +296,61 @@ async function launchCodex(persona, extra) {
|
|
|
295
296
|
}
|
|
296
297
|
|
|
297
298
|
function watch() {
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
const wtDir = path.join(UV_SUITE_DIR, "watchtower");
|
|
300
|
+
|
|
301
|
+
// Legacy fallback: the original Node Watchtower (no Postgres/Docker). `uvs watch --legacy`.
|
|
302
|
+
if (args.includes("--legacy")) {
|
|
303
|
+
const serverScript = path.join(wtDir, "legacy", "server.js");
|
|
304
|
+
if (!fs.existsSync(serverScript)) {
|
|
305
|
+
console.error("Error: legacy watchtower not found at", serverScript);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
const lbg = args.includes("--bg") || args.includes("--background");
|
|
309
|
+
const lurl = "http://localhost:" + (process.env.UVS_WATCHTOWER_PORT || 4200);
|
|
310
|
+
const lopener =
|
|
311
|
+
process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
312
|
+
console.log("UV Suite Watchtower (legacy Node) starting...");
|
|
313
|
+
console.log("Dashboard: " + lurl);
|
|
314
|
+
console.log("");
|
|
315
|
+
setTimeout(() => spawn(lopener, [lurl], { stdio: "ignore" }), 1000);
|
|
316
|
+
const lchild = spawn("node", [serverScript], { stdio: lbg ? "ignore" : "inherit", detached: lbg });
|
|
317
|
+
if (lbg) {
|
|
318
|
+
lchild.unref();
|
|
319
|
+
console.log(`Running in background (PID: ${lchild.pid}). Stop with: kill ${lchild.pid}`);
|
|
320
|
+
} else {
|
|
321
|
+
lchild.on("exit", (code) => process.exit(code || 0));
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (!fs.existsSync(path.join(wtDir, "docker-compose.yml"))) {
|
|
326
|
+
console.error("Error: watchtower compose not found at", wtDir);
|
|
301
327
|
process.exit(1);
|
|
302
328
|
}
|
|
303
|
-
|
|
304
329
|
const bg = args.includes("--bg") || args.includes("--background");
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
"
|
|
308
|
-
);
|
|
330
|
+
const url = "http://localhost:" + (process.env.UVS_WATCHTOWER_PORT || 4200);
|
|
331
|
+
const opener =
|
|
332
|
+
process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
333
|
+
console.log("UV Suite Watchtower (Python + Postgres) starting via docker compose...");
|
|
334
|
+
console.log("Dashboard: " + url);
|
|
309
335
|
console.log("");
|
|
310
336
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
process.
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
opener,
|
|
329
|
-
["http://localhost:" + (process.env.UVS_WATCHTOWER_PORT || 4200)],
|
|
330
|
-
{ stdio: "ignore" },
|
|
331
|
-
);
|
|
332
|
-
} else {
|
|
333
|
-
// Foreground — open browser after a short delay
|
|
334
|
-
setTimeout(() => {
|
|
335
|
-
const opener =
|
|
336
|
-
process.platform === "darwin"
|
|
337
|
-
? "open"
|
|
338
|
-
: process.platform === "win32"
|
|
339
|
-
? "start"
|
|
340
|
-
: "xdg-open";
|
|
341
|
-
spawn(
|
|
342
|
-
opener,
|
|
343
|
-
["http://localhost:" + (process.env.UVS_WATCHTOWER_PORT || 4200)],
|
|
344
|
-
{ stdio: "ignore" },
|
|
345
|
-
);
|
|
346
|
-
}, 1000);
|
|
347
|
-
|
|
348
|
-
const child = spawn("node", [serverScript], { stdio: "inherit" });
|
|
349
|
-
child.on("exit", (code) => process.exit(code || 0));
|
|
350
|
-
}
|
|
337
|
+
// Bring the stack up (Postgres + FastAPI). Build is cached after first run.
|
|
338
|
+
const up = spawn("docker", ["compose", "up", "--build", "-d"], { cwd: wtDir, stdio: "inherit" });
|
|
339
|
+
up.on("exit", (code) => {
|
|
340
|
+
if (code) {
|
|
341
|
+
console.error("docker compose failed. Is Docker running? (the Python Watchtower needs it)");
|
|
342
|
+
process.exit(code);
|
|
343
|
+
}
|
|
344
|
+
setTimeout(() => spawn(opener, [url], { stdio: "ignore" }), 1500);
|
|
345
|
+
if (bg) {
|
|
346
|
+
console.log("Watchtower running in background.");
|
|
347
|
+
console.log("Stop with: (cd watchtower && docker compose down)");
|
|
348
|
+
process.exit(0);
|
|
349
|
+
}
|
|
350
|
+
// Foreground: follow logs until Ctrl-C.
|
|
351
|
+
const logs = spawn("docker", ["compose", "logs", "-f"], { cwd: wtDir, stdio: "inherit" });
|
|
352
|
+
logs.on("exit", (c) => process.exit(c || 0));
|
|
353
|
+
});
|
|
351
354
|
}
|
|
352
355
|
|
|
353
356
|
// --- Parse and route ---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# UV Suite helper: read or change auto-checkpoint settings.
|
|
3
|
-
# Used by the /auto
|
|
3
|
+
# Used by the /session auto slash command.
|
|
4
4
|
#
|
|
5
5
|
# Usage:
|
|
6
6
|
# auto-checkpoint-helper.sh status
|
|
@@ -66,7 +66,7 @@ case "$ARG" in
|
|
|
66
66
|
set_field interval_minutes "$ARG"
|
|
67
67
|
echo "Auto-checkpoint interval: $ARG min (mode: $(get_field mode))"
|
|
68
68
|
else
|
|
69
|
-
echo "Usage: /auto
|
|
69
|
+
echo "Usage: /session auto [on | off | <minutes 1-1440> | status]"
|
|
70
70
|
exit 1
|
|
71
71
|
fi
|
|
72
72
|
;;
|
package/hooks/auto-checkpoint.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Logs every tool call into a per-session activity log. When `interval_minutes`
|
|
6
6
|
# have passed since the last mechanical checkpoint AND there has been activity
|
|
7
7
|
# in the interval, writes a deterministic snapshot to
|
|
8
|
-
# uv-out/
|
|
8
|
+
# uv-out/sessions/<sid>/checkpoints/auto-<ts>-mechanical.md and forwards an
|
|
9
9
|
# AutoCheckpoint event to the watchtower.
|
|
10
10
|
#
|
|
11
11
|
# Tier B (semantic, claude -p) runs separately from the watchtower's timer.
|
|
@@ -96,7 +96,7 @@ fi
|
|
|
96
96
|
|
|
97
97
|
# Resolve checkpoint dir + metadata via the existing helper
|
|
98
98
|
CP_DIR=$(CLAUDE_PROJECT_DIR="$PROJECT_DIR" "$PROJECT_DIR/.claude/hooks/checkpoint-helper.sh" dir 2>/dev/null)
|
|
99
|
-
[ -z "$CP_DIR" ] && CP_DIR="$PROJECT_DIR/uv-out/
|
|
99
|
+
[ -z "$CP_DIR" ] && CP_DIR="$PROJECT_DIR/uv-out/sessions/$SID/checkpoints" && mkdir -p "$CP_DIR"
|
|
100
100
|
|
|
101
101
|
# Build the mechanical checkpoint body
|
|
102
102
|
TS_FILE=$(date +%Y-%m-%d-%H%M)
|
|
@@ -160,7 +160,7 @@ GIT_LOG=$(cd "$PROJECT_DIR" && git log --oneline -5 2>/dev/null)
|
|
|
160
160
|
fi
|
|
161
161
|
} > "$CP_FILE"
|
|
162
162
|
|
|
163
|
-
# Update latest.md so /restore picks it up
|
|
163
|
+
# Update latest.md so /session restore picks it up
|
|
164
164
|
cp "$CP_FILE" "$CP_DIR/latest.md" 2>/dev/null
|
|
165
165
|
echo "$NOW" > "$LAST_CP_FILE"
|
|
166
166
|
|