@caddis/cli 0.4.52 → 0.4.54

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.
Files changed (111) hide show
  1. package/bundles/antigravity-plugin/CADDIS-GLOSSARY.md +1 -0
  2. package/bundles/antigravity-plugin/guard_agy.py +184 -0
  3. package/bundles/antigravity-plugin/plugin.json +1 -1
  4. package/bundles/antigravity-plugin/repo_freshness.py +132 -5
  5. package/bundles/antigravity-plugin/scripts/caddis_budget.py +283 -0
  6. package/bundles/antigravity-plugin/scripts/caddis_checkout_guard.py +227 -0
  7. package/bundles/antigravity-plugin/scripts/caddis_docs_pr.py +284 -0
  8. package/bundles/antigravity-plugin/scripts/caddis_exit.py +2 -0
  9. package/bundles/antigravity-plugin/scripts/caddis_fleet.py +439 -0
  10. package/bundles/antigravity-plugin/scripts/caddis_frontmatter.py +1 -0
  11. package/bundles/antigravity-plugin/scripts/caddis_gate.py +255 -195
  12. package/bundles/antigravity-plugin/scripts/caddis_glossary.py +3 -3
  13. package/bundles/antigravity-plugin/scripts/caddis_governor.py +48 -4
  14. package/bundles/antigravity-plugin/scripts/caddis_inventory.py +38 -0
  15. package/bundles/antigravity-plugin/scripts/caddis_lanes.py +411 -127
  16. package/bundles/antigravity-plugin/scripts/caddis_lineage_publish.py +458 -0
  17. package/bundles/antigravity-plugin/scripts/caddis_merge_chain.py +237 -0
  18. package/bundles/antigravity-plugin/scripts/caddis_notify.py +125 -0
  19. package/bundles/antigravity-plugin/scripts/caddis_prod_check.py +380 -0
  20. package/bundles/antigravity-plugin/scripts/caddis_redact.py +99 -0
  21. package/bundles/antigravity-plugin/scripts/caddis_relay_git.py +2 -2
  22. package/bundles/antigravity-plugin/scripts/caddis_review.py +1309 -0
  23. package/bundles/antigravity-plugin/scripts/caddis_roadmap.py +2109 -0
  24. package/bundles/antigravity-plugin/scripts/caddis_roadmap_page.py +676 -0
  25. package/bundles/antigravity-plugin/scripts/caddis_roadmap_run.py +2605 -0
  26. package/bundles/antigravity-plugin/scripts/caddis_routing.py +7 -6
  27. package/bundles/antigravity-plugin/scripts/caddis_rows.py +476 -0
  28. package/bundles/antigravity-plugin/scripts/caddis_spawn.py +8 -9
  29. package/bundles/antigravity-plugin/scripts/caddis_spend.py +415 -0
  30. package/bundles/antigravity-plugin/scripts/caddis_tidy.py +357 -20
  31. package/bundles/antigravity-plugin/scripts/caddis_todo.py +55 -0
  32. package/bundles/antigravity-plugin/scripts/caddis_workstreams.py +178 -19
  33. package/bundles/antigravity-plugin/scripts/caddis_worktree_close.py +349 -0
  34. package/bundles/antigravity-plugin/scripts/check_doc_coverage.py +0 -56
  35. package/bundles/antigravity-plugin/scripts/claudster_doctor.py +1 -1
  36. package/bundles/antigravity-plugin/scripts/enforcement_inventory.py +0 -1
  37. package/bundles/antigravity-plugin/scripts/oss_review.py +2 -2
  38. package/bundles/antigravity-plugin/scripts/roadmap-recheck.ps1 +89 -0
  39. package/bundles/antigravity-plugin/scripts/roadmap-run.ps1 +88 -0
  40. package/bundles/antigravity-plugin/scripts/setup_project_ai.py +43 -1
  41. package/bundles/antigravity-plugin/session_end_agy.py +3 -3
  42. package/bundles/antigravity-plugin/skills/_registry.md +4 -6
  43. package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md +1 -1
  44. package/bundles/antigravity-plugin/skills/best-practices/agents/codebase-context-builder.md +1 -1
  45. package/bundles/antigravity-plugin/skills/best-practices/agents/task-intent-analyzer.md +1 -1
  46. package/bundles/antigravity-plugin/skills/catchup/SKILL.md +11 -0
  47. package/bundles/antigravity-plugin/skills/cloud-phases/SKILL.md +1 -1
  48. package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +5 -2
  49. package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +35 -83
  50. package/bundles/antigravity-plugin/skills/fleet-close/SKILL.md +167 -0
  51. package/bundles/antigravity-plugin/skills/fleet-open/SKILL.md +110 -0
  52. package/bundles/antigravity-plugin/skills/gh-cli/SKILL.md +2 -1
  53. package/bundles/antigravity-plugin/skills/handoff/SKILL.md +177 -48
  54. package/bundles/antigravity-plugin/skills/implement/SKILL.md +87 -147
  55. package/bundles/antigravity-plugin/skills/migrate-dir/SKILL.md +4 -3
  56. package/bundles/antigravity-plugin/skills/mmr/SKILL.md +5 -2
  57. package/bundles/antigravity-plugin/skills/office-documents-official/SKILL.md +24 -0
  58. package/bundles/antigravity-plugin/skills/park/SKILL.md +0 -1
  59. package/bundles/antigravity-plugin/skills/pr-merge/SKILL.md +28 -20
  60. package/bundles/antigravity-plugin/skills/prd/SKILL.md +2 -10
  61. package/bundles/antigravity-plugin/skills/refactoring/SKILL.md +2 -1
  62. package/bundles/antigravity-plugin/skills/review-pr/SKILL.md +1 -1
  63. package/bundles/antigravity-plugin/skills/roadmap/SKILL.md +260 -0
  64. package/bundles/antigravity-plugin/skills/roadmap/assets/plan-resume-prompt.md +77 -0
  65. package/bundles/antigravity-plugin/skills/roadmap/assets/render-check.template.mjs +68 -0
  66. package/bundles/antigravity-plugin/skills/roadmap/assets/review-protocol.md +78 -0
  67. package/bundles/antigravity-plugin/skills/roadmap/assets/roadmap.template.md +32 -0
  68. package/bundles/antigravity-plugin/skills/roadmap/assets/value-check.template.py +161 -0
  69. package/bundles/antigravity-plugin/skills/ship/SKILL.md +16 -16
  70. package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +15 -5
  71. package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +36 -16
  72. package/bundles/antigravity-plugin/skills/spawn-session/SKILL.md +4 -8
  73. package/bundles/antigravity-plugin/warm_start_agy.py +1 -3
  74. package/bundles/antigravity-plugin-extras/plugin.json +1 -1
  75. package/bundles/antigravity-plugin-extras/skills/_registry.md +1 -2
  76. package/bundles/antigravity-plugin-extras/skills/agent-orchestration/SKILL.md +5 -5
  77. package/bundles/antigravity-plugin-extras/skills/cross-review/SKILL.md +5 -2
  78. package/bundles/antigravity-plugin-extras/skills/runner-move/SKILL.md +214 -0
  79. package/bundles/codex/.codex/skills/coding/refactoring/SKILL.md +2 -1
  80. package/bundles/codex/.codex/skills/devops/gh-cli/SKILL.md +2 -1
  81. package/bundles/codex/.codex/skills/docs/office-documents-official/SKILL.md +24 -0
  82. package/bundles/codex/.codex/skills/workflow/best-practices/agents/best-practices-referencer.md +1 -1
  83. package/bundles/codex/.codex/skills/workflow/best-practices/agents/codebase-context-builder.md +1 -1
  84. package/bundles/codex/.codex/skills/workflow/best-practices/agents/task-intent-analyzer.md +1 -1
  85. package/bundles/codex/.codex/skills/workflow/roadmap/SKILL.md +260 -0
  86. package/bundles/codex/.codex/skills/workflow/roadmap/assets/plan-resume-prompt.md +77 -0
  87. package/bundles/codex/.codex/skills/workflow/roadmap/assets/render-check.template.mjs +68 -0
  88. package/bundles/codex/.codex/skills/workflow/roadmap/assets/review-protocol.md +78 -0
  89. package/bundles/codex/.codex/skills/workflow/roadmap/assets/roadmap.template.md +32 -0
  90. package/bundles/codex/.codex/skills/workflow/roadmap/assets/value-check.template.py +161 -0
  91. package/bundles/codex/AGENTS.md +5 -4
  92. package/bundles/manifest.json +3 -3
  93. package/package.json +1 -1
  94. package/bundles/antigravity-plugin/skills/advisory-hub/SKILL.md +0 -233
  95. package/bundles/antigravity-plugin/skills/advisory-hub/reference/context-template.md +0 -214
  96. package/bundles/antigravity-plugin/skills/advisory-hub/reference/hub-handbook.md +0 -233
  97. package/bundles/antigravity-plugin/skills/advisory-hub/reference/report-contract.md +0 -94
  98. package/bundles/antigravity-plugin/skills/advisory-hub/reference/succession.md +0 -118
  99. package/bundles/antigravity-plugin/skills/resume/SKILL.md +0 -6
  100. package/bundles/antigravity-plugin/skills/review/SKILL.md +0 -6
  101. package/bundles/antigravity-plugin/skills/spawn-hub/SKILL.md +0 -341
  102. package/bundles/antigravity-plugin/skills/statusline/SKILL.md +0 -6
  103. package/bundles/antigravity-plugin/skills/validate-phase/SKILL.md +0 -143
  104. package/bundles/antigravity-plugin-extras/skills/data-lineage/SKILL.md +0 -158
  105. package/bundles/antigravity-plugin-extras/skills/data-lineage/scripts/convert_doc_to_confluence.py +0 -1430
  106. package/bundles/antigravity-plugin-extras/skills/golden-plan/SKILL.md +0 -586
  107. package/bundles/codex/.codex/skills/workflow/advisory-hub/SKILL.md +0 -233
  108. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/context-template.md +0 -214
  109. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/hub-handbook.md +0 -233
  110. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/report-contract.md +0 -94
  111. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/succession.md +0 -118
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env python3
2
+ """Value check template: compare figures from an endpoint with an independent source over a fixed past window.
3
+
4
+ Copy it into the app (for example scripts/check_values.py) so CI and prod checks can run it again.
5
+
6
+ python value-check.template.py --base http://localhost:8000 --expected expected.json
7
+ python value-check.template.py --base http://localhost:8000 --expected expected.json --prove-it-can-fail
8
+
9
+ Expected file:
10
+ {"window": {"start": "2026-09-01", "end": "2026-09-30"},
11
+ "figures": [{"name": "...", "endpoint": "/api/x", "path": "a.b", "expected": 1200,
12
+ "source": "where the expected value came from", "population": "who is counted",
13
+ "denominator": "what the rate divides by, or none", "tolerance": 0.001, "series": "day"}]}
14
+
15
+ Rules:
16
+ - The window must end before today. A moving window ("today") gives a number that changes while you check it.
17
+ - Every figure names its source, population and denominator.
18
+ - A "series": "day" figure has ISO date keys that all fall on one weekday. A weekday gap is not a data gap.
19
+ - --prove-it-can-fail changes the expected values on purpose. The run must then exit 1.
20
+
21
+ Exit codes: 0 all figures pass, 1 a figure fails, 4 bad input or an HTTP error that is not a figure failure.
22
+ """
23
+ from __future__ import annotations
24
+
25
+ import argparse
26
+ import copy
27
+ import datetime as dt
28
+ import json
29
+ import sys
30
+ import urllib.error
31
+ import urllib.parse
32
+ import urllib.request
33
+
34
+ _MISSING = object()
35
+
36
+
37
+ class BadInput(Exception):
38
+ """The expected file or the request is wrong. Exit 4."""
39
+
40
+
41
+ def _parse_date(text: str, what: str) -> dt.date:
42
+ try:
43
+ return dt.date.fromisoformat(str(text))
44
+ except ValueError as exc:
45
+ raise BadInput(f"{what} is not an ISO date: {text!r}") from exc
46
+
47
+
48
+ def validate(spec: dict) -> None:
49
+ window = spec.get("window") or {}
50
+ start, end = _parse_date(window.get("start"), "window.start"), _parse_date(window.get("end"), "window.end")
51
+ if end >= dt.date.today():
52
+ raise BadInput(f"window.end {end} is not before today ({dt.date.today()}): use a fixed past window")
53
+ if start > end:
54
+ raise BadInput("window.start is after window.end")
55
+ figures = spec.get("figures") or []
56
+ if not figures:
57
+ raise BadInput("no figures in the expected file")
58
+ for fig in figures:
59
+ name = fig.get("name") or "<unnamed>"
60
+ for key in ("name", "endpoint", "path", "expected"):
61
+ if key not in fig or fig[key] in ("", None):
62
+ raise BadInput(f"figure {name!r} has no {key}")
63
+ for key in ("source", "population", "denominator"):
64
+ if not str(fig.get(key, "")).strip():
65
+ raise BadInput(f"figure {name!r} has an empty {key}: name it")
66
+ if fig.get("series") == "day":
67
+ if not isinstance(fig["expected"], dict) or not fig["expected"]:
68
+ raise BadInput(f"figure {name!r}: a day series needs a non-empty object of date keys")
69
+ weekdays = {_parse_date(k, f"figure {name!r} key").weekday() for k in fig["expected"]}
70
+ if len(weekdays) > 1:
71
+ raise BadInput(f"figure {name!r}: day series keys fall on more than one weekday")
72
+
73
+
74
+ def prove_it_can_fail(spec: dict) -> dict:
75
+ """Return a copy with a wrong expected value, so a correct endpoint must fail."""
76
+ spec = copy.deepcopy(spec)
77
+ scalars = [f for f in spec["figures"] if not isinstance(f["expected"], dict)]
78
+ if scalars:
79
+ scalars[0]["expected"] = scalars[0]["expected"] + 1
80
+ series = [f for f in spec["figures"] if isinstance(f["expected"], dict)]
81
+ if series:
82
+ series[0]["expected"].pop(next(iter(series[0]["expected"]))) # a missing date must fail the compare
83
+ series[0]["expected"]["1999-01-04"] = 0 # 1999-01-04 is a Monday; the endpoint has no such key
84
+ if not scalars and not series:
85
+ spec["figures"][0]["path"] += ".missing"
86
+ return spec
87
+
88
+
89
+ def fetch(base: str, endpoint: str, window: dict, headers: dict) -> tuple[int, object]:
90
+ query = urllib.parse.urlencode({"start": window["start"], "end": window["end"]})
91
+ req = urllib.request.Request(f"{base.rstrip('/')}{endpoint}?{query}", headers=headers)
92
+ try:
93
+ with urllib.request.urlopen(req, timeout=30) as resp:
94
+ return resp.status, json.loads(resp.read().decode("utf-8"))
95
+ except urllib.error.HTTPError as exc:
96
+ return exc.code, None
97
+ except (urllib.error.URLError, TimeoutError, ValueError) as exc:
98
+ raise BadInput(f"cannot read {endpoint}: {exc}") from exc
99
+
100
+
101
+ def dig(data: object, path: str) -> object:
102
+ for part in path.split("."):
103
+ if isinstance(data, dict) and part in data:
104
+ data = data[part]
105
+ else:
106
+ return _MISSING
107
+ return data
108
+
109
+
110
+ def same(actual: object, expected: object, tolerance: float) -> bool:
111
+ if isinstance(expected, dict):
112
+ if not isinstance(actual, dict):
113
+ return False
114
+ return all(k in actual and same(actual[k], v, tolerance) for k, v in expected.items())
115
+ if isinstance(expected, bool) or isinstance(actual, bool) or not isinstance(expected, (int, float)):
116
+ return actual == expected
117
+ return isinstance(actual, (int, float)) and abs(actual - expected) <= tolerance
118
+
119
+
120
+ def check(spec: dict, base: str, headers: dict) -> bool:
121
+ ok = True
122
+ for fig in spec["figures"]:
123
+ status, body = fetch(base, fig["endpoint"], spec["window"], headers)
124
+ actual = dig(body, fig["path"]) if status == 200 else _MISSING
125
+ passed = actual is not _MISSING and same(actual, fig["expected"], float(fig.get("tolerance", 0)))
126
+ shown = "missing" if actual is _MISSING else actual
127
+ if status != 200:
128
+ shown = f"HTTP {status}"
129
+ print(f"{'PASS' if passed else 'FAIL'} {fig['name']}: endpoint {shown} vs {fig['source']} {fig['expected']}; "
130
+ f"population {fig['population']}; denominator {fig['denominator']}")
131
+ ok = ok and passed
132
+ return ok
133
+
134
+
135
+ def main(argv: list[str] | None = None) -> int:
136
+ ap = argparse.ArgumentParser(description=__doc__.split("\n")[0])
137
+ ap.add_argument("--base", required=True, help="origin of the app, for example http://localhost:8000")
138
+ ap.add_argument("--expected", required=True, help="expected figures JSON file")
139
+ ap.add_argument("--prove-it-can-fail", action="store_true", help="change the expected values; the run must exit 1")
140
+ ap.add_argument("--header", action="append", default=[], metavar="K:V", help="extra request header (repeatable)")
141
+ args = ap.parse_args(argv)
142
+ try:
143
+ with open(args.expected, encoding="utf-8") as fh:
144
+ spec = json.load(fh)
145
+ validate(spec)
146
+ headers = {}
147
+ for h in args.header:
148
+ key, sep, value = h.partition(":")
149
+ if not sep:
150
+ raise BadInput(f"--header needs K:V, got {h!r}")
151
+ headers[key.strip()] = value.strip()
152
+ if args.prove_it_can_fail:
153
+ spec = prove_it_can_fail(spec)
154
+ return 0 if check(spec, args.base, headers) else 1
155
+ except (BadInput, OSError, ValueError) as exc:
156
+ print(f"bad input: {exc}", file=sys.stderr)
157
+ return 4
158
+
159
+
160
+ if __name__ == "__main__":
161
+ sys.exit(main())
@@ -36,7 +36,7 @@ names, branch, and service identifiers — never assume.
36
36
  - Tests: run only if the user says they're needed or a gate explicitly requires them
