@caddis/cli 0.4.55 → 0.4.57
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/bundles/antigravity-plugin/caddis_statusline.py +7 -3
- package/bundles/antigravity-plugin/guard_agy.py +1056 -83
- package/bundles/antigravity-plugin/hooks.json +2 -1
- package/bundles/antigravity-plugin/plugin.json +1 -1
- package/bundles/antigravity-plugin/repo_freshness.py +182 -4
- package/bundles/antigravity-plugin/scripts/caddis_adhoc.py +20 -12
- package/bundles/antigravity-plugin/scripts/caddis_checkout_guard.py +63 -12
- package/bundles/antigravity-plugin/scripts/caddis_docs_pr.py +14 -5
- package/bundles/antigravity-plugin/scripts/caddis_gate.py +27 -1
- package/bundles/antigravity-plugin/scripts/caddis_lanes.py +93 -6
- package/bundles/antigravity-plugin/scripts/caddis_merge_chain.py +67 -22
- package/bundles/antigravity-plugin/scripts/caddis_relay_git.py +8 -2
- package/bundles/antigravity-plugin/scripts/caddis_review.py +290 -176
- package/bundles/antigravity-plugin/scripts/caddis_roadmap.py +346 -50
- package/bundles/antigravity-plugin/scripts/caddis_roadmap_page.py +82 -8
- package/bundles/antigravity-plugin/scripts/caddis_roadmap_run.py +89 -24
- package/bundles/antigravity-plugin/scripts/caddis_statusline.py +7 -3
- package/bundles/antigravity-plugin/scripts/caddis_tidy.py +10 -6
- package/bundles/antigravity-plugin/scripts/caddis_todo.py +7 -1
- package/bundles/antigravity-plugin/scripts/caddis_worktree_close.py +12 -5
- package/bundles/antigravity-plugin/scripts/caddis_worktree_safety.py +182 -0
- package/bundles/antigravity-plugin/scripts/check_doc_coverage.py +2 -0
- package/bundles/antigravity-plugin/scripts/claudster_doctor.py +6 -2
- package/bundles/antigravity-plugin/scripts/no_window.py +49 -0
- package/bundles/antigravity-plugin/scripts/oss_review.py +303 -79
- package/bundles/antigravity-plugin/scripts/secret_filter.py +190 -22
- package/bundles/antigravity-plugin/scripts/setup_project_ai.py +6 -1
- package/bundles/antigravity-plugin/session_end_agy.py +27 -11
- package/bundles/antigravity-plugin/skills/cloud-phases/SKILL.md +55 -9
- package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +11 -8
- package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +1 -1
- package/bundles/antigravity-plugin/skills/gh-cli/SKILL.md +10 -6
- package/bundles/antigravity-plugin/skills/git-commit/SKILL.md +2 -3
- package/bundles/antigravity-plugin/skills/implement/SKILL.md +31 -17
- package/bundles/antigravity-plugin/skills/mmr/SKILL.md +1 -1
- package/bundles/antigravity-plugin/skills/pr-merge/SKILL.md +45 -5
- package/bundles/antigravity-plugin/skills/refactoring/SKILL.md +4 -2
- package/bundles/antigravity-plugin/skills/review-pr/SKILL.md +13 -4
- package/bundles/antigravity-plugin/skills/roadmap/SKILL.md +28 -6
- package/bundles/antigravity-plugin/skills/roadmap/assets/review-protocol.md +16 -13
- package/bundles/antigravity-plugin/skills/ship/SKILL.md +32 -10
- package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +32 -1
- package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +44 -6
- package/bundles/antigravity-plugin/skills/writing-plans/SKILL.md +1 -1
- package/bundles/antigravity-plugin/warm_start_agy.py +40 -16
- package/bundles/antigravity-plugin-extras/plugin.json +1 -1
- package/bundles/antigravity-plugin-extras/skills/agent-orchestration/SKILL.md +5 -5
- package/bundles/antigravity-plugin-extras/skills/cross-review/SKILL.md +1 -1
- package/bundles/antigravity-plugin-extras/skills/deploy-local/SKILL.md +2 -1
- package/bundles/antigravity-plugin-extras/skills/update-readme/SKILL.md +1 -1
- package/bundles/codex/.codex/skills/coding/refactoring/SKILL.md +4 -2
- package/bundles/codex/.codex/skills/devops/gh-cli/SKILL.md +10 -6
- package/bundles/codex/.codex/skills/devops/git-commit/SKILL.md +2 -3
- package/bundles/codex/.codex/skills/docs/writing-plans/SKILL.md +1 -1
- package/bundles/codex/.codex/skills/workflow/roadmap/SKILL.md +28 -6
- package/bundles/codex/.codex/skills/workflow/roadmap/assets/review-protocol.md +16 -13
- package/bundles/manifest.json +3 -3
- package/package.json +1 -1
|
@@ -28,6 +28,19 @@ import os
|
|
|
28
28
|
import subprocess
|
|
29
29
|
import sys
|
|
30
30
|
|
|
31
|
+
# No child process of this hook opens a console window on Windows (scripts/no_window.py). agy hooks ship
|
|
32
|
+
# FLAT at the plugin root with scripts/ beside them; in the source repo scripts/ is one level up.
|
|
33
|
+
try:
|
|
34
|
+
_nw_here = os.path.dirname(os.path.abspath(__file__))
|
|
35
|
+
for _nw_cand in (os.path.join(_nw_here, "scripts"), os.path.join(os.path.dirname(_nw_here), "scripts")):
|
|
36
|
+
if os.path.isfile(os.path.join(_nw_cand, "no_window.py")):
|
|
37
|
+
if _nw_cand not in sys.path:
|
|
38
|
+
sys.path.insert(0, _nw_cand)
|
|
39
|
+
break
|
|
40
|
+
from no_window import NO_WINDOW_KW # noqa: E402
|
|
41
|
+
except Exception: # pragma: no cover - defensive
|
|
42
|
+
NO_WINDOW_KW = {"creationflags": 0x08000000} if os.name == "nt" else {}
|
|
43
|
+
|
|
31
44
|
_ARTIFACT_DIRS = (".caddis",)
|
|
32
45
|
|
|
33
46
|
INJECT_MAX_LINES = 120 # same budget as the Claude Code hook
|
|
@@ -151,7 +164,7 @@ def resolve_relay(root: str, session_id: str = "") -> tuple[str, str | None]:
|
|
|
151
164
|
try:
|
|
152
165
|
branch = subprocess.run(
|
|
153
166
|
["git", "-C", root, "rev-parse", "--abbrev-ref", "HEAD"],
|
|
154
|
-
capture_output=True, text=True, timeout=3,
|
|
167
|
+
capture_output=True, text=True, timeout=3, **NO_WINDOW_KW,
|
|
155
168
|
).stdout.strip()
|
|
156
169
|
except Exception:
|
|
157
170
|
branch = ""
|
|
@@ -232,23 +245,32 @@ def _hook_note(feature, exc, root=None):
|
|
|
232
245
|
|
|
233
246
|
|
|
234
247
|
|
|
235
|
-
def
|
|
236
|
-
""
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
248
|
+
def _safe_conversation(conversation):
|
|
249
|
+
return "".join(c for c in str(conversation) if c.isalnum() or c in "-_")[:64]
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _injected_markers(root, conversation):
|
|
253
|
+
"""Where the "relay already injected" marker for this conversation may be: (repo marker, temp marker).
|
|
254
|
+
|
|
255
|
+
The repo marker lives in `.caddis/.relay-injected/`. The temp marker lives in the user's temp
|
|
256
|
+
folder, keyed by the repo path, for a repo that has no `.caddis/` (the hook must not create one).
|
|
257
|
+
"""
|
|
258
|
+
safe = _safe_conversation(conversation)
|
|
259
|
+
if not safe:
|
|
260
|
+
return None, None
|
|
261
|
+
import hashlib
|
|
262
|
+
import tempfile
|
|
263
|
+
repo_marker = os.path.join(str(root), ".caddis", ".relay-injected", safe)
|
|
264
|
+
key = hashlib.sha1(os.path.normcase(os.path.abspath(str(root))).encode("utf-8", "replace")).hexdigest()[:16]
|
|
265
|
+
temp_marker = os.path.join(tempfile.gettempdir(), "caddis-relay-injected", key + "-" + safe)
|
|
266
|
+
return repo_marker, temp_marker
|
|
244
267
|
|
|
245
268
|
|
|
246
269
|
def _already_injected(root, conversation):
|
|
247
270
|
"""True when this conversation has had its relay injected before. Fail-open: on any
|
|
248
271
|
error return False, because a duplicate relay is a smaller harm than none at all."""
|
|
249
272
|
try:
|
|
250
|
-
|
|
251
|
-
return bool(marker) and os.path.isfile(marker)
|
|
273
|
+
return any(m and os.path.isfile(m) for m in _injected_markers(root, conversation))
|
|
252
274
|
except Exception:
|
|
253
275
|
return False
|
|
254
276
|
|
|
@@ -256,13 +278,15 @@ def _already_injected(root, conversation):
|
|
|
256
278
|
def _mark_injected(root, conversation):
|
|
257
279
|
"""Record that this conversation received its relay. Never raises.
|
|
258
280
|
|
|
259
|
-
|
|
260
|
-
|
|
281
|
+
The marker goes in `.caddis/` when the repo already has it, else in the user's temp folder:
|
|
282
|
+
this hook never creates `.caddis/` in a repo that did not opt in. A failure here means the
|
|
283
|
+
next truncation may re-inject, which is the fail-open direction we want.
|
|
261
284
|
"""
|
|
262
285
|
try:
|
|
263
|
-
|
|
264
|
-
if not
|
|
286
|
+
repo_marker, temp_marker = _injected_markers(root, conversation)
|
|
287
|
+
if not repo_marker:
|
|
265
288
|
return
|
|
289
|
+
marker = repo_marker if os.path.isdir(os.path.join(str(root), ".caddis")) else temp_marker
|
|
266
290
|
os.makedirs(os.path.dirname(marker), exist_ok=True)
|
|
267
291
|
with open(marker, "w", encoding="utf-8") as fh:
|
|
268
292
|
fh.write("")
|
|
@@ -128,7 +128,7 @@ Spec Input
|
|
|
128
128
|
2. Categorise every item by effort (H = hours, D = days) and value (high / medium / low)
|
|
129
129
|
3. Items that are **≤ 1 hour AND high-value** become quick wins (H1, H2, H3…)
|
|
130
130
|
4. Implement quick wins in a single session
|
|
131
|
-
5. Run
|
|
131
|
+
5. Run the tests of the touched files in the foreground (each command under 10 minutes) — all must pass. CI runs the full suite
|
|
132
132
|
6. Commit: `feat: H1–H3 quick wins — <summary>`
|
|
133
133
|
|
|
134
134
|
**Decision Gate:**
|
|
@@ -266,10 +266,10 @@ Score each identified risk:
|
|
|
266
266
|
2. Provide the phase prompt:
|
|
267
267
|
```
|
|
268
268
|
Read .caddis/plans/<feature>.md and implement Phase N.
|
|
269
|
-
Run
|
|
269
|
+
Run the tests of the files you changed, in the foreground, each command under 10 minutes. They must pass before commit. CI runs the full suite.
|
|
270
270
|
```
|
|
271
271
|
3. Implement Agent reads the plan, executes numbered steps
|
|
272
|
-
4. After implementation: run full
|
|
272
|
+
4. After implementation: run the tests of the touched files in the foreground (each command under 10 minutes). CI runs the full suite
|
|
273
273
|
5. If tests pass → commit: `feat(<scope>): phase N — <summary>`
|
|
274
274
|
6. If tests fail → fix within the same session before committing
|
|
275
275
|
|
|
@@ -340,7 +340,7 @@ The plan document should contain **copy-paste prompts** for each phase. This rem
|
|
|
340
340
|
- Acceptance criteria
|
|
341
341
|
3. **Write fix-up plan** — Place in `.caddis/plans/<feature>-fixup.md`
|
|
342
342
|
4. **Execute** — Implement Agent works through issues sequentially
|
|
343
|
-
5. **Verify** — Run
|
|
343
|
+
5. **Verify** — Run the tests of the touched files (foreground, each command under 10 minutes) + visual inspection. CI runs the full suite
|
|
344
344
|
6. **Commit** — `fix(<scope>): post-track cross-component polish`
|
|
345
345
|
|
|
346
346
|
**Example from practice:**
|
|
@@ -610,7 +610,7 @@ Every stage that produces code changes should result in a commit:
|
|
|
610
610
|
A well-orchestrated session should produce:
|
|
611
611
|
|
|
612
612
|
- [ ] **Traceability** — Every spec requirement maps to a plan step, which maps to a commit
|
|
613
|
-
- [ ] **Green tests** —
|
|
613
|
+
- [ ] **Green tests** — Touched-file tests pass before every commit; CI runs the full suite on every PR
|
|
614
614
|
- [ ] **Clean plan** — Fidelity audit: 0 gaps
|
|
615
615
|
- [ ] **Managed risks** — No showstoppers unresolved
|
|
616
616
|
- [ ] **Minimal rework** — Debug pass finds cosmetic issues, not fundamental errors
|
|
@@ -95,7 +95,7 @@ smaller chunks; don't just raise `--max-diff-chars` without knowing the endpoint
|
|
|
95
95
|
|
|
96
96
|
## Three rules: one attempt, one review
|
|
97
97
|
1. **Think before you send.** Before a task goes to any coder, write its edge cases and check the facts it depends on (one query or one file read).
|
|
98
|
-
2. **Run it before review.** The coder runs the
|
|
98
|
+
2. **Run it before review.** The coder runs only the tests of the files it touched, in the foreground, each command under 10 minutes (split into parts if needed). Name the exact commands in the task. Never start the full suite in the background and never wait on a monitor for it: CI runs the full suite on every PR. Then run the change once on real data.
|
|
99
99
|
3. **Review by tier.** Run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-tier --range <base>...HEAD` (add `--plan <plan> --phase <N>` inside a plan; no `TIER:` line means tier 2).
|
|
100
100
|
Tier 0: gates only. Tier 1-small: your self-check only. Tier 1: one review by another vendor; stop at
|
|
101
101
|
the first CLEAN. Tier 2: two reviewers of two other vendors, in one round. Fix blocking findings only;
|
|
@@ -80,7 +80,8 @@ Example:
|
|
|
80
80
|
```powershell
|
|
81
81
|
git status --short
|
|
82
82
|
git add <files>
|
|
83
|
-
git
|
|
83
|
+
git diff --cached --name-only # only <files>; else stop and report
|
|
84
|
+
git commit -m "fix(ci): resolve deploy health check" -- <files>
|
|
84
85
|
git push origin main
|
|
85
86
|
git rev-parse HEAD
|
|
86
87
|
```
|
|
@@ -54,7 +54,7 @@ Use this skill when users ask to:
|
|
|
54
54
|
### Phase 4 — Stage only README changes for docs commit
|
|
55
55
|
|
|
56
56
|
1. Stage README files only:
|
|
57
|
-
- `git add README.md
|
|
57
|
+
- `git add README.md <each changed README by path>` (no `**` pattern: the guard denies it)
|
|
58
58
|
2. Verify staged diff contains no non-README files.
|
|
59
59
|
3. Suggested conventional commit:
|
|
60
60
|
- `docs(readme): document <feature summary>`
|
|
@@ -128,7 +128,8 @@ Activate when:
|
|
|
128
128
|
```bash
|
|
129
129
|
git status --short # stage the files you changed, by name
|
|
130
130
|
git add tests/test_<module>.py
|
|
131
|
-
git
|
|
131
|
+
git diff --cached --name-only # only the files you named
|
|
132
|
+
git commit -m "chore: add tests before refactoring" -- tests/test_<module>.py
|
|
132
133
|
```
|
|
133
134
|
|
|
134
135
|
---
|
|
@@ -387,7 +388,8 @@ DEPRECATED_VALUE = 5 # Not referenced
|
|
|
387
388
|
|
|
388
389
|
2. **If tests pass, commit**
|
|
389
390
|
```bash
|
|
390
|
-
git
|
|
391
|
+
git add <files you changed>
|
|
392
|
+
git commit -m "refactor: extract validation to separate method" -- <files you changed>
|
|
391
393
|
```
|
|
392
394
|
|
|
393
395
|
3. **If tests fail, revert**
|
|
@@ -73,7 +73,10 @@ gh pr diff 55
|
|
|
73
73
|
gh pr checkout 55
|
|
74
74
|
gh pr review 55 --approve --body "LGTM!"
|
|
75
75
|
gh pr review 55 --request-changes --body "Please fix error handling"
|
|
76
|
-
|
|
76
|
+
# merge only on ci-watch RESULT: pass, only its HEAD:, with no default-branch run in progress
|
|
77
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_lanes.py" ci-watch --pr 55
|
|
78
|
+
gh run list --branch main --json status # no in_progress or queued run (main = the default branch)
|
|
79
|
+
gh pr merge 55 --squash --delete-branch --match-head-commit <watched head>
|
|
77
80
|
|
|
78
81
|
# Manage
|
|
79
82
|
gh pr ready 55 # Mark draft as ready
|
|
@@ -168,10 +171,11 @@ gh alias set review 'pr list --search "review-requested:@me"'
|
|
|
168
171
|
```bash
|
|
169
172
|
gh issue develop 42 --branch fix/issue-42
|
|
170
173
|
git add src/auth/login.py tests/test_login.py # named files only, never `git add .`
|
|
171
|
-
git commit -m "fix: resolve login bug" && git push -u origin HEAD
|
|
174
|
+
git commit -m "fix: resolve login bug" -- src/auth/login.py tests/test_login.py && git push -u origin HEAD
|
|
172
175
|
gh pr create --title "fix: resolve login bug" --body "Closes #42"
|
|
173
|
-
|
|
174
|
-
gh
|
|
176
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_lanes.py" ci-watch --pr <n> # RESULT: pass, HEAD: <watched head>
|
|
177
|
+
gh run list --branch main --json status # wait while a default-branch run is in progress
|
|
178
|
+
gh pr merge <n> --squash --delete-branch --match-head-commit <watched head>
|
|
175
179
|
```
|
|
176
180
|
|
|
177
181
|
### Release Workflow
|
|
@@ -189,8 +193,8 @@ gh release upload v1.3.0 ./dist/*.tar.gz
|
|
|
189
193
|
| Create repo | `gh repo create name --public` |
|
|
190
194
|
| Create issue | `gh issue create --title "..." --labels bug` |
|
|
191
195
|
| Create PR | `gh pr create --title "..." --reviewer user` |
|
|
192
|
-
| Merge PR | `gh pr merge 55 --squash --delete-branch`
|
|
196
|
+
| Merge PR | `gh pr merge 55 --squash --delete-branch --match-head-commit <watched head>`, only after ci-watch `RESULT: pass` |
|
|
193
197
|
| Create release | `gh release create v1.0.0 --generate-notes` |
|
|
194
|
-
| Watch CI | `gh run watch`
|
|
198
|
+
| Watch CI | `caddis_lanes.py ci-watch --pr 55` (fallback: `gh run watch`) |
|
|
195
199
|
| Set secret | `echo "val" \| gh secret set KEY` |
|
|
196
200
|
| API call | `gh api /repos/o/r --jq '.description'` |
|
|
@@ -87,9 +87,8 @@ Optional area of change:
|
|
|
87
87
|
# Stage specific files
|
|
88
88
|
git add path/to/file1 path/to/file2
|
|
89
89
|
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
git add src/components/*
|
|
90
|
+
# Never stage by pattern or folder (`*.test.*`, `src/components/`): a pattern also takes
|
|
91
|
+
# files you did not change, and the caddis guard denies it. Name each file.
|
|
93
92
|
```
|
|
94
93
|
|
|
95
94
|
**Never stage secrets** (`.env`, `credentials.json`, private keys).
|
|
@@ -89,8 +89,26 @@ python scripts/caddis_roadmap.py recheck --roadmap <slug>
|
|
|
89
89
|
`Depends on` milestone `done` or `not-needed`, and no open blocker other than `data-condition` (exit 1 names it),
|
|
90
90
|
then runs the Exit check (300 s): pass -> `done`; fail with a `data-condition` blocker -> `code-done/data-pending`;
|
|
91
91
|
fail otherwise -> an `external` blocker
|
|
92
|
-
`exit check failing (exit <n>)
|
|
93
|
-
|
|
92
|
+
`exit check failing (exit <n>): <tail>` (the last 3 non-empty output lines on one line, the whole reason at most
|
|
93
|
+
200 characters, masked as below). The part before `: ` is the blocker's identity: a later rollup adds no second
|
|
94
|
+
row, and `unblock --reason "exit check failing (exit <n>)"` removes every row of that prefix. A check that fails
|
|
95
|
+
on a missing environment (exit 9009/127/126, or output in its last 40 lines such as `No module named`,
|
|
96
|
+
`Cannot find module`, `ENOENT`, `run npm run build first`) is exit 3: no blocker, no PR. Either way the last 64 KB
|
|
97
|
+
of output (masked the same way) go to `.local/exit-check-<id>-<utc>.log` (the newest 10 stay), and rollup prints
|
|
98
|
+
the path. A milestone with no phase refs and no Exit check is refused (exit 4).
|
|
99
|
+
**Masked** in the reason and the log: the values of secret-named variables (`caddis_redact`); a whole
|
|
100
|
+
`-----BEGIN ... PRIVATE KEY-----` block up to its END line (or the end of the output); AWS, GitHub, Slack and JWT
|
|
101
|
+
tokens; a quoted value after a `password`/`secret`/`api_key`/`token` name, spaces included; an unquoted
|
|
102
|
+
`*PASSWORD*=`/`*TOKEN*=`-style line value; URL credentials (`scheme://***@`); and absolute paths as `<path>`: a
|
|
103
|
+
drive or UNC path up to the end of the line, a quote, `<`, `>` or `|`, and a `/home/`, `/Users/`, `/tmp/`, `/root/`,
|
|
104
|
+
`/var/`, `/etc/` or `/opt/` path up to the end of the line or a quote. Other text is published as printed.
|
|
105
|
+
- **`**Exit setup:** <command>`** (optional, one per roadmap, beside `Runner host:`; no `|`) runs in the temp worktree
|
|
106
|
+
before every Exit check (900 s). It must install fresh into that worktree, for example
|
|
107
|
+
`python -m venv .venv && .venv\Scripts\pip install -e .[dev]` or `npm ci && npm run build`. Each command runs in a
|
|
108
|
+
new shell, so the Exit check must call the venv itself: `.venv\Scripts\python -m pytest tests -q`, not
|
|
109
|
+
`python -m pytest`. Never link or junction a shared venv or `node_modules`: the worktree is removed with `--force`
|
|
110
|
+
after the check. A setup that fails or times out is exit 3 and writes nothing; the runner stops
|
|
111
|
+
`BLOCKED rollup not run` and the owner decides (the stop names a docs PR that was opened but not merged).
|
|
94
112
|
- **Owner-only changes:** `set` Status `not-needed`, any `set` Owner, `unblock` of an `owner-gate`, and `block --check`
|
|
95
113
|
(recheck runs that command unattended later). They need `--by-owner` and are refused headless: `CADDIS_HEADLESS`
|
|
96
114
|
or `CLAUDECODE` in the environment (even empty), stdin not a terminal, or on
|
|
@@ -179,8 +197,8 @@ Stops (each one notifies and releases the lock): a STOP file (`~/.caddis/STOP` o
|
|
|
179
197
|
`caddis_spend.py` still counts across runs), a lock or batch claim that cannot be written
|
|
180
198
|
(`BLOCKED claim not written`, before any session), the agy spend cap refusing a reservation, three sessions
|
|
181
199
|
with no newly merged phase, a roadmap write that fails, and the **snapshot guard**: one baseline for the whole run.
|
|
182
|
-
The Milestones and Blockers tables (every cell of every row, rows added, removed or moved)
|
|
183
|
-
are frozen. Every origin read (each `next`, after the runner's own writes, after each session) is compared with the
|
|
200
|
+
The Milestones and Blockers tables (every cell of every row, rows added, removed or moved), the `Runner host` line
|
|
201
|
+
and the `**Exit setup:**` line are frozen. Every origin read (each `next`, after the runner's own writes, after each session) is compared with the
|
|
184
202
|
previous one; the only differences allowed are the exact edits the runner itself made and recorded for that read: a
|
|
185
203
|
Status it set, a blocker row it added, and what a rollup's audit entry (`changes.jsonl`) says it actually wrote.
|
|
186
204
|
Anything else stops the run `FAILED roadmap changed`.
|
|
@@ -206,7 +224,10 @@ refuses a plan that a roadmap lock names, at start and before every session. `-D
|
|
|
206
224
|
the session command, the worktree and any pending rollup, skips the host check, writes no files and starts nothing; it
|
|
207
225
|
does run `git fetch`, which updates the remote-tracking refs. `-GhAccount <login>` (recorded in the launch options,
|
|
208
226
|
passed on by the recheck task and in the printed task) makes every gh call of the runner and of `--last-stop` use
|
|
209
|
-
GH_TOKEN from `gh auth token -u <login>`; on a machine with several gh logins, give the repo's account.
|
|
227
|
+
GH_TOKEN from `gh auth token -u <login>`; on a machine with several gh logins, give the repo's account. The sessions
|
|
228
|
+
never get that token, nor GH_TOKEN, GITHUB_TOKEN, GH_ENTERPRISE_TOKEN, NPM_TOKEN or NODE_AUTH_TOKEN from the
|
|
229
|
+
environment; with CADDIS_HEADLESS=1 the guard denies `git push`, `gh pr merge|create`, `gh release`, a write through
|
|
230
|
+
`gh api`, `gh workflow run` and package publishes. Only the runner publishes. A gh call that
|
|
210
231
|
cannot answer (gh missing, 401, 404) is an error, never "not merged": the run stops
|
|
211
232
|
`BLOCKED gh cannot see <repo> with account <login>`, notified and recorded.
|
|
212
233
|
|
|
@@ -223,7 +244,8 @@ phases) holds the whole plan for every other roadmap and for plan mode. At the t
|
|
|
223
244
|
every milestone that waits only for its rollup (Status not finished, every phase merged, and the same rule as
|
|
224
245
|
`next`: no blocker, dependencies finished, Owner the runner); `--last-stop` says `rollup-ready:` for such a milestone,
|
|
225
246
|
so recheck restarts the runner. A sweep rollup that writes nothing stops `BLOCKED rollup of <id> wrote nothing`
|
|
226
|
-
(recorded, not restartable) and is not retried or reported until the roadmap changes.
|
|
247
|
+
(recorded, not restartable) and is not retried or reported until the roadmap changes. A rollup that exits 3 (its
|
|
248
|
+
exit check or Exit setup could not run) stops `BLOCKED rollup not run: <id> ...` (not restartable; the owner decides). The dry run lists them first. If
|
|
227
249
|
the owner edits the roadmap during a merge wait, the restart stops `FAILED roadmap changed ...` and names the
|
|
228
250
|
recovery: `roadmap-run.ps1 -Roadmap <slug> -AcceptRoadmap` (owner only, refused headless) takes the runner lock (a live
|
|
229
251
|
runner refuses it), prints the diff from the published baseline, asks you to type `accept` (or `--yes`), and accepts
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
type: reference
|
|
3
3
|
title: Review protocol
|
|
4
|
-
description: The review method one model can rely on - invariants, inputs and writers, shared state,
|
|
4
|
+
description: The review method one model can rely on - invariants, inputs and writers, shared state, check what the change promises, tests, docs, then severity (only blocking stops the merge; each finding needs a reproduction), one FINDING line per finding and an END REVIEW line. caddis_review.py sends it to every review run.
|
|
5
5
|
status: current
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Review protocol (generic, any diff)
|
|
9
9
|
|
|
10
|
-
You review a diff. You
|
|
11
|
-
|
|
12
|
-
first finding. Include a short section per step, in order.
|
|
10
|
+
You review a diff. You read only: you have Read, Grep and Glob and no shell, so you run no test and no command, and
|
|
11
|
+
you do not edit, create or delete files. The diff is in the prompt. Tests are the implementer's and CI's job. Work
|
|
12
|
+
through ALL steps in order. Do not stop at the first finding. Include a short section per step, in order.
|
|
13
13
|
|
|
14
14
|
## Step 1 - Purpose and invariants
|
|
15
15
|
Read the card, the plan or design section it cites, and the diff. Write the list of INVARIANTS this change must keep:
|
|
@@ -26,12 +26,14 @@ accident or on purpose? This includes the agent or session the code is meant to
|
|
|
26
26
|
List state that two runs, two kinds of target, or two processes could share (files, locks, relays, logs, caches).
|
|
27
27
|
Can they collide? Can one read the other's output as its own?
|
|
28
28
|
|
|
29
|
-
## Step 4 -
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
and
|
|
33
|
-
with a real payload). Compare risky behaviour with the
|
|
34
|
-
something. Report any that fail or that cannot work as
|
|
29
|
+
## Step 4 - Check what the change promises
|
|
30
|
+
For every command that the plan, its exit gates, the docs or the skill text say should work for this change (the
|
|
31
|
+
documented usage lines, exactly as written), follow it through the code by reading: the argument parsing, the paths it
|
|
32
|
+
reads and writes, the repo's OWN fixtures and example files. Read unattended scripts (hooks, runners) as they are
|
|
33
|
+
really run (as a script, with a real payload). Compare risky behaviour with the code before the change (the `-` lines
|
|
34
|
+
of the diff) when the change claims to fix or tighten something. Report any that would fail or that cannot work as
|
|
35
|
+
documented. For a check you cannot settle by reading, write one line `not executed: <command> (reviewer has no
|
|
36
|
+
shell)`.
|
|
35
37
|
|
|
36
38
|
## Step 5 - Tests
|
|
37
39
|
For each new or changed test: could it pass for the wrong reason (no assertion that can fail, mocked away the thing
|
|
@@ -52,9 +54,10 @@ Severity rule. Only **blocking** stops the merge, so use it with care:
|
|
|
52
54
|
negative test, a doc that is wrong in a way that does not make a command fail, an error message that misleads.
|
|
53
55
|
- **nit** = style and wording.
|
|
54
56
|
|
|
55
|
-
Every finding needs a concrete reproduction: a command, an input or a test that
|
|
56
|
-
failure scenario. A finding without a reproduction is a **nit**,
|
|
57
|
-
write "might", "could in theory" or "a future change may": show it
|
|
57
|
+
Every finding needs a concrete reproduction: a command, an input or a test that would show the failure, written in
|
|
58
|
+
the failure scenario (you do not run it; the implementer does). A finding without a reproduction is a **nit**,
|
|
59
|
+
whatever its severity would otherwise be. Do not write "might", "could in theory" or "a future change may": show it
|
|
60
|
+
or call it a nit.
|
|
58
61
|
|
|
59
62
|
The gate exits by the findings. A **blocking** finding fails it. **should-fix** and **nit** findings do not: they are
|
|
60
63
|
listed in the report under "Follow-up (not blocking)". The tool allows 3 completed review rounds for a phase; the 4th completed round
|
package/bundles/manifest.json
CHANGED
package/package.json
CHANGED