@caddis/cli 0.2.4 → 0.2.5

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 (37) hide show
  1. package/README.md +11 -0
  2. package/bundles/antigravity-plugin/agents/claude-md-curator.md +7 -4
  3. package/bundles/antigravity-plugin/plugin.json +1 -1
  4. package/bundles/antigravity-plugin/skills/_registry.md +6 -0
  5. package/bundles/antigravity-plugin/skills/advisory-hub/SKILL.md +183 -0
  6. package/bundles/antigravity-plugin/skills/advisory-hub/reference/context-template.md +214 -0
  7. package/bundles/antigravity-plugin/skills/advisory-hub/reference/hub-handbook.md +233 -0
  8. package/bundles/antigravity-plugin/skills/advisory-hub/reference/report-contract.md +94 -0
  9. package/bundles/antigravity-plugin/skills/advisory-hub/reference/succession.md +96 -0
  10. package/bundles/antigravity-plugin/skills/brainstorming/SKILL.md +1 -1
  11. package/bundles/antigravity-plugin/skills/code-review/SKILL.md +7 -0
  12. package/bundles/antigravity-plugin/skills/context-curator/SKILL.md +1 -1
  13. package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +71 -14
  14. package/bundles/antigravity-plugin/skills/dashboard-perf-sweep/SKILL.md +18 -18
  15. package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +164 -9
  16. package/bundles/antigravity-plugin/skills/gate-preflight/SKILL.md +34 -0
  17. package/bundles/antigravity-plugin/skills/gate-review/SKILL.md +36 -0
  18. package/bundles/antigravity-plugin/skills/golden-plan/SKILL.md +22 -13
  19. package/bundles/antigravity-plugin/skills/handoff/SKILL.md +78 -0
  20. package/bundles/antigravity-plugin/skills/implement/SKILL.md +182 -3
  21. package/bundles/antigravity-plugin/skills/mermaid-diagrams/SKILL.md +57 -1
  22. package/bundles/antigravity-plugin/skills/park/SKILL.md +126 -0
  23. package/bundles/antigravity-plugin/skills/prd/SKILL.md +4 -2
  24. package/bundles/antigravity-plugin/skills/preflight/SKILL.md +5 -0
  25. package/bundles/antigravity-plugin/skills/spawn-hub/SKILL.md +287 -0
  26. package/bundles/antigravity-plugin/skills/validate-phase/SKILL.md +112 -0
  27. package/bundles/antigravity-plugin/skills/writing-plans/SKILL.md +7 -4
  28. package/bundles/antigravity-plugin/warm_start_agy.py +28 -2
  29. package/bundles/antigravity-plugin-extras/plugin.json +1 -1
  30. package/bundles/antigravity-plugin-extras/skills/agent-orchestration/SKILL.md +9 -9
  31. package/bundles/antigravity-plugin-extras/skills/cross-review/SKILL.md +56 -6
  32. package/bundles/antigravity-plugin-extras/skills/requesting-code-review/SKILL.md +1 -1
  33. package/bundles/antigravity-plugin-extras/skills/schema-migration/SKILL.md +2 -2
  34. package/bundles/antigravity-plugin-extras/skills/state-tracking/SKILL.md +4 -4
  35. package/bundles/manifest.json +3 -3
  36. package/dist/cli.js +55 -4
  37. package/package.json +1 -1
@@ -14,6 +14,27 @@ issue. This skill runs that second reviewer over the current changes and acts on
14
14
  - On a risky diff (auth, crypto, data-touching, concurrency) where a second opinion is cheap insurance.
15
15
  - NOT a replacement for the in-repo `/caddis:code-review` — this is the *cross-vendor* complement.
16
16
 
17
+ ## Check the key FIRST, and ask if it is missing
18
+
19
+ ```bash
20
+ python "$TOOL" --check-config
21
+ ```
22
+
23
+ Exit 0 prints which providers have a key. **Exit 3 means nothing is configured — stop and ask the
24
+ user before reading any diff.** Do not proceed, and do not silently skip the review.
25
+
26
+ Ask with `AskUserQuestion` which provider to set up, then write the key to `~/.caddis/keys.env` as
27
+ `DEEPSEEK_API_KEY=<key>` (or the matching variable). That file sits outside every git repo, so it
28
+ cannot be committed by accident. **Never put a key in the repo, in a command, or in a reply.**
29
+
30
+ This used to fail mid-task with a commit pending — the worst moment to go hunting for a credential.
31
+ A command that fails once at an inconvenient moment does not get retried, so the safety check is
32
+ quietly lost and nothing records the loss. The script stays non-interactive because it also runs
33
+ headless, where a stdin prompt hangs instead of asking; the asking is the agent's job.
34
+
35
+ If a key exists for a *different* provider than the one requested, the error names it and gives the
36
+ exact flag (`--provider glm`). Read the message before concluding anything is missing.
37
+
17
38
  ## Prerequisites (one-time)