37
37
  - Fix any failures before proceeding. Do not commit broken code.
38
38
 
39
- **2. STAGE + COMMIT** — Stage only the intended files (never `git add -A` blindly):
39
+ **2. STAGE + COMMIT** — Stage only the intended files, by name (never `git add -A`, `git add .` or a folder):
40
40
  ```
41
41
  git status --short # confirm what's staged
42
42
  git add <specific files>
@@ -48,20 +48,8 @@ Use conventional commits: `fix:`, `feat:`, `chore:`, `refactor:`, `docs:`. Scope
48
48
  **2b. CROSS-REVIEW TRIGGER** — `ship` has no review pause at all, which is how sixteen fixes reached production unreviewed in one day.
49
49
 
50
50
  <!-- shared:cross-review-trigger — keep byte-identical across commands; a test pins it -->
51
- **Run the trigger, do not eyeball the diff:**
52
-
53
- ```bash
54
- python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-trigger --range <base>...HEAD
55
- ```
56
-
57
- Exit **0** — say nothing, carry on. Exit **2** — it prints which rule fired and on which files.
58
- Run `/caddis:cross-review`, show the findings, and let the user decide. It **never blocks**: this
59
- picks when to ask for a second opinion, it is not a verdict, and a review gate that blocks a ship
60
- gets switched off inside a week.
61
-
62
- It fires on SQL and repositories, `services/`, caches and refresh jobs, auth and RBAC, or a diff
63
- over 400 changed lines. No judgement in any of those — deliberately, because judgement is exactly
64
- what failed.
51
+ Run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-tier --range <base>...HEAD` and review by its tier (rule 3).
52
+ `<base>` is `origin/<default branch>` (on the default branch itself, the commit before this change). Tier 0 or 1-small: no model review. Tier 1: one `/caddis:cross-review`. Tier 2: two reviewers of two other vendors in one round. No `TIER:` line means tier 2.
65
53
  <!-- /shared:cross-review-trigger -->
