@caddis/cli 0.4.51 → 0.4.53
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-GLOSSARY.md +1 -0
- package/bundles/antigravity-plugin/plugin.json +1 -1
- package/bundles/antigravity-plugin/repo_freshness.py +132 -5
- package/bundles/antigravity-plugin/scripts/caddis_checkout_guard.py +223 -0
- package/bundles/antigravity-plugin/scripts/caddis_docs_pr.py +284 -0
- package/bundles/antigravity-plugin/scripts/caddis_exit.py +2 -0
- package/bundles/antigravity-plugin/scripts/caddis_frontmatter.py +1 -0
- package/bundles/antigravity-plugin/scripts/caddis_gate.py +226 -195
- package/bundles/antigravity-plugin/scripts/caddis_glossary.py +3 -3
- package/bundles/antigravity-plugin/scripts/caddis_governor.py +48 -4
- package/bundles/antigravity-plugin/scripts/caddis_inventory.py +38 -0
- package/bundles/antigravity-plugin/scripts/caddis_lanes.py +294 -127
- package/bundles/antigravity-plugin/scripts/caddis_lineage_publish.py +458 -0
- package/bundles/antigravity-plugin/scripts/caddis_merge_chain.py +237 -0
- package/bundles/antigravity-plugin/scripts/caddis_notify.py +121 -0
- package/bundles/antigravity-plugin/scripts/caddis_prod_check.py +380 -0
- package/bundles/antigravity-plugin/scripts/caddis_redact.py +99 -0
- package/bundles/antigravity-plugin/scripts/caddis_relay_git.py +2 -2
- package/bundles/antigravity-plugin/scripts/caddis_review.py +1309 -0
- package/bundles/antigravity-plugin/scripts/caddis_roadmap.py +2056 -0
- package/bundles/antigravity-plugin/scripts/caddis_roadmap_run.py +2572 -0
- package/bundles/antigravity-plugin/scripts/caddis_routing.py +3 -2
- package/bundles/antigravity-plugin/scripts/caddis_rows.py +476 -0
- package/bundles/antigravity-plugin/scripts/caddis_spawn.py +8 -9
- package/bundles/antigravity-plugin/scripts/caddis_spend.py +415 -0
- package/bundles/antigravity-plugin/scripts/caddis_tidy.py +357 -20
- package/bundles/antigravity-plugin/scripts/caddis_todo.py +55 -0
- package/bundles/antigravity-plugin/scripts/caddis_workstreams.py +178 -19
- package/bundles/antigravity-plugin/scripts/caddis_worktree_close.py +349 -0
- package/bundles/antigravity-plugin/scripts/check_doc_coverage.py +0 -56
- package/bundles/antigravity-plugin/scripts/claudster_doctor.py +1 -1
- package/bundles/antigravity-plugin/scripts/enforcement_inventory.py +0 -1
- package/bundles/antigravity-plugin/scripts/oss_review.py +2 -2
- package/bundles/antigravity-plugin/scripts/roadmap-recheck.ps1 +89 -0
- package/bundles/antigravity-plugin/scripts/roadmap-run.ps1 +88 -0
- package/bundles/antigravity-plugin/scripts/setup_project_ai.py +86 -2
- package/bundles/antigravity-plugin/session_end_agy.py +3 -3
- package/bundles/antigravity-plugin/skills/_registry.md +2 -6
- package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md +1 -1
- package/bundles/antigravity-plugin/skills/best-practices/agents/codebase-context-builder.md +1 -1
- package/bundles/antigravity-plugin/skills/best-practices/agents/task-intent-analyzer.md +1 -1
- package/bundles/antigravity-plugin/skills/catchup/SKILL.md +7 -0
- package/bundles/antigravity-plugin/skills/cloud-phases/SKILL.md +1 -1
- package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +5 -2
- package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +29 -83
- package/bundles/antigravity-plugin/skills/handoff/SKILL.md +77 -48
- package/bundles/antigravity-plugin/skills/implement/SKILL.md +87 -147
- package/bundles/antigravity-plugin/skills/migrate-dir/SKILL.md +1 -1
- package/bundles/antigravity-plugin/skills/mmr/SKILL.md +5 -2
- package/bundles/antigravity-plugin/skills/office-documents-official/SKILL.md +24 -0
- package/bundles/antigravity-plugin/skills/park/SKILL.md +0 -1
- package/bundles/antigravity-plugin/skills/pr-merge/SKILL.md +8 -14
- package/bundles/antigravity-plugin/skills/prd/SKILL.md +2 -10
- package/bundles/antigravity-plugin/skills/roadmap/SKILL.md +259 -0
- package/bundles/antigravity-plugin/skills/roadmap/assets/plan-resume-prompt.md +77 -0
- package/bundles/antigravity-plugin/skills/roadmap/assets/render-check.template.mjs +68 -0
- package/bundles/antigravity-plugin/skills/roadmap/assets/review-protocol.md +78 -0
- package/bundles/antigravity-plugin/skills/roadmap/assets/roadmap.template.md +32 -0
- package/bundles/antigravity-plugin/skills/roadmap/assets/value-check.template.py +161 -0
- package/bundles/antigravity-plugin/skills/ship/SKILL.md +14 -14
- package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +6 -0
- package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +33 -14
- package/bundles/antigravity-plugin/skills/spawn-session/SKILL.md +4 -8
- package/bundles/antigravity-plugin/warm_start_agy.py +1 -3
- package/bundles/antigravity-plugin-extras/plugin.json +1 -1
- package/bundles/antigravity-plugin-extras/skills/_registry.md +1 -2
- package/bundles/antigravity-plugin-extras/skills/agent-orchestration/SKILL.md +5 -5
- package/bundles/antigravity-plugin-extras/skills/cross-review/SKILL.md +5 -2
- package/bundles/antigravity-plugin-extras/skills/runner-move/SKILL.md +214 -0
- package/bundles/codex/.codex/skills/docs/office-documents-official/SKILL.md +24 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/agents/best-practices-referencer.md +1 -1
- package/bundles/codex/.codex/skills/workflow/best-practices/agents/codebase-context-builder.md +1 -1
- package/bundles/codex/.codex/skills/workflow/best-practices/agents/task-intent-analyzer.md +1 -1
- package/bundles/codex/.codex/skills/workflow/roadmap/SKILL.md +259 -0
- package/bundles/codex/.codex/skills/workflow/roadmap/assets/plan-resume-prompt.md +77 -0
- package/bundles/codex/.codex/skills/workflow/roadmap/assets/render-check.template.mjs +68 -0
- package/bundles/codex/.codex/skills/workflow/roadmap/assets/review-protocol.md +78 -0
- package/bundles/codex/.codex/skills/workflow/roadmap/assets/roadmap.template.md +32 -0
- package/bundles/codex/.codex/skills/workflow/roadmap/assets/value-check.template.py +161 -0
- package/bundles/codex/AGENTS.md +5 -4
- package/bundles/manifest.json +3 -3
- package/package.json +1 -1
- package/bundles/antigravity-plugin/skills/advisory-hub/SKILL.md +0 -233
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/context-template.md +0 -214
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/hub-handbook.md +0 -233
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/report-contract.md +0 -94
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/succession.md +0 -118
- package/bundles/antigravity-plugin/skills/resume/SKILL.md +0 -6
- package/bundles/antigravity-plugin/skills/review/SKILL.md +0 -6
- package/bundles/antigravity-plugin/skills/spawn-hub/SKILL.md +0 -341
- package/bundles/antigravity-plugin/skills/statusline/SKILL.md +0 -6
- package/bundles/antigravity-plugin/skills/validate-phase/SKILL.md +0 -143
- package/bundles/antigravity-plugin-extras/skills/data-lineage/SKILL.md +0 -158
- package/bundles/antigravity-plugin-extras/skills/data-lineage/scripts/convert_doc_to_confluence.py +0 -1430
- package/bundles/antigravity-plugin-extras/skills/golden-plan/SKILL.md +0 -586
- package/bundles/codex/.codex/skills/workflow/advisory-hub/SKILL.md +0 -233
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/context-template.md +0 -214
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/hub-handbook.md +0 -233
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/report-contract.md +0 -94
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/succession.md +0 -118
|
@@ -139,7 +139,6 @@ def _enforcer_for(rel_path: str, text: str) -> str | None:
|
|
|
139
139
|
GATE_SCRIPT = REPO / "scripts" / "caddis_gate.py"
|
|
140
140
|
GATE_CONCERNS = {
|
|
141
141
|
"lane-check": ("lane", "spawn", "launch command", "--print", "-p"),
|
|
142
|
-
"verdict-gate": ("verdict", "advisory-hub", "blocked-pending-hub", "accept-degraded"),
|
|
143
142
|
"tracker-vs-git": ("tracker",),
|
|
144
143
|
}
|
|
145
144
|
|
|
@@ -416,7 +416,7 @@ def current_branch(cwd: str) -> str:
|
|
|
416
416
|
|
|
417
417
|
def build_review_prompt(diff_text: str, branch: str, rng: str | None,
|
|
418
418
|
all_paths: list[str] | None = None) -> str:
|
|
419
|
-
"""Adversarial review prompt
|
|
419
|
+
"""Adversarial review prompt.
|
|
420
420
|
|
|
421
421
|
Self-contained: the criteria are inline so a real review always happens, and it ends with
|
|
422
422
|
a single machine-parseable verdict line the caller maps to an exit code.
|
|
@@ -570,7 +570,7 @@ def main(argv: list[str] | None = None, env: dict[str, str] | None = None) -> in
|
|
|
570
570
|
args = parser.parse_args(argv)
|
|
571
571
|
|
|
572
572
|
# --check-config is deliberately NON-INTERACTIVE. This script runs headless — from CI, from a
|
|
573
|
-
#
|
|
573
|
+
# runner, from a `claude -p` session — where a prompt on stdin does not ask a question,
|
|
574
574
|
# it hangs forever. The ASKING belongs in `/caddis:cross-review`, which is driven by an agent
|
|
575
575
|
# that can actually talk to a human. This half just answers "is it configured?" cheaply enough
|
|
576
576
|
# to call before you need it, instead of finding out mid-commit.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# roadmap-recheck - the scheduled task for one roadmap (caddis-next Phase 9). It starts
|
|
2
|
+
# `roadmap-run.ps1 -Roadmap <slug>` detached only when ALL of these hold, checked in this order:
|
|
3
|
+
# 1. `--last-stop` exits 0: the runner's last recorded stop is `BLOCKED nothing ready`, there is none, or one of
|
|
4
|
+
# these, each with its own line prefix: `merged:` (the waiting PR merged), `freed:` (the runners that held our
|
|
5
|
+
# batches are gone), `rollup-ready:` (a milestone waits only for its rollup); any FAILED stop
|
|
6
|
+
# (the snapshot guard, a crash), `running` (a killed run), a cap or a STOP file needs the owner, so it prints
|
|
7
|
+
# why and starts nothing;
|
|
8
|
+
# 2. the roadmap runner lock is absent or stale (`--lock-state`); a live lock starts and writes nothing;
|
|
9
|
+
# 3. `caddis_roadmap.py recheck` cleared a blocker (exit 0); in a `merged:`, `freed:` or `rollup-ready:` tick
|
|
10
|
+
# recheck is NOT run (the
|
|
11
|
+
# merge is the change, and a cleared blocker would change the roadmap the restart checks against its hash);
|
|
12
|
+
# 4. agy engine only (the recorded launch options): `caddis_spend.py check` exits 0.
|
|
13
|
+
# It restarts with the launch options the last run recorded (`--restart-args`: engine, model, caps), never the
|
|
14
|
+
# defaults. A run that holds the lock records the last stop `running`, so a run killed without a stop (a crash, a
|
|
15
|
+
# reboot) is never restarted here: it needs the owner.
|
|
16
|
+
# The owner registers it every 2 hours with the command that `roadmap-run.ps1 -Roadmap <slug> -PrintRecheckTask`
|
|
17
|
+
# prints. Every Python call here runs with CADDIS_HEADLESS=1, so no owner-only roadmap change can pass.
|
|
18
|
+
# Test seams: CADDIS_RECHECK_PYTHON (the interpreter) and CADDIS_RECHECK_SCRIPTS (the folder that holds
|
|
19
|
+
# caddis_roadmap.py, caddis_roadmap_run.py, caddis_spend.py and roadmap-run.ps1).
|
|
20
|
+
# Usage: roadmap-recheck.ps1 -Roadmap <slug> [-Repo <path>] [-GhAccount <gh login>]
|
|
21
|
+
# Exit: 0 started the runner, 1 nothing to start, 3 cannot run, 4 bad input.
|
|
22
|
+
param(
|
|
23
|
+
[string]$Roadmap = '',
|
|
24
|
+
[string]$Repo = (Get-Location).Path,
|
|
25
|
+
[string]$GhAccount = ''
|
|
26
|
+
)
|
|
27
|
+
$SlugRule = '^[a-z0-9][a-z0-9-]{0,62}$' # = caddis_roadmap.SLUG_RE_TEXT (a test keeps the three equal)
|
|
28
|
+
if ($Roadmap -cnotmatch $SlugRule) { Write-Error "roadmap-recheck: -Roadmap must match $SlugRule"; exit 4 }
|
|
29
|
+
$py = if ($env:CADDIS_RECHECK_PYTHON) { $env:CADDIS_RECHECK_PYTHON } else { (Get-Command python -ErrorAction SilentlyContinue).Source }
|
|
30
|
+
if (-not $py) { Write-Error "roadmap-recheck: python not found on PATH"; exit 3 }
|
|
31
|
+
$dirs = if ($env:CADDIS_RECHECK_SCRIPTS) { @($env:CADDIS_RECHECK_SCRIPTS) } else { @($PSScriptRoot, (Join-Path $PSScriptRoot '../../scripts')) }
|
|
32
|
+
function Find-Script([string]$name) {
|
|
33
|
+
foreach ($dir in $dirs) {
|
|
34
|
+
$p = Join-Path $dir $name
|
|
35
|
+
if (Test-Path $p) { return (Resolve-Path $p).Path }
|
|
36
|
+
}
|
|
37
|
+
return $null
|
|
38
|
+
}
|
|
39
|
+
$roadmapPy = Find-Script 'caddis_roadmap.py'
|
|
40
|
+
$runnerPy = Find-Script 'caddis_roadmap_run.py'
|
|
41
|
+
$spendPy = Find-Script 'caddis_spend.py'
|
|
42
|
+
$runPs1 = Find-Script 'roadmap-run.ps1'
|
|
43
|
+
if (-not ($roadmapPy -and $runnerPy -and $spendPy -and $runPs1)) {
|
|
44
|
+
Write-Error "roadmap-recheck: caddis_roadmap.py, caddis_roadmap_run.py, caddis_spend.py or roadmap-run.ps1 not found"
|
|
45
|
+
exit 4
|
|
46
|
+
}
|
|
47
|
+
$env:CADDIS_HEADLESS = '1' # inherited by every child below
|
|
48
|
+
# No trailing separator (a trailing `\` before a closing quote escapes it); a drive root keeps `X:\`.
|
|
49
|
+
$Repo = $Repo.TrimEnd('\', '/')
|
|
50
|
+
if ($Repo -match '^[A-Za-z]:$') { $Repo += '\' }
|
|
51
|
+
$repoArg = if ($Repo -match '\\$') { "$Repo\" } else { $Repo } # doubled in front of the closing quote
|
|
52
|
+
|
|
53
|
+
$ghArgs = if ($GhAccount) { @('--gh-account', $GhAccount) } else { @() }
|
|
54
|
+
$why = (& $py $runnerPy --roadmap $Roadmap --repo $Repo --last-stop @ghArgs) -join ' '
|
|
55
|
+
if ($LASTEXITCODE -ne 0) { Write-Output "roadmap-recheck: $why; runner not started"; exit 1 }
|
|
56
|
+
|
|
57
|
+
# A live lock: a runner is starting or running. Start nothing and WRITE nothing (no recheck either: a cleared
|
|
58
|
+
# blocker would change the roadmap under that runner's guard). `--last-stop` above only reads.
|
|
59
|
+
$state = & $py $runnerPy --roadmap $Roadmap --repo $Repo --lock-state
|
|
60
|
+
if ($LASTEXITCODE -ne 0) { Write-Output "roadmap-recheck: runner lock is $state; runner not started"; exit 1 }
|
|
61
|
+
|
|
62
|
+
$merged = $why -match '^(merged|freed|rollup-ready):' # merged PR, holder gone, or a milestone waits for its rollup
|
|
63
|
+
if (-not $merged) {
|
|
64
|
+
# Only after `BLOCKED nothing ready` (or no stop). Never in a `merged:` tick: clearing a blocker now would change
|
|
65
|
+
# the origin roadmap the restarted runner checks against the hash it recorded at publish time.
|
|
66
|
+
& $py $roadmapPy recheck --roadmap $Roadmap --root $Repo
|
|
67
|
+
$rc = $LASTEXITCODE
|
|
68
|
+
if ($rc -ne 0) { Write-Output "roadmap-recheck: no blocker cleared (recheck exit $rc); runner not started"; exit 1 }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
$options = @(& $py $runnerPy --roadmap $Roadmap --repo $Repo --restart-args | Where-Object { $_ -ne '' })
|
|
72
|
+
if ($LASTEXITCODE -ne 0) { Write-Output "roadmap-recheck: launch options not readable; runner not started"; exit 1 }
|
|
73
|
+
if ($GhAccount -and $options -notcontains '-GhAccount') { $options += @('-GhAccount', $GhAccount) }
|
|
74
|
+
|
|
75
|
+
# The global agy spend cap applies to the agy engine only (a claude run needs no spend-cap file).
|
|
76
|
+
$engineAt = [array]::IndexOf($options, '-Engine')
|
|
77
|
+
$engine = if ($engineAt -ge 0 -and $engineAt + 1 -lt $options.Count) { $options[$engineAt + 1] } else { 'claude' }
|
|
78
|
+
if ($engine -eq 'agy') {
|
|
79
|
+
& $py $spendPy check
|
|
80
|
+
if ($LASTEXITCODE -ne 0) { Write-Output "roadmap-recheck: spend check exit $LASTEXITCODE; runner not started"; exit 1 }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
$shell = (Get-Process -Id $PID).Path
|
|
84
|
+
$argv = @('-NoProfile', '-File', "`"$runPs1`"", '-Roadmap', $Roadmap, '-Repo', "`"$repoArg`"") + $options
|
|
85
|
+
$start = @{ FilePath = $shell; ArgumentList = $argv }
|
|
86
|
+
if ($IsWindows -or $env:OS -eq 'Windows_NT') { $start['WindowStyle'] = 'Hidden' }
|
|
87
|
+
Start-Process @start
|
|
88
|
+
Write-Output "roadmap-recheck: started roadmap-run.ps1 -Roadmap $Roadmap $($options -join ' ') (lock was $state)"
|
|
89
|
+
exit 0
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# roadmap-run - start one fresh headless session per batch, until a stop. A thin shim over caddis_roadmap_run.py
|
|
2
|
+
# (design: .caddis/plans/programme-method-design.md sections 8.2 and 8.5; caddis-next Phase 9).
|
|
3
|
+
# -Plan runs a plain plan (plan mode). -Roadmap runs the next batches of a roadmap on origin (roadmap mode). Give one.
|
|
4
|
+
# -PrintRecheckTask prints a PowerShell block (Register-ScheduledTask) that registers roadmap-recheck.ps1 every 2 hours;
|
|
5
|
+
# it registers nothing.
|
|
6
|
+
# Usage: roadmap-run.ps1 (-Plan <slug> | -Roadmap <slug>) [-Repo <path>] [-MaxHours 10] [-MaxSessions 12]
|
|
7
|
+
# [-SessionTimeoutMin 120] [-MaxUsdPerSession 25] [-MaxUsdTotal 150]
|
|
8
|
+
# [-Engine claude] [-Model opus] [-GhAccount <gh login>] [-DryRun]
|
|
9
|
+
# roadmap-run.ps1 -Roadmap <slug> [-Repo <path>] -PrintRecheckTask
|
|
10
|
+
# roadmap-run.ps1 -Roadmap <slug> [-Repo <path>] -AcceptRoadmap [-DryRun] [-Yes] (owner only: accept an owner
|
|
11
|
+
# edit made during
|
|
12
|
+
# a merge wait as the new baseline)
|
|
13
|
+
param(
|
|
14
|
+
[string]$Plan = '',
|
|
15
|
+
[string]$Roadmap = '',
|
|
16
|
+
[string]$Repo = (Get-Location).Path,
|
|
17
|
+
[double]$MaxHours = 10,
|
|
18
|
+
[int]$MaxSessions = 12,
|
|
19
|
+
[double]$SessionTimeoutMin = 120,
|
|
20
|
+
[double]$MaxUsdPerSession = 25,
|
|
21
|
+
[double]$MaxUsdTotal = 150,
|
|
22
|
+
[ValidateSet('claude', 'agy', 'codex')][string]$Engine = 'claude',
|
|
23
|
+
[string]$Model = '',
|
|
24
|
+
[switch]$DryRun,
|
|
25
|
+
[string]$GhAccount = '',
|
|
26
|
+
[switch]$PrintRecheckTask,
|
|
27
|
+
[switch]$AcceptRoadmap,
|
|
28
|
+
[switch]$Yes
|
|
29
|
+
)
|
|
30
|
+
if ([bool]$Plan -eq [bool]$Roadmap) { Write-Error "roadmap-run: give exactly one of -Plan <slug> and -Roadmap <slug>"; exit 4 }
|
|
31
|
+
$SlugRule = '^[a-z0-9][a-z0-9-]{0,62}$' # = caddis_roadmap.SLUG_RE_TEXT (a test keeps the three equal)
|
|
32
|
+
if ($GhAccount -and $GhAccount -notmatch '^[A-Za-z0-9._-]+$') {
|
|
33
|
+
Write-Error "roadmap-run: -GhAccount must be a gh login name (got '$GhAccount')"; exit 4
|
|
34
|
+
}
|
|
35
|
+
if ($Roadmap -and $Roadmap -cnotmatch $SlugRule) {
|
|
36
|
+
Write-Error "roadmap-run: -Roadmap must match $SlugRule (got '$Roadmap')"; exit 4
|
|
37
|
+
}
|
|
38
|
+
if ($PrintRecheckTask) {
|
|
39
|
+
if (-not $Roadmap) { Write-Error "roadmap-run: -PrintRecheckTask needs -Roadmap <slug>"; exit 4 }
|
|
40
|
+
# A PowerShell block for the owner to paste: every value is a single-quoted literal (a ' is doubled), and the
|
|
41
|
+
# task's whole argument line is ONE string, so no shell splits it.
|
|
42
|
+
if (-not (Test-Path -LiteralPath $Repo -PathType Container)) {
|
|
43
|
+
Write-Error "roadmap-run: -Repo '$Repo' is not a folder; nothing printed"; exit 4
|
|
44
|
+
}
|
|
45
|
+
$recheck = (Resolve-Path (Join-Path $PSScriptRoot 'roadmap-recheck.ps1')).Path
|
|
46
|
+
# A full path with no trailing separator: in a quoted command-line argument a trailing `\` would escape the quote. A
|
|
47
|
+
# drive root keeps one `\`, doubled so it stays a backslash in front of the closing quote.
|
|
48
|
+
$repoFull = (Resolve-Path -LiteralPath $Repo).Path.TrimEnd('\', '/')
|
|
49
|
+
if ($repoFull -match '^[A-Za-z]:$') { $repoFull += '\\' }
|
|
50
|
+
$shellExe = (Get-Process -Id $PID).Path
|
|
51
|
+
function Sq([string]$s) { "'" + $s.Replace("'", "''") + "'" }
|
|
52
|
+
$argLine = "-NoProfile -NonInteractive -File `"$recheck`" -Roadmap $Roadmap -Repo `"$repoFull`""
|
|
53
|
+
if ($GhAccount) { $argLine += " -GhAccount $GhAccount" }
|
|
54
|
+
Write-Output "`$action = New-ScheduledTaskAction -Execute $(Sq $shellExe) -Argument $(Sq $argLine)"
|
|
55
|
+
Write-Output "`$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 2)"
|
|
56
|
+
Write-Output ("Register-ScheduledTask -TaskName $(Sq "caddis-roadmap-recheck-$Roadmap") -Action `$action " +
|
|
57
|
+
"-Trigger `$trigger -Description $(Sq "caddis roadmap $Roadmap recheck, every 2 hours")")
|
|
58
|
+
Write-Output ("# Note: this task runs only while you are logged on. To run it whether you are logged on or not, " +
|
|
59
|
+
"add -User <DOMAIN\user> -Password <password> to Register-ScheduledTask, or set that option in Task Scheduler.")
|
|
60
|
+
exit 0
|
|
61
|
+
}
|
|
62
|
+
$py = (Get-Command python -ErrorAction SilentlyContinue).Source
|
|
63
|
+
if (-not $py) { Write-Error "roadmap-run: python not found on PATH"; exit 3 }
|
|
64
|
+
# Installed plugin: both files sit in scripts/. Source repo: the Python file is in <repo>/scripts.
|
|
65
|
+
$runner = Join-Path $PSScriptRoot 'caddis_roadmap_run.py'
|
|
66
|
+
if (-not (Test-Path $runner)) { $runner = Join-Path $PSScriptRoot '..\..\scripts\caddis_roadmap_run.py' }
|
|
67
|
+
if (-not (Test-Path $runner)) { Write-Error "roadmap-run: caddis_roadmap_run.py not found"; exit 4 }
|
|
68
|
+
$inv = [Globalization.CultureInfo]::InvariantCulture
|
|
69
|
+
$argv = @($runner)
|
|
70
|
+
if ($Plan) { $argv += @('--plan', $Plan) } else { $argv += @('--roadmap', $Roadmap) }
|
|
71
|
+
$argv += @('--repo', $Repo,
|
|
72
|
+
'--max-hours', $MaxHours.ToString($inv), '--max-sessions', $MaxSessions.ToString($inv),
|
|
73
|
+
'--session-timeout-min', $SessionTimeoutMin.ToString($inv),
|
|
74
|
+
'--max-usd-per-session', $MaxUsdPerSession.ToString($inv), '--max-usd-total', $MaxUsdTotal.ToString($inv),
|
|
75
|
+
'--engine', $Engine)
|
|
76
|
+
if ($Model) { $argv += @('--model', $Model) }
|
|
77
|
+
if ($DryRun) { $argv += '--dry-run' }
|
|
78
|
+
if ($AcceptRoadmap) { # owner only: the Python side refuses it headless
|
|
79
|
+
if (-not $Roadmap) { Write-Error "roadmap-run: -AcceptRoadmap needs -Roadmap <slug>"; exit 4 }
|
|
80
|
+
$acceptArgs = @('--roadmap', $Roadmap, '--repo', $Repo, '--accept-roadmap')
|
|
81
|
+
if ($DryRun) { $acceptArgs += '--dry-run' } # print the diff, write nothing
|
|
82
|
+
if ($Yes) { $acceptArgs += '--yes' } # no console confirmation
|
|
83
|
+
& $py $runner @acceptArgs
|
|
84
|
+
exit $LASTEXITCODE
|
|
85
|
+
}
|
|
86
|
+
if ($GhAccount) { $argv += @('--gh-account', $GhAccount) }
|
|
87
|
+
& $py @argv
|
|
88
|
+
exit $LASTEXITCODE
|
|
@@ -689,7 +689,49 @@ if [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then
|
|
|
689
689
|
echo "[gate] interpreter: $PY"
|
|
690
690
|
py_gate ruff check .
|
|
691
691
|
if py_sources_exist; then py_gate mypy .; else echo "[skip] mypy: no Python sources"; fi
|
|
692
|
-
|
|
692
|
+
# pytest is OPT-IN here (CADDIS_GATE_PYTEST=1). Found 2026-10-10: the full suite took 25-31 min in this
|
|
693
|
+
# hook on a box whose system disk was slow, while CI ran the same suite in 5 min - and a merge needs green
|
|
694
|
+
# CI anyway. A local gate five times slower than the check it stands in for trains people to --no-verify it.
|
|
695
|
+
# When it does run: CADDIS_GATE_TMP moves TMPDIR/TEMP/TMP (tests write to tmp_path; Python reads TMPDIR
|
|
696
|
+
# first, so set all three), CADDIS_GATE_PYTEST_ARGS adds arguments (for example "-n 4" with pytest-xdist;
|
|
697
|
+
# use a number, not "auto"), and a machine-wide lock (CADDIS_GATE_LOCK, mkdir-based, waits up to
|
|
698
|
+
# CADDIS_GATE_LOCK_WAIT seconds, a stale one is taken over after 60 min) lets only ONE pytest gate run at a time, so several repos pushing together cannot
|
|
699
|
+
# pile their suites on the same disk and CI runners.
|
|
700
|
+
if [ "${CADDIS_GATE_PYTEST:-0}" = "1" ]; then
|
|
701
|
+
if [ -n "${CADDIS_GATE_TMP:-}" ]; then
|
|
702
|
+
mkdir -p "$CADDIS_GATE_TMP" 2>/dev/null || true
|
|
703
|
+
export TMPDIR="$CADDIS_GATE_TMP" TEMP="$CADDIS_GATE_TMP" TMP="$CADDIS_GATE_TMP"
|
|
704
|
+
fi
|
|
705
|
+
LOCK="${CADDIS_GATE_LOCK:-${TMPDIR:-${TEMP:-/tmp}}/caddis-pytest-gate.lock}"
|
|
706
|
+
mkdir -p "$(dirname "$LOCK")" 2>/dev/null || true
|
|
707
|
+
lock_wait="${CADDIS_GATE_LOCK_WAIT:-1800}"
|
|
708
|
+
waited=0
|
|
709
|
+
got_lock=0
|
|
710
|
+
while :; do
|
|
711
|
+
if mkdir "$LOCK" 2>/dev/null; then got_lock=1; break; fi
|
|
712
|
+
# A stale lock is removed, then this round still sleeps and counts: if the removal fails (a lock owned
|
|
713
|
+
# by another user), the loop ends at lock_wait instead of spinning forever.
|
|
714
|
+
if [ -n "$(find "$LOCK" -maxdepth 0 -mmin +60 2>/dev/null)" ]; then
|
|
715
|
+
rmdir "$LOCK" 2>/dev/null || true
|
|
716
|
+
fi
|
|
717
|
+
if [ "$waited" -ge "$lock_wait" ]; then break; fi
|
|
718
|
+
if [ "$waited" -eq 0 ]; then echo "[gate] pytest: waiting for another repo's pytest gate ($LOCK)"; fi
|
|
719
|
+
sleep 1
|
|
720
|
+
waited=$((waited + 1))
|
|
721
|
+
done
|
|
722
|
+
if [ "$got_lock" -eq 1 ]; then
|
|
723
|
+
trap 'rmdir "$LOCK" 2>/dev/null || true' EXIT INT TERM
|
|
724
|
+
# shellcheck disable=SC2086 # CADDIS_GATE_PYTEST_ARGS is meant to word-split
|
|
725
|
+
py_gate pytest -q ${CADDIS_GATE_PYTEST_ARGS:-}
|
|
726
|
+
rmdir "$LOCK" 2>/dev/null || true
|
|
727
|
+
trap - EXIT INT TERM
|
|
728
|
+
else
|
|
729
|
+
echo "[gate] pytest: another pytest gate holds $LOCK for over ${lock_wait}s - cannot run, so the gate fails" >&2
|
|
730
|
+
fail=1
|
|
731
|
+
fi
|
|
732
|
+
else
|
|
733
|
+
echo "[skip] pytest: runs in CI (set CADDIS_GATE_PYTEST=1 to run it here)"
|
|
734
|
+
fi
|
|
693
735
|
fi
|
|
694
736
|
fi
|
|
695
737
|
if [ -f "package.json" ] && command -v npm >/dev/null 2>&1; then
|
|
@@ -1054,7 +1096,6 @@ items?" has no answer when one state has three spellings.
|
|
|
1054
1096
|
| Work in flight right now | `.caddis/plans/<feature>.md` | A plan is being executed. A parking-lot item is not. |
|
|
1055
1097
|
| A task interrupted mid-session | `/caddis:digress` stack | That is a pause, not a backlog item. `/caddis:catchup` pops it. |
|
|
1056
1098
|
| An ask only an outsider can resolve | `.caddis/comms/register.md` | Blocked on a human, not on us. |
|
|
1057
|
-
| Board cards | `.caddis/backlog/` | **docket writes that directory.** It is a projection of the board, not a hand-written register. Never edit it by hand. |
|
|
1058
1099
|
|
|
1059
1100
|
## Commands
|
|
1060
1101
|
|
|
@@ -1432,6 +1473,48 @@ def ensure_user_env(dry: bool, home: Path | None = None) -> list[str]:
|
|
|
1432
1473
|
+ ("" if not raw else " (previous version saved as settings.json.caddis-bak)")]
|
|
1433
1474
|
|
|
1434
1475
|
|
|
1476
|
+
CLEANUP_PERIOD_KEY = "cleanupPeriodDays"
|
|
1477
|
+
CLEANUP_PERIOD_DAYS = 120
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
def ensure_cleanup_period(dry: bool, home: Path | None = None, days: int = CLEANUP_PERIOD_DAYS) -> str:
|
|
1481
|
+
"""Keep Claude Code transcripts `days` days (Claude Code's own default is 30) by adding `cleanupPeriodDays`.
|
|
1482
|
+
|
|
1483
|
+
WHY: caddis measures which skills and commands are used from those transcripts; on 11 Oct 2026 only
|
|
1484
|
+
35 days were left, too few to decide what to cut (caddis-next checks, section 4.6). Same rules as
|
|
1485
|
+
ensure_user_env: an existing value is ALWAYS left alone, a file that does not parse is never rewritten,
|
|
1486
|
+
a backup is kept and the write is atomic. `CADDIS_NO_SETTINGS_ENV` skips it. Its backup has its own name
|
|
1487
|
+
(`settings.json.caddis-retention-bak`): main() runs ensure_user_env first, and sharing `.caddis-bak` would
|
|
1488
|
+
overwrite the user's original file with that function's output. Known limit, as for ensure_user_env: a
|
|
1489
|
+
write by Claude Code between this read and the replace is lost."""
|
|
1490
|
+
if os.environ.get("CADDIS_NO_SETTINGS_ENV"):
|
|
1491
|
+
return "transcript retention: skipped (CADDIS_NO_SETTINGS_ENV set)"
|
|
1492
|
+
path = _user_settings_path(home)
|
|
1493
|
+
if path.is_file():
|
|
1494
|
+
raw = path.read_text(encoding="utf-8", errors="ignore")
|
|
1495
|
+
try:
|
|
1496
|
+
data = json.loads(raw)
|
|
1497
|
+
except json.JSONDecodeError as exc:
|
|
1498
|
+
return (f"transcript retention: {path} is NOT VALID JSON ({exc.msg}, line {exc.lineno}) — "
|
|
1499
|
+
"left untouched; fix it by hand.")
|
|
1500
|
+
if not isinstance(data, dict):
|
|
1501
|
+
return f"transcript retention: {path} is not a JSON object — left untouched"
|
|
1502
|
+
else:
|
|
1503
|
+
raw, data = "", {}
|
|
1504
|
+
if CLEANUP_PERIOD_KEY in data:
|
|
1505
|
+
return f"transcript retention: {CLEANUP_PERIOD_KEY} already set to {data[CLEANUP_PERIOD_KEY]!r} — left alone"
|
|
1506
|
+
data[CLEANUP_PERIOD_KEY] = days
|
|
1507
|
+
if not dry:
|
|
1508
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
1509
|
+
if raw:
|
|
1510
|
+
path.with_suffix(".json.caddis-retention-bak").write_text(raw, encoding="utf-8")
|
|
1511
|
+
tmp = path.with_suffix(".json.caddis-tmp")
|
|
1512
|
+
tmp.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
|
1513
|
+
os.replace(tmp, path)
|
|
1514
|
+
verb = "would set" if dry else "set"
|
|
1515
|
+
return f"transcript retention: {verb} {CLEANUP_PERIOD_KEY}={days} in {path}"
|
|
1516
|
+
|
|
1517
|
+
|
|
1435
1518
|
def scaffold_artifact_dir(target: Path, dry: bool) -> list[str]:
|
|
1436
1519
|
"""Create the harness-owned .caddis/ artifact tree + a default .gitignore + a config example.
|
|
1437
1520
|
|
|
@@ -1733,6 +1816,7 @@ def main() -> int:
|
|
|
1733
1816
|
print("-- user settings (additive only, never overwrites a value you set)")
|
|
1734
1817
|
for line in ensure_user_env(args.dry_run):
|
|
1735
1818
|
print(f" {line}")
|
|
1819
|
+
print(f" {ensure_cleanup_period(args.dry_run)}")
|
|
1736
1820
|
|
|
1737
1821
|
print("-- doc-coverage discipline (DOC-MAP + page guide + checker)")
|
|
1738
1822
|
for line in emit_doc_discipline(target, ident, args.force, args.dry_run):
|
|
@@ -9,7 +9,7 @@ stdout as a `{"decision":…}` object — a stray string trips its "unsupported
|
|
|
9
9
|
does a pure side effect and prints NOTHING: empty stdout is agy's "no decision", while
|
|
10
10
|
`{"decision": "continue"}` would stop the session from ending.
|
|
11
11
|
|
|
12
|
-
Headless runs (CADDIS_HEADLESS
|
|
12
|
+
Headless runs (CADDIS_HEADLESS set and non-empty) are skipped, as in
|
|
13
13
|
the Claude Stop hook, so review and lane runs leave no files. The record is one append with no
|
|
14
14
|
transcript read, so it stays here rather than moving to /handoff (Phase 13).
|
|
15
15
|
|
|
@@ -90,11 +90,11 @@ def _workspace_roots(data):
|
|
|
90
90
|
return []
|
|
91
91
|
return [str(r) for r in roots if isinstance(r, (str, bytes)) and str(r).strip()]
|
|
92
92
|
|
|
93
|
-
_HEADLESS_MARKERS = ("CADDIS_HEADLESS",
|
|
93
|
+
_HEADLESS_MARKERS = ("CADDIS_HEADLESS",)
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
def _headless() -> bool:
|
|
97
|
-
"""True when
|
|
97
|
+
"""True when CADDIS_HEADLESS is set to a non-empty value. `CADDIS_HEADLESS=` is not headless."""
|
|
98
98
|
return any(str(os.environ.get(name, "")).strip() for name in _HEADLESS_MARKERS)
|
|
99
99
|
|
|
100
100
|
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
| Explainer Doc | `explainer-doc/` | Hand-off doc for a team that did NOT do the investigation (vendor, contractor, another team) — the "stranger must follow it alone" case. Use when the user says "write a spec for the X team", "document this for someone outside the team", "explainer doc", "implementation spec for a vendor", or "hand this off to Y". Not for readers with full context. |
|
|
56
56
|
| Hld | `hld/` | Generate High-Level Design (HLD) Markdown documentation and Confluence XHTML with native PlantUML diagrams. |
|
|
57
57
|
| Lld | `lld/` | Generate Lower-Level Design (LLD) Markdown documentation and Confluence XHTML with native PlantUML diagrams. |
|
|
58
|
+
| Office Documents Official | `office-documents-official/` | Hint for Office and PDF file work. Use when the user asks to create, edit, read or convert a Word .docx, PDF, PowerPoint .pptx or Excel .xlsx file. caddis does not ship these skills; points to Anthropic's official document-skills plugin. |
|
|
58
59
|
| Tech Explainer | `tech-explainer/` | >- |
|
|
59
60
|
| Technical Writing | `technical-writing/` | Documentation best practices for READMEs, API docs, architecture docs, runbooks and developer guides. Use when writing or reviewing docs or setting documentation standards. |
|
|
60
61
|
| Writing Plans | `writing-plans/` | Use when you have a spec or requirements for a multi-step task, before touching code |
|
|
@@ -97,20 +98,15 @@
|
|
|
97
98
|
| Pr Merge | `pr-merge/` | End-to-end pull request and merge lane — push feature branch, open or update PR, monitor CI to green, merge to default branch, and clean up the feature branch. |
|
|
98
99
|
| Prd | `prd/` | Capture requirements through structured discovery and write a PRD |
|
|
99
100
|
| Rca | `rca/` | Record a root cause in one step — .caddis/rca/<date>-<slug>.md — or close one with the fixing commit |
|
|
100
|
-
| Resume | `resume/` | Renamed to /caddis:catchup (alias, removed next release) |
|
|
101
|
-
| Review | `review/` | Renamed to /caddis:review-pr (alias, removed next release) |
|
|
102
101
|
| Review Pr | `review-pr/` | Review someone else's OPEN pull request end to end — what changed, what CI says, what is risky — then approve or request changes. Never approves on its own. |
|
|
103
102
|
| Ship | `ship/` | Commit, push, and monitor the deploy pipeline (auto-detects Gitea, GitHub Actions, or local-only) |
|
|
104
103
|
| Ship Merge | `ship-merge/` | Merge an already-green, already-reviewed PR behind an explicit deploy-confirm, monitor the deploy, validate prod, then clean up the branch — only on green. |
|
|
105
104
|
| Ship Pr | `ship-pr/` | Open a reviewed PR for the current feature branch — rebase-safe push, PR create/update, monitor CI, STOP at green. Never merges, never deploys (that's /ship-merge). |
|
|
106
|
-
| Spawn Hub | `spawn-hub/` | Hand the Advisory Hub role to a fresh session — run the mechanical audit, then generate the succession prompt with a context self-check the new Hub must pass |
|
|
107
105
|
| Spawn Session | `spawn-session/` | Hand the WORK to a fresh session — generate the handover from the repo, then validate the successor by re-deriving its answers |
|
|
108
|
-
| Statusline | `statusline/` | Renamed to /caddis:install-statusline (alias, removed next release) |
|
|
109
106
|
| Tdd | `tdd/` | Run a strict red-green-refactor TDD cycle for a unit of behavior |
|
|
110
107
|
| Ui Brief | `ui-brief/` | Design-first UI brief — lock the aesthetic before writing any code |
|
|
111
108
|
| Usage Review | `usage-review/` | Review local caddis usage over a window, surface prioritised recommendations, and apply config changes in one step |
|
|
112
109
|
| Use Model | `use-model/` | Explain (or apply) the model lanes — claude / claude-glm / cross-review — key resolution, and how to add a provider |
|
|
113
|
-
| Validate Phase | `validate-phase/` | Advisory Hub phase validation — consume a phase report, RE-DERIVE its claims independently, and return ACCEPT / ACCEPT-WITH-CORRECTION / REJECT |
|
|
114
110
|
| Version | `version/` | Report the installed caddis version |
|
|
115
111
|
|
|
116
112
|
### Media
|
|
@@ -134,10 +130,10 @@
|
|
|
134
130
|
|
|
135
131
|
| Skill | Path | When to Use |
|
|
136
132
|
|-------|------|-------------|
|
|
137
|
-
| Advisory Hub | `advisory-hub/` | >- |
|
|
138
133
|
| Best Practices | `best-practices/` | >- |
|
|
139
134
|
| Brainstorming | `brainstorming/` | You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation. |
|
|
140
135
|
| Context Curator | `context-curator/` | Compress and prioritize codebase context before handing work to reasoning agents, minimizing token waste while preserving the required decision inputs. |
|
|
141
136
|
| Preflight | `preflight/` | Plan-vs-codebase validation — verifies API contracts, type names, field accuracy, dependencies, and paths before implementation begins |
|
|
137
|
+
| Roadmap | `roadmap/` | Track milestones across plans in .caddis/roadmaps/<slug>/: next batch, typed blockers, rollup. Every change is a docs PR via caddis_roadmap.py. |
|
|
142
138
|
| Setup Project Ai | `setup-project-ai/` | Install or refresh the agent-agnostic dev harness in this project (AGENTS.md-canonical rules hierarchy + CLAUDE.md @import shims, subagents, commands, settings) |
|
|
143
139
|
| Skill Creator | `skill-creator/` | Create, edit and improve skills, run evals and benchmarks, and optimize a skill's description for triggering accuracy. |
|
package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md
CHANGED
|
@@ -44,7 +44,7 @@ description: >-
|
|
|
44
44
|
constraints pattern, and surfaces anti-patterns around breaking changes.
|
|
45
45
|
</commentary>
|
|
46
46
|
</example>
|
|
47
|
-
model:
|
|
47
|
+
model: sonnet
|
|
48
48
|
---
|
|
49
49
|
|
|
50
50
|
**Note: The current year is 2026.** Use this when searching for recent documentation and patterns.
|
|
@@ -46,7 +46,7 @@ description: >-
|
|
|
46
46
|
finds slow query examples, and identifies existing performance tests.
|
|
47
47
|
</commentary>
|
|
48
48
|
</example>
|
|
49
|
-
model:
|
|
49
|
+
model: sonnet
|
|
50
50
|
---
|
|
51
51
|
|
|
52
52
|
**Note: The current year is 2026.** Use this when referencing recent patterns or documentation.
|
|
@@ -48,7 +48,7 @@ description: >-
|
|
|
48
48
|
considerations: caching, N+1 queries, database indexes, async processing.
|
|
49
49
|
</commentary>
|
|
50
50
|
</example>
|
|
51
|
-
model:
|
|
51
|
+
model: sonnet
|
|
52
52
|
---
|
|
53
53
|
|
|
54
54
|
**Note: The current year is 2026.** Use this when referencing recent patterns or documentation.
|
|
@@ -68,6 +68,13 @@ on is worse than one sentence admitting there is nothing to recap.
|
|
|
68
68
|
|
|
69
69
|
**No argument:** this is the last step of the catchup procedure above, not a separate one.
|
|
70
70
|
After the list, add the workstream index and the open work:
|
|
71
|
+
0. The roadmap on origin is the order of work. List the roadmaps, then show each one's status line:
|
|
72
|
+
```
|
|
73
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_roadmap.py" list
|
|
74
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_roadmap.py" status --roadmap <slug>
|
|
75
|
+
```
|
|
76
|
+
Run `caddis_roadmap.py list`, then `caddis_roadmap.py status --roadmap <slug>` for each slug it prints, and
|
|
77
|
+
show the `line`. If `list` prints nothing (exit 1), the repo has no roadmap: go on to step 1.
|
|
71
78
|
1. Refresh and show the index: `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_workstreams.py" render-index`,
|
|
72
79
|
then display `.caddis/relay.md`. If it refuses a legacy `.caddis/relay.md`, display that file
|
|
73
80
|
as it is and suggest `/handoff`, which migrates it.
|
|
@@ -152,7 +152,7 @@ For each PR from a `<prefix>/phase-<NN>` branch, one at a time:
|
|
|
152
152
|
1. Read the whole diff (`gh pr diff <N>`). Check it against the phase's Design and Touches. A file
|
|
153
153
|
outside Touches is a finding.
|
|
154
154
|
2. Wait for CI: `gh pr checks <N> --watch` (or the ci-watch lane, if this caddis has it).
|
|
155
|
-
3. Review under the three rules
|
|
155
|
+
3. Review under the three rules (rule 3, review by tier): stop at the first CLEAN; after 3 rounds,
|
|
156
156
|
ask the owner. A fix goes back to the same cloud session or is made locally on the PR branch.
|
|
157
157
|
4. Just before merging, re-read `gh pr view <N> --json headRefOid,mergeStateStatus`. Merge only if
|
|
158
158
|
the head SHA is the one you reviewed and CI passed on it:
|
|
@@ -96,14 +96,17 @@ as a diff that silently is not read. Name a provider explicitly only when you ha
|
|
|
96
96
|
## Interpret the exit code
|
|
97
97
|
- **0 — REVIEW: CLEAN** → no blocking issues. Proceed.
|
|
98
98
|
- **1 — REVIEW: BLOCKING** → read the printed findings, then **FIX each blocking item** (or explicitly
|
|
99
|
-
justify why one is a false positive).
|
|
99
|
+
justify why one is a false positive). Fix it, then re-review only the fix diff. After 3 rounds, ask the owner (rule 3).
|
|
100
100
|
- **4 — error** → no verdict parsed, or a git/endpoint failure. Read stderr; do NOT treat as clean.
|
|
101
101
|
- **3 — misconfigured** → `REVIEW_API_KEY` is unset. Set it (see Prerequisite) and re-run.
|
|
102
102
|
|
|
103
103
|
## Three rules: one attempt, one review
|
|
104
104
|
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).
|
|
105
105
|
2. **Run it before review.** The coder runs the same checks as CI (name the exact commands in the task). Then run the change once on real data.
|
|
106
|
-
3. **Review
|
|
106
|
+
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).
|
|
107
|
+
Tier 0: gates only. Tier 1-small: your self-check only. Tier 1: one review by another vendor; stop at
|
|
108
|
+
the first CLEAN. Tier 2: two reviewers of two other vendors, in one round. Fix blocking findings only;
|
|
109
|
+
park the rest. Re-review only the fix diff, and only when the fix changed logic. After 3 rounds, ask the owner.
|
|
107
110
|
|
|
108
111
|
A diff over the batch ceiling is split into batches. Each batch prompt lists every file in the
|
|
109
112
|
change, so a batch does not report the others as missing.
|