18
39
  Only the key is mandatory — the tool ships **provider presets** (default `deepseek`, the cheapest + most
19
40
  architecturally distinct-from-Claude option; a review costs well under a cent):
@@ -28,16 +49,41 @@ churn — the preset table in `oss_review.py` is the one place to edit a rename,
28
49
  `REVIEW_BASE_URL` always win, so you can point at any new id without touching code.
29
50
 
30
51
  ## How to run
31
- From the repo root. Locate the tool, in order:
32
- - `.github/tools/oss_review.py` — this project vendors its own copy.
33
- - `${CLAUDE_PLUGIN_ROOT}/scripts/oss_review.py` — the plugin-bundled copy (every Claude Code
34
- install has this; use it whenever the project has no local copy).
52
+ From the repo root. Resolve the tool path deterministically — check only these two exact
53
+ locations, in order, and **never search the filesystem for it** (see Rules below):
54
+ ```bash
55
+ # THE PLUGIN COPY WINS. It is the one `caddis update` refreshes; a vendored copy is a snapshot
56
+ # of whatever caddis shipped the day someone copied it, and it never updates again.
57
+ if [ -f "${CLAUDE_PLUGIN_ROOT}/scripts/oss_review.py" ]; then
58
+ TOOL="${CLAUDE_PLUGIN_ROOT}/scripts/oss_review.py"
59
+ # A vendored copy that DIFFERS is a live hazard, not a curiosity — say so, do not stay silent.
60
+ if [ -f ".github/tools/oss_review.py" ] && ! diff -q ".github/tools/oss_review.py" "$TOOL" >/dev/null 2>&1; then
61
+ echo "[cross-review] WARNING: .github/tools/oss_review.py differs from the caddis copy and is"
62
+ echo " being IGNORED. Delete it, or keep the local change deliberately."
63
+ fi
64
+ elif [ -f ".github/tools/oss_review.py" ]; then
65
+ TOOL=".github/tools/oss_review.py" # no plugin present — the vendored copy is all there is
66
+ else
67
+ echo "oss_review.py not found at either known location — report this and stop. Do NOT search for it."
68
+ exit 3
69
+ fi
35
70
  ```
36
- python <resolved-path>/oss_review.py # review the working tree (staged+unstaged)
37
- python <resolved-path>/oss_review.py --range origin/main..HEAD # review a branch's commits
71
+
72
+ > **Why the plugin copy is first.** It used to be second. On 2026-08-10 a repo ran a stale vendored
73
+ > `oss_review.py` and got `REVIEW: CLEAN` on a database write path that was never reviewed. The bug
74
+ > had been fixed on 2026-08-01 — the fix just never reached the caller, because a file someone
75
+ > copied weeks earlier silently won. `caddis_gate.py vendor-drift` now fails on the same condition.
76
+ ```
77
+ python "$TOOL" # review the working tree (staged+unstaged)
78
+ python "$TOOL" --range origin/main..HEAD # review a branch's commits
38
79
  ```
39
80
  Optional flags: `--cwd <repo>`, `--base-url <url>`, `--model <id>` (override the env).
40
81
 
82
+ **Diff-size ceiling.** A diff over `REVIEW_MAX_DIFF_CHARS` (default 60,000 chars) is **split into batches** on whole-file boundaries and each batch reviewed separately (verdict is CLEAN only if every batch is). Exit 2 now means a *single unsplittable file* over the ceiling, or too many batches — not an ordinary large diff. Previously it was refused with exit 2
83
+ *before* any LLM call — an oversized diff has been observed to come back either an empty response, or
84
+ worse, a `REVIEW: CLEAN` with zero real engagement. If you hit this, narrow `--range` or review in
85
+ smaller chunks; don't just raise `--max-diff-chars` without knowing the endpoint's real limit.
86
+
41
87
  ## Interpret the exit code
42
88
  - **0 — REVIEW: CLEAN** → no blocking issues. Proceed.