66
54
 
67
55
  **3. PUSH** — to the repo's default branch (confirm the branch first; don't assume `main`):
@@ -117,9 +105,21 @@ Health: green ✓ | n/a
117
105
  Release tag: <tag> → <sha> | n/a
118
106
  ```
119
107
 
108
+ ## Programme triggers
109
+
110
+ Small work that does not meet a trigger skips its block.
111
+
112
+ **Trigger: Always, when the repo deploys on push.** No merge while a push run on the default branch is in progress. Check `gh run list --branch <default> --event push --status in_progress`; if a run is listed, wait for it. `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_merge_chain.py"` does this check.
113
+
114
+ **Trigger: A peer session is known.** A relay or a SessionStart warning names another session on this repo. Before the merge, send each named peer session a message (SendMessage or the peer channel). It is a notice, never a request for permission.
115
+
116
+ **Trigger: Always, when the repo deploys on push.** After the merge, run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_prod_check.py" <sha>` with the repo's profile, `.caddis/prod-check.toml`. The script resolves a short SHA to the full SHA first, or refuses with exit 4. A repo with no profile gets items 1 and 2 only, and the script says so.
117
+
118
+ **Trigger: Two or more reviewed green PRs wait to merge.** Combine them into one release PR (the global rule of 2026-10-10): merge their branches into one release branch, run the gates once, open one release PR that links the components, then close the components with a link.
119
+
120
120
  ## Rules
