@caddis/cli 0.2.3 → 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.
- package/README.md +11 -0
- package/bundles/antigravity-plugin/agents/anchor.md +60 -0
- package/bundles/antigravity-plugin/agents/claude-md-curator.md +144 -0
- package/bundles/antigravity-plugin/agents/codebase-audit.md +53 -0
- package/bundles/antigravity-plugin/agents/data-engineer.md +51 -0
- package/bundles/antigravity-plugin/agents/debug.md +48 -0
- package/bundles/antigravity-plugin/agents/knowledge-transfer.md +139 -0
- package/bundles/antigravity-plugin/agents/security-analyst.md +49 -0
- package/bundles/antigravity-plugin/agents/sql-expert.md +46 -0
- package/bundles/antigravity-plugin/agents/tester.md +45 -0
- package/bundles/antigravity-plugin/agents/ui-design-reviewer.md +110 -0
- package/bundles/antigravity-plugin/plugin.json +1 -1
- package/bundles/antigravity-plugin/skills/_registry.md +6 -0
- package/bundles/antigravity-plugin/skills/advisory-hub/SKILL.md +183 -0
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/context-template.md +214 -0
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/hub-handbook.md +233 -0
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/report-contract.md +94 -0
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/succession.md +96 -0
- package/bundles/antigravity-plugin/skills/brainstorming/SKILL.md +1 -1
- package/bundles/antigravity-plugin/skills/code-review/SKILL.md +7 -0
- package/bundles/antigravity-plugin/skills/context-curator/SKILL.md +1 -1
- package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +71 -14
- package/bundles/antigravity-plugin/skills/dashboard-perf-sweep/SKILL.md +18 -18
- package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +164 -9
- package/bundles/antigravity-plugin/skills/gate-preflight/SKILL.md +34 -0
- package/bundles/antigravity-plugin/skills/gate-review/SKILL.md +36 -0
- package/bundles/antigravity-plugin/skills/golden-plan/SKILL.md +22 -13
- package/bundles/antigravity-plugin/skills/handoff/SKILL.md +78 -0
- package/bundles/antigravity-plugin/skills/implement/SKILL.md +182 -3
- package/bundles/antigravity-plugin/skills/mermaid-diagrams/SKILL.md +57 -1
- package/bundles/antigravity-plugin/skills/park/SKILL.md +126 -0
- package/bundles/antigravity-plugin/skills/prd/SKILL.md +4 -2
- package/bundles/antigravity-plugin/skills/preflight/SKILL.md +5 -0
- package/bundles/antigravity-plugin/skills/spawn-hub/SKILL.md +287 -0
- package/bundles/antigravity-plugin/skills/validate-phase/SKILL.md +112 -0
- package/bundles/antigravity-plugin/skills/writing-plans/SKILL.md +7 -4
- package/bundles/antigravity-plugin/warm_start_agy.py +35 -6
- package/bundles/antigravity-plugin-extras/plugin.json +1 -1
- package/bundles/antigravity-plugin-extras/skills/agent-orchestration/SKILL.md +9 -9
- package/bundles/antigravity-plugin-extras/skills/cross-review/SKILL.md +56 -6
- package/bundles/antigravity-plugin-extras/skills/requesting-code-review/SKILL.md +1 -1
- package/bundles/antigravity-plugin-extras/skills/schema-migration/SKILL.md +2 -2
- package/bundles/antigravity-plugin-extras/skills/state-tracking/SKILL.md +4 -4
- package/bundles/manifest.json +3 -3
- package/dist/cli.js +143 -59
- 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.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
|
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 `.
|
|
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: `.
|
|
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** (`.
|
|
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:** `.
|
|
46
|
-
**Tracker:** `.
|
|
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 (`.
|
|
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`.
|
package/bundles/manifest.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -3473,6 +3473,51 @@ var require_commander = __commonJS({
|
|
|
3473
3473
|
}
|
|
3474
3474
|
});
|
|
3475
3475
|
|
|
3476
|
+
// src/util/exec.ts
|
|
3477
|
+
async function run(cmd, args, opts = {}) {
|
|
3478
|
+
const { execa } = await import("execa");
|
|
3479
|
+
try {
|
|
3480
|
+
const result = await execa(cmd, args, {
|
|
3481
|
+
cwd: opts.cwd,
|
|
3482
|
+
timeout: opts.timeout ?? DEFAULT_TIMEOUT_MS,
|
|
3483
|
+
env: opts.env,
|
|
3484
|
+
reject: false,
|
|
3485
|
+
all: false,
|
|
3486
|
+
stripFinalNewline: true,
|
|
3487
|
+
// Windows: resolve .cmd/.ps1 shims through the shell-less path lookup
|
|
3488
|
+
// execa already does, but be explicit that we are not using a shell.
|
|
3489
|
+
shell: false,
|
|
3490
|
+
windowsHide: true
|
|
3491
|
+
});
|
|
3492
|
+
return {
|
|
3493
|
+
ok: result.exitCode === 0 && !result.failed,
|
|
3494
|
+
code: result.exitCode ?? null,
|
|
3495
|
+
stdout: String(result.stdout ?? ""),
|
|
3496
|
+
stderr: String(result.stderr ?? ""),
|
|
3497
|
+
failure: result.failed && result.exitCode === void 0 ? result.shortMessage : void 0
|
|
3498
|
+
};
|
|
3499
|
+
} catch (error) {
|
|
3500
|
+
return {
|
|
3501
|
+
ok: false,
|
|
3502
|
+
code: null,
|
|
3503
|
+
stdout: "",
|
|
3504
|
+
stderr: "",
|
|
3505
|
+
failure: error instanceof Error ? error.message : String(error)
|
|
3506
|
+
};
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
function formatCommand(cmd, args) {
|
|
3510
|
+
const quoted = args.map((a) => /\s/.test(a) ? `"${a}"` : a);
|
|
3511
|
+
return [cmd, ...quoted].join(" ");
|
|
3512
|
+
}
|
|
3513
|
+
var DEFAULT_TIMEOUT_MS;
|
|
3514
|
+
var init_exec = __esm({
|
|
3515
|
+
"src/util/exec.ts"() {
|
|
3516
|
+
"use strict";
|
|
3517
|
+
DEFAULT_TIMEOUT_MS = 12e4;
|
|
3518
|
+
}
|
|
3519
|
+
});
|
|
3520
|
+
|
|
3476
3521
|
// node_modules/isexe/dist/commonjs/index.min.js
|
|
3477
3522
|
var require_index_min = __commonJS({
|
|
3478
3523
|
"node_modules/isexe/dist/commonjs/index.min.js"(exports) {
|
|
@@ -4482,33 +4527,73 @@ var init_drive = __esm({
|
|
|
4482
4527
|
}
|
|
4483
4528
|
});
|
|
4484
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
|
+
|
|
4485
4556
|
// src/commands/report.ts
|
|
4557
|
+
async function checkCliUpdate(currentVersion) {
|
|
4558
|
+
const result = await run("npm", ["view", "@caddis/cli", "version"], { timeout: 5e3 });
|
|
4559
|
+
if (!result.ok) return null;
|
|
4560
|
+
const latest = result.stdout.trim();
|
|
4561
|
+
if (!latest || latest === currentVersion) return null;
|
|
4562
|
+
return { current: currentVersion, latest };
|
|
4563
|
+
}
|
|
4486
4564
|
function classify(adapter, detection, status4, poolVersion) {
|
|
4487
4565
|
if (!detection.present) return "absent";
|
|
4488
4566
|
if (!adapter.supported) return "unsupported";
|
|
4489
4567
|
if (!status4.installed) return "missing";
|
|
4490
4568
|
if (!status4.version) return "unknown";
|
|
4491
4569
|
if (poolVersion === "unknown") return "unknown";
|
|
4492
|
-
|
|
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";
|
|
4493
4574
|
}
|
|
4494
|
-
async function gather(adapters) {
|
|
4575
|
+
async function gather(adapters, options = {}) {
|
|
4495
4576
|
const manifest = bundleManifest();
|
|
4496
4577
|
const poolVersion = manifest.poolVersion;
|
|
4497
4578
|
const extrasVersion = manifest.bundles["antigravity-plugin-extras"];
|
|
4498
|
-
const
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
adapter,
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4579
|
+
const cliVersion = packageInfo().version;
|
|
4580
|
+
const [agents, cliUpdate] = await Promise.all([
|
|
4581
|
+
Promise.all(
|
|
4582
|
+
adapters.map(async (adapter) => {
|
|
4583
|
+
const detection = await adapter.detect();
|
|
4584
|
+
const status4 = detection.present ? await adapter.status() : { installed: false, note: "agent not installed" };
|
|
4585
|
+
return {
|
|
4586
|
+
adapter,
|
|
4587
|
+
detection,
|
|
4588
|
+
status: status4,
|
|
4589
|
+
drift: classify(adapter, detection, status4, poolVersion),
|
|
4590
|
+
extrasDrift: classifyExtras(adapter, detection, status4, extrasVersion)
|
|
4591
|
+
};
|
|
4592
|
+
})
|
|
4593
|
+
),
|
|
4594
|
+
options.checkCliUpdate ? checkCliUpdate(cliVersion) : Promise.resolve(null)
|
|
4595
|
+
]);
|
|
4596
|
+
return { cliVersion, poolVersion, extrasVersion, agents, cliUpdate: cliUpdate ?? void 0 };
|
|
4512
4597
|
}
|
|
4513
4598
|
function classifyExtras(adapter, detection, status4, extrasVersion) {
|
|
4514
4599
|
if (!status4.extras) return void 0;
|
|
@@ -4522,13 +4607,16 @@ function actionable(report, includeCurrent = false) {
|
|
|
4522
4607
|
return report.agents.filter((entry) => {
|
|
4523
4608
|
if (!entry.detection.present || !entry.adapter.supported) return false;
|
|
4524
4609
|
if (includeCurrent) return true;
|
|
4610
|
+
if (entry.drift === "ahead") return false;
|
|
4525
4611
|
return entry.drift !== "current" || entry.extrasDrift === "stale" || entry.extrasDrift === "unknown";
|
|
4526
4612
|
});
|
|
4527
4613
|
}
|
|
4528
4614
|
var init_report = __esm({
|
|
4529
4615
|
"src/commands/report.ts"() {
|
|
4530
4616
|
"use strict";
|
|
4617
|
+
init_exec();
|
|
4531
4618
|
init_pkg();
|
|
4619
|
+
init_semver();
|
|
4532
4620
|
}
|
|
4533
4621
|
});
|
|
4534
4622
|
|
|
@@ -4614,10 +4702,18 @@ async function update(options) {
|
|
|
4614
4702
|
const targets = actionable(report, options.force === true);
|
|
4615
4703
|
if (targets.length === 0) {
|
|
4616
4704
|
const supportedPresent = report.agents.filter((e2) => e2.detection.present && e2.adapter.supported);
|
|
4705
|
+
const ahead = report.agents.filter((e2) => e2.drift === "ahead");
|
|
4617
4706
|
line("");
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
)
|
|
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
|
+
}
|
|
4621
4717
|
return 0;
|
|
4622
4718
|
}
|
|
4623
4719
|
line("");
|
|
@@ -4646,7 +4742,7 @@ __export(doctor_exports, {
|
|
|
4646
4742
|
import os3 from "os";
|
|
4647
4743
|
import process2 from "process";
|
|
4648
4744
|
async function doctor(options) {
|
|
4649
|
-
const report = await gather(options.adapters);
|
|
4745
|
+
const report = await gather(options.adapters, { checkCliUpdate: true });
|
|
4650
4746
|
const findings = [];
|
|
4651
4747
|
if (options.json) {
|
|
4652
4748
|
line(JSON.stringify(toJson(report), null, 2));
|
|
@@ -4667,7 +4763,17 @@ function renderEnvironment(report, problems) {
|
|
|
4667
4763
|
problems.push({ kind: "problem", text: `node ${process2.versions.node} is below the required ${REQUIRED_NODE_MAJOR}.${REQUIRED_NODE_MINOR}`, fix: "upgrade node" });
|
|
4668
4764
|
}
|
|
4669
4765
|
item("info", `platform ${process2.platform} ${process2.arch} (${os3.release()})`);
|
|
4670
|
-
|
|
4766
|
+
if (report.cliUpdate) {
|
|
4767
|
+
item("warn", `@caddis/cli ${report.cliVersion} ${color.dim("\u2192")} ${color.bold(report.cliUpdate.latest)} available`);
|
|
4768
|
+
detail("everything below is compared against the pool THIS install carries, which is now behind the published one");
|
|
4769
|
+
problems.push({
|
|
4770
|
+
kind: "problem",
|
|
4771
|
+
text: `@caddis/cli itself is behind: ${report.cliUpdate.current} installed, ${report.cliUpdate.latest} published`,
|
|
4772
|
+
fix: "npm i -g @caddis/cli@latest"
|
|
4773
|
+
});
|
|
4774
|
+
} else {
|
|
4775
|
+
item("ok", `@caddis/cli ${report.cliVersion}`);
|
|
4776
|
+
}
|
|
4671
4777
|
const manifest = bundleManifest();
|
|
4672
4778
|
if (report.poolVersion === "unknown") {
|
|
4673
4779
|
item("fail", "shipped pool version unknown");
|
|
@@ -4738,6 +4844,7 @@ function renderSummary(report, findings) {
|
|
|
4738
4844
|
function markFor(drift) {
|
|
4739
4845
|
switch (drift) {
|
|
4740
4846
|
case "current":
|
|
4847
|
+
case "ahead":
|
|
4741
4848
|
return "ok";
|
|
4742
4849
|
case "stale":
|
|
4743
4850
|
case "missing":
|
|
@@ -4753,6 +4860,8 @@ function describe(entry, poolVersion) {
|
|
|
4753
4860
|
switch (entry.drift) {
|
|
4754
4861
|
case "current":
|
|
4755
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`)}`;
|
|
4756
4865
|
case "stale":
|
|
4757
4866
|
return `caddis ${color.yellow(entry.status.version ?? "?")} ${color.dim("\u2192")} ${color.bold(poolVersion)} available`;
|
|
4758
4867
|
case "unknown":
|
|
@@ -4837,6 +4946,7 @@ function problemFor(entry, poolVersion) {
|
|
|
4837
4946
|
function toJson(report) {
|
|
4838
4947
|
return {
|
|
4839
4948
|
cliVersion: report.cliVersion,
|
|
4949
|
+
cliUpdate: report.cliUpdate ?? null,
|
|
4840
4950
|
poolVersion: report.poolVersion,
|
|
4841
4951
|
extrasVersion: report.extrasVersion ?? null,
|
|
4842
4952
|
node: process2.versions.node,
|
|
@@ -4918,10 +5028,17 @@ async function status3(options) {
|
|
|
4918
5028
|
const stale = report.agents.filter(
|
|
4919
5029
|
(entry) => entry.drift === "stale" || entry.drift === "missing" || entry.extrasDrift === "stale"
|
|
4920
5030
|
);
|
|
5031
|
+
const ahead = report.agents.filter((entry) => entry.drift === "ahead");
|
|
4921
5032
|
if (stale.length > 0) {
|
|
4922
5033
|
line(` ${color.yellow(`${stale.length} agent(s) behind`)} \u2014 run ${color.cyan("caddis update")} (or ${color.cyan("caddis doctor")} for detail)`);
|
|
4923
5034
|
line("");
|
|
4924
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
|
+
}
|
|
4925
5042
|
return 0;
|
|
4926
5043
|
}
|
|
4927
5044
|
function toRow(entry) {
|
|
@@ -4942,6 +5059,8 @@ function stateLabel(drift, disabled) {
|
|
|
4942
5059
|
return disabled ? color.yellow("current, disabled") : color.green("current");
|
|
4943
5060
|
case "stale":
|
|
4944
5061
|
return color.yellow("update available");
|
|
5062
|
+
case "ahead":
|
|
5063
|
+
return color.green("newer than CLI pool");
|
|
4945
5064
|
case "unknown":
|
|
4946
5065
|
return color.yellow("version unknown");
|
|
4947
5066
|
case "missing":
|
|
@@ -4990,44 +5109,8 @@ var {
|
|
|
4990
5109
|
Help
|
|
4991
5110
|
} = import_index.default;
|
|
4992
5111
|
|
|
4993
|
-
// src/
|
|
4994
|
-
|
|
4995
|
-
async function run(cmd, args, opts = {}) {
|
|
4996
|
-
const { execa } = await import("execa");
|
|
4997
|
-
try {
|
|
4998
|
-
const result = await execa(cmd, args, {
|
|
4999
|
-
cwd: opts.cwd,
|
|
5000
|
-
timeout: opts.timeout ?? DEFAULT_TIMEOUT_MS,
|
|
5001
|
-
env: opts.env,
|
|
5002
|
-
reject: false,
|
|
5003
|
-
all: false,
|
|
5004
|
-
stripFinalNewline: true,
|
|
5005
|
-
// Windows: resolve .cmd/.ps1 shims through the shell-less path lookup
|
|
5006
|
-
// execa already does, but be explicit that we are not using a shell.
|
|
5007
|
-
shell: false,
|
|
5008
|
-
windowsHide: true
|
|
5009
|
-
});
|
|
5010
|
-
return {
|
|
5011
|
-
ok: result.exitCode === 0 && !result.failed,
|
|
5012
|
-
code: result.exitCode ?? null,
|
|
5013
|
-
stdout: String(result.stdout ?? ""),
|
|
5014
|
-
stderr: String(result.stderr ?? ""),
|
|
5015
|
-
failure: result.failed && result.exitCode === void 0 ? result.shortMessage : void 0
|
|
5016
|
-
};
|
|
5017
|
-
} catch (error) {
|
|
5018
|
-
return {
|
|
5019
|
-
ok: false,
|
|
5020
|
-
code: null,
|
|
5021
|
-
stdout: "",
|
|
5022
|
-
stderr: "",
|
|
5023
|
-
failure: error instanceof Error ? error.message : String(error)
|
|
5024
|
-
};
|
|
5025
|
-
}
|
|
5026
|
-
}
|
|
5027
|
-
function formatCommand(cmd, args) {
|
|
5028
|
-
const quoted = args.map((a) => /\s/.test(a) ? `"${a}"` : a);
|
|
5029
|
-
return [cmd, ...quoted].join(" ");
|
|
5030
|
-
}
|
|
5112
|
+
// src/agents/claude.ts
|
|
5113
|
+
init_exec();
|
|
5031
5114
|
|
|
5032
5115
|
// src/util/which.ts
|
|
5033
5116
|
var import_which = __toESM(require_lib(), 1);
|
|
@@ -5167,6 +5250,7 @@ var claudeAdapter = {
|
|
|
5167
5250
|
};
|
|
5168
5251
|
|
|
5169
5252
|
// src/agents/agy.ts
|
|
5253
|
+
init_exec();
|
|
5170
5254
|
import { readFileSync as readFileSync2, existsSync as existsSync2, mkdtempSync, cpSync, rmSync } from "fs";
|
|
5171
5255
|
import os from "os";
|
|
5172
5256
|
import path2 from "path";
|
package/package.json
CHANGED