43
89
  - **1 — REVIEW: BLOCKING** → the reviewer found blocking issues. **Read the printed findings, then FIX
@@ -52,3 +98,7 @@ Optional flags: `--cwd <repo>`, `--base-url <url>`, `--model <id>` (override the
52
98
  the main thread after reading the findings.
53
99
  - Treat exit 2/3 as blocking-unknown, never as approval (the tool is fail-closed by design).
54
100
  - Different vendor ⇒ different style; weigh its findings on merit, don't cargo-cult them.
101
+ - **Never use `find`, `Get-ChildItem -Recurse`, or any other filesystem-wide search to locate
102
+ `oss_review.py`.** Check only the two paths above. On Git Bash under Windows, `find /` (or any
103
+ search rooted at `/`) walks every mounted drive, not just the repo — it can hang or take minutes.
104
+ If neither path exists, stop and report it; don't go hunting for the file.
@@ -58,7 +58,7 @@ HEAD_SHA=$(git rev-parse HEAD)
58
58
 
59
59
  [Dispatch superpowers:code-reviewer subagent]
60
60
  WHAT_WAS_IMPLEMENTED: Verification and repair functions for conversation index
61
- PLAN_OR_REQUIREMENTS: Task 2 from docs/plans/deployment-plan.md
61
+ PLAN_OR_REQUIREMENTS: Task 2 from .caddis/plans/deployment-plan.md
62
62
  BASE_SHA: a7981ec
63
63
  HEAD_SHA: 3df7661
64
64
  DESCRIPTION: Added verifyIndex() and repairIndex() with 4 issue types
@@ -24,7 +24,7 @@ Systematically migrate an application from a legacy database schema to a new sch
24
24
  1. **Read-Only** — Never execute DDL or DML (`CREATE`, `ALTER`, `INSERT`, `UPDATE`, `DELETE`) against the database. All analysis is SELECT-only.
25
25
  2. **No SQL Aliases** — Proposed queries must use direct `Table.Column` notation. Aliases obscure the mapping and make future changes harder to trace.
26
26
  3. **No Assumptions** — Every column mapping must be verified against the actual schema DDL. If a mapping is ambiguous or a source column has no clear target, flag it as a **GAP** rather than guessing.
27
- 4. **Scratchpad Protocol** — If context becomes large, save intermediate findings to `.github/plans/temp_migration_scratchpad.md` to preserve state across reasoning steps.
27
+ 4. **Scratchpad Protocol** — If context becomes large, save intermediate findings to `.caddis/plans/temp_migration_scratchpad.md` to preserve state across reasoning steps.
28
28
 
29
29
  ---
30
30
 
@@ -255,7 +255,7 @@ Produce a single, comprehensive document suitable for use as an **Implementation
255
255
  ```
256
256
 
257
257
  ### Output Location
258
- Place the final report at the path specified by the user (default: `.github/plans/backlog/migration_report.md`).
258
+ Place the final report at the path specified by the user (default: `.caddis/agent-docs/migration_report.md` — it is an agent-produced report, not a backlog item).
259
259
 
260
260
  ---
261
261
 
@@ -23,7 +23,7 @@ State tracking uses two distinct documents with different write semantics:
23
23
 
24
24
  | Document | Write mode | Purpose |
25
25
  |----------|-----------|---------|
26
- | **Plan Tracker** (`.github/plans/tracker/<slug>-tracker.md`) | Overwrite each row | Per-phase completion record, linked to commits |
26
+ | **Plan Tracker** (`.caddis/plans/tracker/<slug>-tracker.md`) | Overwrite each row | Per-phase completion record, linked to commits |
27
27
  | **CURRENT_STATE** (`.github/agent-docs/CURRENT_STATE.md`) | Overwrite head section | Single-view of right now: what phase, what's done, what's blocked |
28
28
  | **Session Log** (inline in CURRENT_STATE, append-only) | Append only | Chronological audit trail — never rewrite past entries |
29
29
 
@@ -42,8 +42,8 @@ Replace this section wholesale each time:
42
42
  ```markdown
43
43
  ## Current Status
44
44
 
45
- **Plan:** `.github/plans/<feature-slug>.md`
46
- **Tracker:** `.github/plans/tracker/<feature-slug>-tracker.md`
45
+ **Plan:** `.caddis/plans/<feature-slug>.md`
46
+ **Tracker:** `.caddis/plans/tracker/<feature-slug>-tracker.md`
47
47
  **Last updated:** YYYY-MM-DDTHH:MM:SSZ
48
48
  **Active agent:** @[Agent] (model: [Model])
49
49
  **Current phase:** Phase N — [Name]
@@ -116,7 +116,7 @@ The canonical template is at `.github/agent-docs/CURRENT_STATE.md`. Copy it for
116
116
  ## Integration with Golden-Plan
117
117
 
118
118
  When running a golden-plan:
119
- - The plan tracker (`.github/plans/tracker/<slug>-tracker.md`) is the commitment ledger.
119
+ - The plan tracker (`.caddis/plans/tracker/<slug>-tracker.md`) is the commitment ledger.
120
120
  - CURRENT_STATE.md is the working scratch-pad for the current session.
121
121
  - After completing a phase, update BOTH the tracker row AND the CURRENT_STATE current-status section.
122
122
  - When all tracker rows are `Complete`, follow the Plan Completion Protocol in golden-plan: move the plan to `plans/done/`, set `status: done`.
@@ -1,7 +1,7 @@
1
1
  {
2
- "poolVersion": "1.3.54",
2
+ "poolVersion": "1.3.74",
3
3
  "bundles": {
4
- "antigravity-plugin": "1.3.54",
5
- "antigravity-plugin-extras": "1.3.20"
4
+ "antigravity-plugin": "1.3.74",
5
+ "antigravity-plugin-extras": "1.3.24"
6
6
  }
7
7
  }
package/dist/cli.js CHANGED
@@ -4527,6 +4527,32 @@ var init_drive = __esm({
4527
4527
  }
4528
4528
  });