121
121
  - Never push before preflight gates are green.
122
- - Never use `git add -A` without reviewing `git status` first.
122
+ - Never `git add -A`, `git add .` or `git add <dir>`, even after reading `git status`: stage named files only (the guard denies the first two).
123
123
  - Do not edit a workflow file (`.gitea/workflows/` or `.github/workflows/`) to make a failing gate
124
124
  pass — fix the source.
125
125
  - Gitea lane: tag-triggered runs after `release_metadata` are expected; verify `deploy_prod` is
@@ -48,6 +48,12 @@ State plainly, then wait for confirmation:
48
48
  This is the one irreversible, outward-facing step. Approval here **does not carry over** to any
49
49
  future run — ask every time, even for the same PR five minutes later.
50
50
 
51
+ ## Programme triggers
52
+
53
+ Small work that does not meet a trigger skips its block.
54
+
55
+ **Trigger: Always, when the repo deploys on push.** No merge while a push run on the default branch is in progress. Check `gh run list --branch <default> --event push --status in_progress`; if a run is listed, wait for it. `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_merge_chain.py"` does this check.
56
+
51
57
  ## Step 3 — Merge
52
58
 
53
59
  Re-read PR head and merge state before merging (GitHub lane):
@@ -65,8 +71,9 @@ an explicit argument wins. Options: **squash**, **merge-commit**, **rebase-merge
65
71
  if detection is inconclusive, say so and use merge-commit (never silently squash someone's history).
66
72
 
67
73
  Then merge:
68
- - GitHub: `gh pr merge <pr>` with `--squash` (squash), `--merge` (merge-commit) or `--rebase` (rebase-merge).
69
- - Gitea: call the Gitea PR merge API with the chosen strategy.
74
+ - GitHub: `gh pr merge <pr> --match-head-commit <head-sha>` (the full SHA) with `--squash` (squash), `--merge`
75
+ (merge-commit) or `--rebase` (rebase-merge). GitHub refuses the merge if the head moved.
76
+ - Gitea: call the Gitea PR merge API with the chosen strategy and `head_commit_id: <head-sha>`.
70
77
 
71
78
  Record the merge SHA.
72
79
 
@@ -93,8 +100,11 @@ attempt a silent re-deploy — and **skip cleanup** (Step 6).
93
100
  ## Step 6 — Branch cleanup — only after a confirmed-green deploy
94
101
 
95
102
  **Only after** Step 5 is green:
96
- - Delete the **remote** feature branch; delete the **local** feature branch.
97
- - Switch to the default branch and fast-forward it to the merge commit.
103
+ - Run `git status --short`. If it shows changes you did not make, do not switch, stash, reset or commit:
104
+ leave them, report them, and stop cleanup here.
105
+ - `git fetch --prune`, then switch to the default branch and fast-forward it to the merge commit.
106
+ - Delete the **remote** feature branch; delete the **local** feature branch (for a squash merge, compare
107
+ the branch tree with the merged tree first, not ancestry).
98
108
  - Drop the `backup/<branch>-preship` ref `/ship-pr` created.
99
109
 
100
110
  If deploy validation failed: **skip cleanup** entirely and say so — never delete a branch whose
@@ -113,7 +123,7 @@ Cleanup: remote branch ✗ deleted / local ✗ deleted / backup ref droppe
113
123
  ## Rules
114
124
  - Never merge without: green required checks **and** the explicit human deploy-confirm.
115
125
  - Never delete a branch before its deploy is validated green.
116
- - Never `git add -A` without reviewing `git status`; never edit a workflow file to make a gate pass.
126
+ - Never `git add -A`, `git add .` or `git add <dir>`, even after reading `git status`: stage named files only (the guard denies the first two). Never edit a workflow file to make a gate pass.
117
127
  - Local-only lane: no PR, no merge — refuse and point at `/ship`.
118
128
 
119
129
  ## Skill reference
@@ -40,6 +40,37 @@ are uncommitted.)
40
40
  - Fix failures first. **Never open a PR over red preflight** — a PR that arrives red wastes the
