@caddis/cli 0.4.52 → 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 +43 -1
- 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
|
|
@@ -1096,7 +1096,6 @@ items?" has no answer when one state has three spellings.
|
|
|
1096
1096
|
| Work in flight right now | `.caddis/plans/<feature>.md` | A plan is being executed. A parking-lot item is not. |
|
|
1097
1097
|
| A task interrupted mid-session | `/caddis:digress` stack | That is a pause, not a backlog item. `/caddis:catchup` pops it. |
|
|
1098
1098
|
| An ask only an outsider can resolve | `.caddis/comms/register.md` | Blocked on a human, not on us. |
|
|
1099
|
-
| 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. |
|
|
1100
1099
|
|
|
1101
1100
|
## Commands
|
|
1102
1101
|
|
|
@@ -1474,6 +1473,48 @@ def ensure_user_env(dry: bool, home: Path | None = None) -> list[str]:
|
|
|
1474
1473
|
+ ("" if not raw else " (previous version saved as settings.json.caddis-bak)")]
|
|
1475
1474
|
|
|
1476
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
|
+
|
|
1477
1518
|
def scaffold_artifact_dir(target: Path, dry: bool) -> list[str]:
|
|
1478
1519
|
"""Create the harness-owned .caddis/ artifact tree + a default .gitignore + a config example.
|
|
1479
1520
|
|
|
@@ -1775,6 +1816,7 @@ def main() -> int:
|
|
|
1775
1816
|
print("-- user settings (additive only, never overwrites a value you set)")
|
|
1776
1817
|
for line in ensure_user_env(args.dry_run):
|
|
1777
1818
|
print(f" {line}")
|
|
1819
|
+
print(f" {ensure_cleanup_period(args.dry_run)}")
|
|
1778
1820
|
|
|
1779
1821
|
print("-- doc-coverage discipline (DOC-MAP + page guide + checker)")
|
|
1780
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.
|
|
@@ -13,9 +13,8 @@ The plan file is the **durable spine of the harness** — it must let any future
|
|
|
13
13
|
agent, on any tool) resume with zero re-discovery. Optimize for that.
|
|
14
14
|
|
|
15
15
|
## Headless mode
|
|
16
|
-
When the invocation contains the marker **`HEADLESS RUN RULES`**, **or `CADDIS_HEADLESS`
|
|
17
|
-
|
|
18
|
-
`CADDIS_HEADLESS` on claude's `-p`/`--print`; the docket runner sets the others) — a non-interactive
|
|
16
|
+
When the invocation contains the marker **`HEADLESS RUN RULES`**, **or `CADDIS_HEADLESS` is set in
|
|
17
|
+
the environment** (the caddis OSS launchers export it on claude's `-p`/`--print`) — a non-interactive
|
|
19
18
|
caller spawned this session and no human is present, so the scope-check questions and any interview are
|
|
20
19
|
**suspended and forbidden**. This mode exists for one-line ideas: the card may be a short title with **no
|
|
21
20
|
description**, and there may be **no codebase, PROJECT-FACTS, or prior PRD** to read. That is expected —
|
|
@@ -39,13 +38,6 @@ Absolute rules in this mode (they override everything below):
|
|
|
39
38
|
a bullet under `## Constraints & decisions` — never a question to the user.
|
|
40
39
|
- **Honor the caller's output path and slug** (falling back to `.caddis/plans/<feature-slug>.md`);
|
|
41
40
|
set `feature: <slug>` in the frontmatter to that slug.
|
|
42
|
-
- **Also emit a visual companion** — a self-contained, scannable HTML page at `<artifact_dir>/<slug>.html`
|
|
43
|
-
presenting the plan visually (a goal card, phases as cards with their steps, an affected-files table,
|
|
44
|
-
and a risks/decisions section). **Use inline `<style>` ONLY** — the visual is rendered in a *sandboxed*
|
|
45
|
-
iframe with no script execution, so a `<script>`/CDN (e.g. the Tailwind browser CDN) would NOT run and
|
|
46
|
-
the page would appear unstyled. Keep it fully portable — no external `<script>`/`<link>`, no local
|
|
47
|
-
asset files, no `/`-rooted paths. This is the visual the human reviews in docket alongside the markdown.
|
|
48
|
-
Write it after the `.md`; the runner finds it by the matching `<slug>.html` name.
|
|
49
41
|
- **Always write the plan file, then end with exactly one fenced `json` highlights block** — nothing
|
|
50
42
|
after it:
|
|
51
43
|
```json
|
|
@@ -63,7 +55,7 @@ exists instead of assumed. If the work fits comfortably in one session, say so a
|
|
|
63
55
|
instead of planning. Only produce a plan for genuinely multi-phase work.
|
|
64
56
|
|
|
65
57
|
### Evidence gate — do not write plan content while a BLOCKER is unresolved
|
|
66
|
-
|
|
58
|
+
This is the direct counter to the failure
|
|
67
59
|
mode that makes a plan dangerous: **you write the spec, so you cannot see its gaps.** A phase built
|
|
68
60
|
on guessed field names or an imagined API is confidently wrong, passes every completeness check,
|
|
69
61
|
and only fails at the exit gate — or worse, doesn't.
|
|
@@ -164,9 +156,11 @@ of that role and write its Lane line as follows:
|
|
|
164
156
|
- `sonnet`: `claude — /model sonnet`
|
|
165
157
|
- `claude`: `claude — this session`
|
|
166
158
|
- `codex`: codex — `codex exec --ephemeral --sandbox workspace-write "HEADLESS RUN RULES. Read <plan path> and its Constraints. Implement Phase N only in the current checkout. Do not switch or create branches, commit, push, or edit files outside this phase. Run its exit gate and report the literal result."`
|
|
167
|
-
- `agy`: agy — `agy --mode accept-edits --dangerously-skip-permissions --add-dir . --print-timeout 20m --output-format
|
|
159
|
+
- `agy`: agy — `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spend.py" run --caller lane-pN -- agy --mode accept-edits --dangerously-skip-permissions --add-dir . --print-timeout 20m --output-format json -p "HEADLESS RUN RULES. Read <plan path> and its Constraints. Implement Phase N only in the current checkout. Do not switch or create branches, commit, push, or edit files outside this phase. Run its exit gate and report the literal result."`
|
|
168
160
|
|
|
169
|
-
Replace `<plan path>` and `N` with this plan's path and phase number.
|
|
161
|
+
Replace `<plan path>` and `N` (also in `lane-pN`) with this plan's path and phase number. The agy line
|
|
162
|
+
always starts with `caddis_spend.py run`: it books the call against the global EUR spend cap, and
|
|
163
|
+
`caddis_gate.py lane-check` refuses a bare `agy` Lane line. If the routing command fails
|
|
170
164
|
or exits 3, use `claude — this session` and state the reason in that phase.
|
|
171
165
|
|
|
172
166
|
#### A phase may take a no-escalation lane only if its exit gate would fail on a spec error
|
|
@@ -186,14 +180,9 @@ internal repo path into stakeholder-facing copy, and set a `live` status flag th
|
|
|
186
180
|
framework's own "Soon" badge). `tsc` clean, 632/632 tests green, cross-review CLEAN, exit gate
|
|
187
181
|
satisfied. A headless run following it literally would have committed both, entirely green.
|
|
188
182
|
|
|
189
|
-
In an Advisory-Hub plan, treat your lane as **provisional**: the Hub writes each `phase-NN.prompt.md`
|
|
190
|
-
before the phase runs, and that is the first time anyone but the spec's author reads it. Let that
|
|
191
|
-
read confirm or downgrade the lane. It costs nothing — the prompt is being written anyway.
|
|
192
|
-
|
|
193
183
|
### Group phases into MILESTONES — only when the plan is big enough
|
|
194
184
|
**Add milestones when the plan has ~8+ phases OR spans multiple sessions.** Below that, phases and a
|
|
195
|
-
Tracker are enough; a three-phase feature gains nothing from ceremony.
|
|
196
|
-
Advisory-Hub test, deliberately — one threshold to remember, not two.)
|
|
185
|
+
Tracker are enough; a three-phase feature gains nothing from ceremony.
|
|
197
186
|
|
|
198
187
|
A milestone is **a group of phases that ship together**. It answers "what lands when this is done?",
|
|
199
188
|
which is the question a long plan otherwise leaves the executor guessing at.
|
|
@@ -211,9 +200,10 @@ resuming session can see at a glance which group it is in and what remains befor
|
|
|
211
200
|
### Flag high-risk phases (`risk:` — a marker, not a mechanism)
|
|
212
201
|
Each phase may carry **`risk: normal|high`** (default `normal` — omit the line unless the phase is
|
|
213
202
|
`high`), meaning only "this is a phase where a wrong answer is expensive" — security/authz, a
|
|
214
|
-
correctness-critical algorithm, an ambiguous spec, or an irreversible change. It
|
|
215
|
-
|
|
216
|
-
|
|
203
|
+
correctness-critical algorithm, an ambiguous spec, or an irreversible change. It selects no model and
|
|
204
|
+
implies no fan-out. It has one effect: the roadmap/plan runner reviews a finished `risk: high` phase
|
|
205
|
+
twice (`caddis_review.py --plan --phase --runs 2`), gives it one fix session on blocking
|
|
206
|
+
findings, and stops `BLOCKED review` when findings remain. Roadmap mode reviews before it publishes the PR. Do not emit orchestration, lane fan-out, or
|
|
217
207
|
`Workflow` scripts from this command; the runtime decision rules and the intent→model map live in one
|
|
218
208
|
place, the `agent-orchestration` skill's *Multi-model fan-out* section.
|
|
219
209
|
|
|
@@ -275,7 +265,10 @@ yourself (relay + Tracker) before stopping — do not hand back "run `/caddis:ha
|
|
|
275
265
|
Three rules: one attempt, one review.
|
|
276
266
|
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).
|
|
277
267
|
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.
|
|
278
|
-
3. **Review
|
|
268
|
+
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).
|
|
269
|
+
Tier 0: gates only. Tier 1-small: your self-check only. Tier 1: one review by another vendor; stop at
|
|
270
|
+
the first CLEAN. Tier 2: two reviewers of two other vendors, in one round. Fix blocking findings only;
|
|
271
|
+
park the rest. Re-review only the fix diff, and only when the fix changed logic. After 3 rounds, ask the owner.
|
|
279
272
|
|
|
280
273
|
- One phase at a time: read this plan → run the phase on its **Lane** → RED→GREEN→VERIFY→CROSS-REVIEW→
|
|
281
274
|
COMMIT → update the **Tracker** row. The Tracker is the resume signal for every future session.
|
|
@@ -293,6 +286,10 @@ Three rules: one attempt, one review.
|
|
|
293
286
|
normally; the halt stops anything being **built on top of it** before a human has looked. Blast
|
|
294
287
|
radius stays one reviewable, revertable commit. Halting *beforehand* buys nothing: the phase has
|
|
295
288
|
to be executed either way, and a well-specced high-risk phase is as executable as any other.
|
|
289
|
+
One exception: when the session prompt says the runner reviews `risk: high` phases (the
|
|
290
|
+
runner's `plan-resume-prompt.md` says so), the runner's review gate replaces this halt: the
|
|
291
|
+
session ends `STATUS: CONTINUE`, and the runner reviews the phase twice before anything builds
|
|
292
|
+
on it. A headless marker (`CADDIS_HEADLESS=1`) alone does not lift the halt.
|
|
296
293
|
4. **A failed or blocked phase** — tests red, exit gate unmet, or the plan turned out wrong. Stop;
|
|
297
294
|
do not build on it.
|
|
298
295
|
- **A lane change is NOT a halt.** `/caddis:implement` spawns the assigned lane itself and verifies
|
|
@@ -366,66 +363,15 @@ done:
|
|
|
366
363
|
|
|
367
364
|
If any phase relies on the implementer *reasoning out* a gap, close the gap in the plan now.
|
|
368
365
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
> **You MUST call `Skill(advisory-hub)` and read *"When it earns its keep"* before deciding.**
|
|
380
|
-
> Do not decide from memory, and do not decide from any summary — including one in this file.
|
|
381
|
-
> The test is stated in exactly one place on purpose: two copies of a rule drift on the first edit,
|
|
382
|
-
> and the copy that used to live here had already drifted. It compressed the REQUIRED leg to the
|
|
383
|
-
> phrase *"expensive-to-reverse"* and dropped the enumeration that defines it — which reads as
|
|
384
|
-
> *"can I `git revert` this?"*, and under that reading a plan that publishes € figures to business
|
|
385
|
-
> stakeholders scores "no stakes". That is the one leg that fires on reporting, analytics and
|
|
386
|
-
> dashboard work, i.e. most of what this fleet builds. Load the skill.
|
|
387
|
-
|
|
388
|
-
If the test passes, tell the user plainly what it costs and what it buys, and offer to scaffold the
|
|
389
|
-
context doc from the `advisory-hub` skill's template. **Do not create it silently** — an opt-in
|
|
390
|
-
pattern that switches itself on is no longer opt-in.
|
|
391
|
-
|
|
392
|
-
**In headless mode, never offer and never create.** Headless forbids asking anything, so an "offer"
|
|
393
|
-
is impossible there. Instead record the result as a line under `## Constraints & decisions` —
|
|
394
|
-
*"Advisory Hub: test passed (N phases, <criteria>) — not scaffolded, headless run; create
|
|
395
|
-
`<plan-stem>-advisory-context.md` to enable"* — so the decision reaches a human rather than being
|
|
396
|
-
silently dropped or silently taken.
|
|
397
|
-
|
|
398
|
-
If it does not pass, say nothing **to the user** — a three-phase feature should never hear about
|
|
399
|
-
this. But **always record the determination in the plan, pass or fail**: one line under
|
|
400
|
-
`## Constraints & decisions`, naming which REQUIRED trigger was or was not hit.
|
|
401
|
-
|
|
402
|
-
> `Advisory Hub: not applicable — no REQUIRED trigger (not a migration / security change /
|
|
403
|
-
> production data correctness / numbers published to stakeholders).`
|
|
404
|
-
|
|
405
|
-
### If the test FAILS but this repo already runs a Hub for another plan
|
|
406
|
-
|
|
407
|
-
Check for an existing `*-advisory-context.md` in `.caddis/plans/` belonging to a **different** plan.
|
|
408
|
-
If one exists, add a second line under `## Constraints & decisions`:
|
|
409
|
-
|
|
410
|
-
> `Hub conventions: this repo runs Advisory Hub for <other-plan>. This plan does NOT — if it borrows
|
|
411
|
-
> the phase-NN.prompt.md / .report.md / CONTINUE GATE conventions, the lightweight rule applies: the
|
|
412
|
-
> session that files a report must not write the next prompt without an independent re-check.`
|
|
413
|
-
|
|
414
|
-
**Why this line exists.** A repo with one Hub plan has its artefacts sitting there as the most recent
|
|
415
|
-
example of "how we structure a multi-session plan here", and the next plan copies them by analogy.
|
|
416
|
-
It inherits the file names and none of the safety, because the safety was never in the names.
|
|
417
|
-
Measured once already: an implementing session filed its own batch report and then wrote the next
|
|
418
|
-
batch's prompt in the same session, with nobody having looked in between. Nothing was wrong that
|
|
419
|
-
time — and nothing checked either.
|
|
420
|
-
|
|
421
|
-
This is the cheapest possible place to catch it: when the second plan is created, before any
|
|
422
|
-
artefact-mimicry has happened. See *"Failing this test correctly does not mean no discipline"* in the
|
|
423
|
-
`advisory-hub` skill for the rule itself. Do not restate the rule here — one home, or the copies
|
|
424
|
-
drift.
|
|
425
|
-
|
|
426
|
-
Silent to the human, auditable in the artifact. "Say nothing" once meant *leave no trace anywhere*,
|
|
427
|
-
and a wrong negative was then invisible — no line in the plan, no line in the chat, nothing for
|
|
428
|
-
anyone to challenge. A rule whose failures leave no artifact cannot be reviewed.
|
|
366
|
+
A `risk: high` phase gets two independent review runs: run by the roadmap/plan runner automatically (from caddis-next Phase 11), and by hand in an interactive `/caddis:implement` run (`caddis_review.py --plan <plan> --phase <n> --runs 2`, from Phase 10). Only a `blocking` finding fails that review (exit 1); `should-fix` and `nit` findings go on a follow-up list and do not stop the merge. A phase gets 3 completed review rounds (a run that did not complete uses none); the 4th ends with exit 5, "stop, the owner decides". The advisory hub is retired; do not plan a separate validation session.
|
|
367
|
+
|
|
368
|
+
## Programme triggers
|
|
369
|
+
|
|
370
|
+
Small work that does not meet a trigger skips its block.
|
|
371
|
+
|
|
372
|
+
**Trigger: Always.** Add one open-work row for the plan in `.caddis/open-work.md`. Set its cells with `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_rows.py" set --file <open-work.md> --id <row id> --col Status=todo`, never with a regex edit.
|
|
373
|
+
|
|
374
|
+
**Trigger: The plan records a decision.** Record it with `/caddis:decide`.
|
|
429
375
|
|
|
430
376
|
## Step 4 — Report
|
|
431
377
|
Output the plan path (`.caddis/plans/<feature-slug>.md`), the phase list (one line each, with each
|