4529
4529
 
4530
+ // src/util/semver.ts
4531
+ function compareVersions(a, b3) {
4532
+ const pa = parse(a);
4533
+ const pb = parse(b3);
4534
+ if (!pa || !pb) return null;
4535
+ for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
4536
+ const da = pa[i] ?? 0;
4537
+ const db = pb[i] ?? 0;
4538
+ if (da > db) return 1;
4539
+ if (da < db) return -1;
4540
+ }
4541
+ return 0;
4542
+ }
4543
+ function parse(v) {
4544
+ if (!v || v === "unknown") return null;
4545
+ const core = v.trim().replace(/^v/, "").split(/[-+]/)[0] ?? "";
4546
+ const parts = core.split(".");
4547
+ if (parts.length === 0 || parts.some((p2) => p2 === "" || !/^\d+$/.test(p2))) return null;
4548
+ return parts.map((p2) => Number.parseInt(p2, 10));
4549
+ }
4550
+ var init_semver = __esm({
4551
+ "src/util/semver.ts"() {
4552
+ "use strict";
4553
+ }
4554
+ });
4555
+
4530
4556
  // src/commands/report.ts
4531
4557
  async function checkCliUpdate(currentVersion) {
4532
4558
  const result = await run("npm", ["view", "@caddis/cli", "version"], { timeout: 5e3 });
@@ -4541,7 +4567,10 @@ function classify(adapter, detection, status4, poolVersion) {
4541
4567
  if (!status4.installed) return "missing";
4542
4568
  if (!status4.version) return "unknown";
4543
4569
  if (poolVersion === "unknown") return "unknown";
4544
- return status4.version === poolVersion ? "current" : "stale";
4570
+ const order = compareVersions(status4.version, poolVersion);
4571
+ if (order === null) return status4.version === poolVersion ? "current" : "stale";
4572
+ if (order === 0) return "current";
4573
+ return order > 0 ? "ahead" : "stale";
4545
4574
  }
4546
4575
  async function gather(adapters, options = {}) {
4547
4576
  const manifest = bundleManifest();
@@ -4578,6 +4607,7 @@ function actionable(report, includeCurrent = false) {
4578
4607
  return report.agents.filter((entry) => {
4579
4608
  if (!entry.detection.present || !entry.adapter.supported) return false;
4580
4609
  if (includeCurrent) return true;
4610
+ if (entry.drift === "ahead") return false;
4581
4611
  return entry.drift !== "current" || entry.extrasDrift === "stale" || entry.extrasDrift === "unknown";
4582
4612
  });
4583
4613
  }
@@ -4586,6 +4616,7 @@ var init_report = __esm({
4586
4616
  "use strict";
4587
4617
  init_exec();
4588
4618
  init_pkg();
4619
+ init_semver();
4589
4620
  }
4590
4621
  });
4591
4622
 
@@ -4671,10 +4702,18 @@ async function update(options) {
4671
4702
  const targets = actionable(report, options.force === true);
4672
4703
  if (targets.length === 0) {
4673
4704
  const supportedPresent = report.agents.filter((e2) => e2.detection.present && e2.adapter.supported);
4705
+ const ahead = report.agents.filter((e2) => e2.drift === "ahead");
4674
4706
  line("");
4675
- line(
4676
- supportedPresent.length === 0 ? ` ${color.yellow("No supported agent found.")} caddis v0.1 drives Claude Code and agy.` : ` ${color.green("Everything is already current.")} Use --force to re-drive anyway.`
4677
- );
4707
+ if (supportedPresent.length === 0) {
4708
+ line(` ${color.yellow("No supported agent found.")} caddis v0.1 drives Claude Code and agy.`);
4709
+ } else if (ahead.length > 0) {
4710
+ line(
4711
+ ` ${color.green("Nothing to do.")} ${ahead.length} agent(s) are NEWER than this package's bundled pool (${report.poolVersion}) \u2014 driving them would be a DOWNGRADE, so they were left alone.`
4712
+ );
4713
+ line(` Update the CLI itself (${color.cyan("npm i -g @caddis/cli")}), or ${color.cyan("--force")} to roll back deliberately.`);
4714
+ } else {
4715
+ line(` ${color.green("Everything is already current.")} Use --force to re-drive anyway.`);
4716
+ }
4678
4717
  return 0;
4679
4718
  }
4680
4719
  line("");
@@ -4805,6 +4844,7 @@ function renderSummary(report, findings) {
4805
4844
  function markFor(drift) {
4806
4845
  switch (drift) {
4807
4846
  case "current":
4847
+ case "ahead":
4808
4848
  return "ok";
4809
4849
  case "stale":
4810
4850
  case "missing":
@@ -4820,6 +4860,8 @@ function describe(entry, poolVersion) {
4820
4860
  switch (entry.drift) {
4821
4861
  case "current":
4822
4862
  return `caddis ${entry.status.version} ${color.dim("(current)")}`;
4863
+ case "ahead":
4864
+ return `caddis ${color.green(entry.status.version ?? "?")} ${color.dim("\u2014 newer than this CLI bundles")} ${color.dim(`(${poolVersion}); left alone, update @caddis/cli to catch up`)}`;
4823
4865
  case "stale":
4824
4866
  return `caddis ${color.yellow(entry.status.version ?? "?")} ${color.dim("\u2192")} ${color.bold(poolVersion)} available`;
4825
4867
  case "unknown":
@@ -4986,10 +5028,17 @@ async function status3(options) {
4986
5028
  const stale = report.agents.filter(
4987
5029
  (entry) => entry.drift === "stale" || entry.drift === "missing" || entry.extrasDrift === "stale"
4988
5030
  );
5031
+ const ahead = report.agents.filter((entry) => entry.drift === "ahead");
4989
5032
  if (stale.length > 0) {
4990
5033
  line(` ${color.yellow(`${stale.length} agent(s) behind`)} \u2014 run ${color.cyan("caddis update")} (or ${color.cyan("caddis doctor")} for detail)`);
4991
5034
  line("");
4992
5035
  }
5036
+ if (ahead.length > 0) {
5037
+ line(
5038
+ ` ${ahead.length} agent(s) are NEWER than this CLI's bundled pool (${report.poolVersion}) \u2014 left alone. Update the CLI itself (${color.cyan("npm i -g @caddis/cli")}) to catch up.`
5039
+ );
5040
+ line("");
5041
+ }
4993
5042
  return 0;
4994
5043
  }
4995
5044
  function toRow(entry) {
@@ -5010,6 +5059,8 @@ function stateLabel(drift, disabled) {
5010
5059
  return disabled ? color.yellow("current, disabled") : color.green("current");
5011
5060
  case "stale":
5012
5061
  return color.yellow("update available");
5062
+ case "ahead":
5063
+ return color.green("newer than CLI pool");
5013
5064
  case "unknown":
5014
5065
  return color.yellow("version unknown");
5015
5066
  case "missing":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caddis/cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Install, update and diagnose the caddis dev harness across every coding agent you use (Claude Code, agy/Antigravity, and more).",
5
5
  "keywords": [
6
6
  "caddis",