41
41
  reviewer it exists to serve.
42
42
 
43
+ ## Step 2b — Tidy check on this PR's files (before the PR exists)
44
+
45
+ Finished plans close in the PR that finishes them (`/caddis:implement` step 4b). Check that this
46
+ PR did, on the files it touches only:
47
+
48
+ ```bash
49
+ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_tidy.py" --repo-root . --check --commit-range origin/<default>..HEAD
50
+ ```
51
+
52
+ (`<default>` is the default branch from Step 0. Falls back to `scripts/caddis_tidy.py` from a
53
+ source checkout; skip this step if the script is missing or the repo has no `.caddis/`.)
54
+
55
+ - Exit **0** — carry on.
56
+ - Exit **1** — **stop; do not open the PR.** Show each `CHECK VIOLATION` or `ERROR` line.
57
+ - `plan <path>: tracker done, status <s>` — run
58
+ `caddis_tidy.py --repo-root . --apply --only <path>`, `git add` the moved plan by name,
59
+ commit, and run this step again.
60
+ - `plan <path>: tracker done, but done/<name> already exists (rename one of them)` — `--apply`
61
+ cannot fix this; it changes nothing while the name is taken. Rename the plan or the old
62
+ `done/` copy with `git mv`, commit, and run this step again.
63
+ - Any other violation — fix that file's frontmatter, commit, and run this step again.
64
+ - `ERROR: uncommitted changes in files this range touched: <paths>; commit them first` — the
65
+ check reads the committed files the PR ships, so commit (or discard) those changes first.
66
+ - `ERROR: cannot read commit range <range>: <git error>`, or `commit range has an empty side`
67
+ — the range is wrong, not the files. Fix the range: name both sides, and use the remote and
68
+ default branch this repo really has (for example `upstream/master..HEAD`; check with
69
+ `git remote` and Step 0). No violation list is printed with an `ERROR`, so nothing was
70
+ checked yet.
71
+ - Only files this branch changed are checked, so problems already on the default branch never
72
+ block an unrelated PR. The owner's fleet report (`caddis-fleet-tidy.ps1`) lists those.
73
+
43
74
  ## Step 3 — Scope-guard pre-check (before the PR exists)
44
75
 
45
76
  - If the repo has a **named scope-guard workflow** (e.g. a Gitea `pr-scope-guard` that blocks PRs
@@ -53,20 +84,8 @@ are uncommitted.)
53
84
  ## Step 3b — Cross-review trigger (before anything is pushed)
54
85
 
55
86
  <!-- shared:cross-review-trigger — keep byte-identical across commands; a test pins it -->
56
- **Run the trigger, do not eyeball the diff:**
57
-
58
- ```bash
59
- python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-trigger --range <base>...HEAD
60
- ```
61
-
62
- Exit **0** — say nothing, carry on. Exit **2** — it prints which rule fired and on which files.
63
- Run `/caddis:cross-review`, show the findings, and let the user decide. It **never blocks**: this
64
- picks when to ask for a second opinion, it is not a verdict, and a review gate that blocks a ship
65
- gets switched off inside a week.
66
-
67
- It fires on SQL and repositories, `services/`, caches and refresh jobs, auth and RBAC, or a diff
68
- over 400 changed lines. No judgement in any of those — deliberately, because judgement is exactly
69
- what failed.
87
+ Run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-tier --range <base>...HEAD` and review by its tier (rule 3).
88
+ `<base>` is `origin/<default branch>` (on the default branch itself, the commit before this change). Tier 0 or 1-small: no model review. Tier 1: one `/caddis:cross-review`. Tier 2: two reviewers of two other vendors in one round. No `TIER:` line means tier 2.
70
89
  <!-- /shared:cross-review-trigger -->
71
90
 
72
91
  > **Why this is mechanical and not "consider a review here".** a fleet app shipped four
@@ -107,7 +126,8 @@ scope-guard check when present:
107
126
  ```bash
108
127
  python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_lanes.py" ci-watch --pr <pr>
109
128
  ```
110
- Exit codes: **0** pass → continue; **1** fail → read `FAILING:` and the gh output, classify, apply the minimum source fix, then re-push (through Step 4's safety if history must change); **3** could not tell → stop and report, do not merge.
129
+ `RESULT: pass` means every check of the PR's head commit is complete and green; `HEAD:` names that commit.
130
+ Exit codes: **0** pass → continue; **1** fail → read `FAILING:` and the gh output, classify, apply the minimum source fix, then re-push (through Step 4's safety if history must change); **3** could not tell (also: a check still unfinished, or the head's checks unreadable) → run `ci-watch` again; if it stays 3, stop and report, do not merge.
111
131
  Fallback when `caddis_lanes.py` is not available: watch in-session with `gh pr checks <pr> --watch` / `gh run watch` (`gh-cli` skill).
112
132
  On a red check, classify the failure and apply the minimum **source** fix, then re-push (through
113
133
  Step 4's safety if history must change).
@@ -126,7 +146,7 @@ human-confirmed door.
126
146
 
127
147
  ## Rules
128
148
  - **Never merges, never deploys** — no merge action exists in this command, by design.
129
- - Never `git add -A` without reviewing `git status` first.
149
+ - Never `git add -A`, `git add .` or `git add <dir>`, even after reading `git status`: stage named files only (the guard denies the first two).
130
150
  - Never force-push without a `backup/*-preship` recovery ref; force pushes are `--force-with-lease` only.
131
151
  - Never edit a workflow file (`.gitea/workflows/`, `.github/workflows/`) to make a gate pass — fix the source.
132
152
  - Local-only lane: refuse + point at `/ship`. On the default branch: stop + point at `/ship`.
@@ -9,9 +9,7 @@ Use this when a session is long enough that its own recall has become the risk.
9
9
  `/caddis:handoff` for that case: `/handoff` writes down what you remember, and **what you remember
10
10
  is the failure mode.**
11
11
 
12
- **Sibling, not duplicate, of `/caddis:spawn-hub`.** `spawn-hub` hands over a validation ROLE;
13
- this hands over the WORK. Both run on `scripts/caddis_spawn.py`, so a fix to the machinery lands in
14
- both.
12
+ It runs on `scripts/caddis_spawn.py`.
15
13
 
16
14
  ## The failure this exists to catch
17
15
 
@@ -333,9 +331,9 @@ Use a read-only agent that can open files and run commands (`caddis:anchor` fits
333
331
  verdict, record it, and fix any handover document it proves wrong. On a runtime with no subagents,
334
332
  grade in a fresh session and say so. Never grade from a nearly-full context.
335
333
 
336
- **ALIVE until `handshake close`; not WRITING, with two named exceptions.** `/caddis:spawn-hub`
337
- carries a single-writer rule, because two sessions committed to one repo concurrently and one's work
338
- landed inside the other's commit. Here it has exactly two exceptions: your own handover artefacts,
334
+ **ALIVE until `handshake close`; not WRITING, with two named exceptions.** The single-writer rule
335
+ exists because two sessions committed to one repo concurrently and one's work landed inside the
336
+ other's commit. It has exactly two exceptions: your own handover artefacts,
339
337
  and a document a verdict proves wrong. **Commit and push each one before you reply.** Never hold an
340
338
  uncommitted change while the child is live, because a checkout on its side can take it with no copy
341
339
  anywhere.
@@ -404,8 +402,6 @@ immediately.
404
402
  **REJECT exists because a confidently wrong successor is more dangerous than a confused one.** In
405
403
  this project the failure has never been *"I don't know"* — it has been a fluent wrong answer.
406
404
 
407
- The vocabulary matches `/caddis:validate-phase` on purpose: same discipline, different object.
408
-
409
405
  **Two REJECTs on one spawn means the HANDOVER is at fault, not the successor. Regenerate it** rather
410
406
  than coaching the child through it.
411
407
 
@@ -76,9 +76,7 @@ def freshness_lines(root: str) -> list[str]:
76
76
 
77
77
  def is_headless() -> bool:
78
78
  """True when no human is watching — a run given its task explicitly needs no resume pointer."""
79
- if str(os.environ.get("CADDIS_HEADLESS", "")).strip().lower() in _TRUTHY:
80
- return True
81
- return bool(os.environ.get("DOCKET_PLAN") or os.environ.get("DOCKET_BRANCH"))
79
+ return str(os.environ.get("CADDIS_HEADLESS", "")).strip().lower() in _TRUTHY
82
80
 
83
81
 
84
82
  def _first_existing(paths: list[str]) -> str:
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "caddis-extras",
3
- "version": "1.3.42",
3
+ "version": "1.3.43",
4
4
  "description": "caddis-extras — the long-tail skills for the Antigravity (agy) caddis plugin; install alongside caddis for the full set."
5
5
  }
@@ -53,6 +53,7 @@
53
53
  | Changelog Generator | `changelog-generator/` | Create user-facing changelogs and release notes from git commit history, grouping changes and rewriting technical commits in plain language. |
54
54
  | Deploy Local | `deploy-local/` | Local deployment loop for Gitea-hosted projects: commit on dev, push, watch the golden CI/build/deploy workflow, check prod, and fix lint/test/pipeline failures until the deploy is healthy. |
55
55
  | Monorepo | `monorepo/` | Turborepo and pnpm workspaces: turbo.json tasks, remote caching, shared packages, affected-only CI, apps/ vs packages/ layout, and pitfalls like circular deps, version drift and hoisting. |
56
+ | Runner Move | `runner-move/` | >- |
56
57
  | Safe Cleanup | `safe-cleanup/` | Use BEFORE deleting a directory tree, scratchpad or git worktree, or "tidying up" generated folders, especially on Windows, where deleting through a junction or symlink destroys its target; and to verify a venv or node_modules survived. |
57
58
  | Update Readme | `update-readme/` | Detect feature commits and update README sections (Features, API, Usage) to match, then stage only the README. Use when features, routes or components were added. |
58
59
 
@@ -61,7 +62,6 @@
61
62
  | Skill | Path | When to Use |
62
63
  |-------|------|-------------|
63
64
  | Architecture Document | `architecture-document/` | Generate enterprise HLD and LLD documents from the living Architecture.md, as DOCX (editable) or PPTX (executive summary). |
64
- | Data Lineage | `data-lineage/` | Generates End-to-End Data Lineage and Telemetry Specifications linking UI pages, API routes, database datasets, and ETL/SP producers for watch-sight observability. |
65
65
  | Doc Coauthoring | `doc-coauthoring/` | Structured workflow for co-authoring documentation: transfer context, refine by iteration, test it on readers. Use when the user is writing docs, proposals, technical specs or decision docs. |
66
66
  | Documentation Analyzer | `documentation-analyzer/` | Analyze a codebase, explain what the code does, and generate documentation such as README files. |
67
67
  | Hld | `hld/` | Generate High-Level Design (HLD) Markdown and convert it to Confluence Storage Format XHTML with PlantUML diagrams and legends. |
@@ -135,7 +135,6 @@
135
135
  | File Organizer | `file-organizer/` | Organize files and folders by context: find duplicates, suggest better structures, automate cleanup. |
136
136
  | Game Changing Features | `game-changing-features/` | Find 10x product opportunities and high-leverage features. Use when the user mentions '10x', says 'what would make this 10x better', 'product strategy', or 'what should we build next'. |
137
137
  | Golden Nuggets | `golden-nuggets/` | Extract durable tribal knowledge ('gold nuggets') from a codebase or changed files and route each to an instruction file, runbook, hub or CI review inbox. Use after a feature, fix, sprint, incident or release. |
138
- | Golden Plan | `golden-plan/` | Use when the user asks for a comprehensive multi-phase plan (full-stack, UI + backend), says 'create a plan for building X', 'plan this project', 'I need a detailed plan', 'build plan', 'implementation plan', or attaches a mockup and asks how to build it. Produces an evidence-gated plan with self-contained phase prompts and validation gates. |
139
138
  | Intent Writer | `intent-writer/` | Structure freetext ideas, backlog items, or vague requirements into a formal Intent Document that preserves user intent across the entire agent pipeline chain. |
140
139
  | Receiving Code Review | `receiving-code-review/` | Use when receiving code review feedback, before implementing it, especially if it seems unclear or wrong: verify with technical rigor, no performative agreement or blind implementation. |
141
140
  | Setup Project Ai | `setup-project-ai/` | Install or refresh the agent-agnostic harness in a project: AGENTS.md rules with CLAUDE.md shims, subagents, commands and settings. Use when setting up AI resources on a project, or the user says 'set up the harness', 'setup-project-ai', 'generate CLAUDE.md', 'onboard this project to Claude Code / Codex / agy', or runs /setup-project-ai. |
@@ -7,7 +7,7 @@ description: "Blueprint for orchestrating the agent pipeline from spec to planni
7
7
 
8
8
  ## Purpose
9
9
 
10
- Codify the **Advisory Hub** methodology: a repeatable workflow where the human operator drives a multi-agent pipeline from raw specification to production-ready code. This skill captures the exact sequence, decision points, and artefacts that emerged from real feature delivery so any future session can follow the same playbook.
10
+ Codify the **operator-led orchestration** methodology: a repeatable workflow where the human operator drives a multi-agent pipeline from raw specification to production-ready code. This skill captures the exact sequence, decision points, and artefacts that emerged from real feature delivery so any future session can follow the same playbook.
11
11
 
12
12
  ---
13
13
 
@@ -22,7 +22,7 @@ Codify the **Advisory Hub** methodology: a repeatable workflow where the human o
22
22
 
23
23
  ## Core Concepts
24
24
 
25
- ### Advisory Hub Mode
25
+ ### Operator-Led Mode
26
26
 
27
27
  The operator (human) acts as **orchestrator**. Agents act as an **advisory board** — each specialised, none acting unilaterally. The operator:
28
28
 
@@ -33,7 +33,7 @@ The operator (human) acts as **orchestrator**. Agents act as an **advisory board
33
33
 
34
34
  ```
35
35
  ┌─────────────────────────────────────────────────────────┐
36
- │ ADVISORY HUB │
36
+ │ OPERATOR-LED PIPELINE │
37
37
  │ │
38
38
  │ Operator ◄──► PRD Agent (requirements) │
39
39
  │ Operator ◄──► Architect Agent (design decisions) │
@@ -226,7 +226,7 @@ Score each identified risk:
226
226
 
227
227
  ### Stage 3: Mid-Flight Absorption (When Needed)
228
228
 
229
- **Agent:** Planner agent (or operator + Advisory Hub)
229
+ **Agent:** Planner agent (or the operator)
230
230
 
231
231
  **Purpose:** Handle changes that arrive after the plan is created but before or during implementation. This is inevitable in real projects.
232
232
 
@@ -548,7 +548,7 @@ Full command/billing decision table: `docs/guide/multi-model-workflow.md`.
548
548
  ```
549
549
  Operator opens new chat:
550
550
 
551
- "I have a feature spec in <file>. Let's use the Advisory Hub approach:
551
+ "I have a feature spec in <file>. Let's use the operator-led pipeline:
552
552
  1. Read the spec
553
553
  2. Triage quick wins (H1–H3)
554
554
  3. Implement quick wins and commit
@@ -88,7 +88,7 @@ smaller chunks; don't just raise `--max-diff-chars` without knowing the endpoint
88
88
  - **0 — REVIEW: CLEAN** → no blocking issues. Proceed.
89
89
  - **1 — REVIEW: BLOCKING** → the reviewer found blocking issues. **Read the printed findings, then FIX
90
90
  each blocking item** (or, if you judge one a false positive, state explicitly why it's safe to ignore).
91
- Re-run once. A second BLOCKING goes to the owner (rule 3).
91
+ Fix it, then re-review only the fix diff. After 3 rounds, ask the owner (rule 3).
92
92
  - **4 — error** → no verdict parsed, a git failure, or an endpoint/parse failure. Read stderr; do not
93
93
  treat this as CLEAN — investigate.
94
94
  - **3 — misconfigured** → `REVIEW_API_KEY` is unset. Set it (see Prerequisites) and re-run.
@@ -96,7 +96,10 @@ smaller chunks; don't just raise `--max-diff-chars` without knowing the endpoint
96
96
  ## Three rules: one attempt, one review
97
97
  1. **Think before you send.** Before a task goes to any coder, write its edge cases and check the facts it depends on (one query or one file read).
98
98
  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.
99
- 3. **Review once.** Use whatever reviewer is available. Stop at the first CLEAN. After two blocking reviews, ask the owner.
99
+ 3. **Review by tier.** Run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-tier --range <base>...HEAD` (add `--plan <plan> --phase <N>` inside a plan; no `TIER:` line means tier 2).
100
+ Tier 0: gates only. Tier 1-small: your self-check only. Tier 1: one review by another vendor; stop at
101
+ the first CLEAN. Tier 2: two reviewers of two other vendors, in one round. Fix blocking findings only;
102
+ park the rest. Re-review only the fix diff, and only when the fix changed logic. After 3 rounds, ask the owner.
100
103
 
101
104
  A diff over the batch ceiling is split into batches. Each batch prompt lists every file in the
102
105
  change, so a batch does not report the others as missing.