@ccoalm/ccl-skills 0.14.0 → 0.15.1
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/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/ccl-skills.ts +80 -4
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/commands/ccl-install-skills.md +16 -4
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/owner-dispatch.sh +13 -2
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/test.sh +53 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +19 -24
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/client-routing.md +32 -32
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/manual-invocation-and-prompts.md +16 -14
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +24 -26
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/AGENTS.md +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/claude_review.sh +60 -209
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/init_policy_matrix.py +114 -367
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_probe_result.py +52 -672
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +17 -3
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/runtime-surface-verification-design.md +4 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_claude_review_probe.sh +77 -444
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_init_policy_matrix.sh +33 -98
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_probe_result.sh +57 -173
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +65 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/grill-me/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +5 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/alerting-and-on-call.md +8 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/SKILL.md +14 -14
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/dual-sidecar-and-traffic-config-center.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/grpc-authority-workaround.md +40 -83
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/mesh-architecture.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/retry-timeout-circuit-breaker.md +44 -37
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/service-discovery-recipe.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/delivery-lifecycle.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/rd-standards-doc-family-checklist.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-baseline/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-scope/SKILL.md +9 -6
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/eval-routing.md +6 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +4 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +52 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-golden-trace.rb +31 -7
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-routing-bank.rb +62 -3
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +188 -13
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/review_ledger_binding.py +36 -13
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/skill-behavior-eval.py +103 -21
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_impact_chain_refscripts.sh +261 -14
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_routing_bank_resolution.sh +253 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_runtime.py +428 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_verdict_differential.sh +49 -25
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_review_ledger_binding.sh +63 -5
- package/dist/assets/release.json +76 -56
- package/dist/claude-adapter.js +14 -7
- package/dist/codex-host.d.ts +1 -3
- package/dist/codex-host.js +6 -9
- package/dist/host-probe.d.ts +11 -0
- package/dist/host-probe.js +27 -0
- package/dist/opencode-adapter.js +24 -19
- package/dist/unified.js +11 -9
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
// Version discovery must not hold up other hosts or wait for interactive input.
|
|
3
|
+
const HOST_PROBE_TIMEOUT_MS = 10000;
|
|
4
|
+
export function probeHostVersion(command, env = process.env) {
|
|
5
|
+
const result = spawnSync(command, ["--version"], {
|
|
6
|
+
encoding: "utf8",
|
|
7
|
+
env,
|
|
8
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
9
|
+
timeout: HOST_PROBE_TIMEOUT_MS,
|
|
10
|
+
// spawnSync still waits if a child catches SIGTERM and does not exit.
|
|
11
|
+
killSignal: "SIGKILL",
|
|
12
|
+
});
|
|
13
|
+
if (result.error || result.status !== 0) {
|
|
14
|
+
const errorCode = result.error?.code;
|
|
15
|
+
const kind = errorCode === "ETIMEDOUT" ? "timeout" : errorCode === "ENOENT" ? "missing" : "probe-failed";
|
|
16
|
+
return {
|
|
17
|
+
ok: false,
|
|
18
|
+
kind,
|
|
19
|
+
message: kind === "timeout"
|
|
20
|
+
? `${command} --version timed out after ${HOST_PROBE_TIMEOUT_MS}ms`
|
|
21
|
+
: kind === "missing"
|
|
22
|
+
? `${command} CLI is unavailable (ENOENT)`
|
|
23
|
+
: `${command} --version failed (${errorCode || (result.signal ? `signal ${result.signal}` : result.error ? "spawn error" : `exit ${result.status}`)})`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return { ok: true, output: `${result.stdout}\n${result.stderr}` };
|
|
27
|
+
}
|
package/dist/opencode-adapter.js
CHANGED
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
import { atomicJson, sha256 } from "./fs-safe.js";
|
|
7
7
|
import { readRelease } from "./manifest.js";
|
|
8
8
|
import { compare } from "./version.js";
|
|
9
|
+
import { probeHostVersion } from "./host-probe.js";
|
|
9
10
|
const PACKAGE = "@ccoalm/ccl-skills";
|
|
10
11
|
function paths(context) {
|
|
11
12
|
const rawHome = context.home ?? (context.env ? context.env.HOME : process.env.HOME);
|
|
@@ -21,7 +22,7 @@ function assertExclusiveRoot(base, root, createBase = false) {
|
|
|
21
22
|
throw new Error("managed root is not canonical");
|
|
22
23
|
if (createBase)
|
|
23
24
|
mkdirSync(base, { recursive: true });
|
|
24
|
-
for (const component of [base, root]) {
|
|
25
|
+
for (const component of [base, root, join(root, "snapshots")]) {
|
|
25
26
|
if (!existsSync(component))
|
|
26
27
|
continue;
|
|
27
28
|
const stat = lstatSync(component);
|
|
@@ -124,10 +125,6 @@ function readManifest(path, root) {
|
|
|
124
125
|
}).sort((a, b) => a.destination.localeCompare(b.destination));
|
|
125
126
|
return { schema: 1, npmPackage: PACKAGE, installedAt: raw.installedAt, version: raw.version, sourceCommit: raw.sourceCommit, sourceKind: raw.sourceKind, snapshot, snapshotHash: raw.snapshotHash, entries };
|
|
126
127
|
}
|
|
127
|
-
function hostAvailable(context) {
|
|
128
|
-
const result = spawnSync("opencode", ["--version"], { encoding: "utf8", env: context.env || process.env });
|
|
129
|
-
return !result.error && result.status === 0;
|
|
130
|
-
}
|
|
131
128
|
function sharedPath(base, rel) {
|
|
132
129
|
const path = resolve(base, safeRel(rel, "OpenCode destination"));
|
|
133
130
|
if (!path.startsWith(`${resolve(base)}${sep}`))
|
|
@@ -190,17 +187,19 @@ function actualFiles(directory) {
|
|
|
190
187
|
function preflight(base, next, old) {
|
|
191
188
|
assertSafeSharedParents(base, next);
|
|
192
189
|
const previous = new Map((old?.entries || []).map((entry) => [entry.destination, entry]));
|
|
190
|
+
const drift = [];
|
|
193
191
|
if (old) {
|
|
192
|
+
assertSafeSharedParents(base, old.entries);
|
|
194
193
|
for (const entry of old.entries) {
|
|
195
194
|
const path = sharedPath(base, entry.destination);
|
|
196
195
|
if (!existsSync(path) || (regular(path).mode & 0o777) !== entry.mode || sha256(path) !== entry.sha256)
|
|
197
|
-
|
|
196
|
+
drift.push(entry.destination);
|
|
198
197
|
}
|
|
199
198
|
const skillNames = new Set(old.entries.filter((entry) => entry.destination.startsWith("skills/")).map((entry) => entry.destination.split("/")[1]));
|
|
200
199
|
for (const skill of skillNames) {
|
|
201
200
|
const expected = old.entries.filter((entry) => entry.destination.startsWith(`skills/${skill}/`)).map((entry) => entry.destination.slice(`skills/${skill}/`.length)).sort();
|
|
202
201
|
if (JSON.stringify(actualFiles(join(base, "skills", skill))) !== JSON.stringify(expected))
|
|
203
|
-
|
|
202
|
+
drift.push(`skills/${skill}`);
|
|
204
203
|
}
|
|
205
204
|
}
|
|
206
205
|
const nextSkills = new Set(next.filter((entry) => entry.destination.startsWith("skills/")).map((entry) => entry.destination.split("/")[1]));
|
|
@@ -211,6 +210,7 @@ function preflight(base, next, old) {
|
|
|
211
210
|
for (const entry of next)
|
|
212
211
|
if (!previous.has(entry.destination) && existsSync(sharedPath(base, entry.destination)))
|
|
213
212
|
throw new Error(`OpenCode path collision: ${entry.destination}`);
|
|
213
|
+
return drift;
|
|
214
214
|
}
|
|
215
215
|
function prepareSnapshot(p, candidate) {
|
|
216
216
|
const snapshotRel = join("snapshots", candidate.snapshotHash, "source"), snapshot = join(p.root, snapshotRel);
|
|
@@ -305,8 +305,9 @@ function writeShared(p, snapshot, entries, old, isInterrupted, copyShared = (fro
|
|
|
305
305
|
function doctor(context) {
|
|
306
306
|
const p = paths(context);
|
|
307
307
|
assertExclusiveRoot(p.base, p.root);
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
const host = probeHostVersion("opencode", context.env || process.env);
|
|
309
|
+
if (!host.ok)
|
|
310
|
+
return { code: 4, status: `host-${host.kind}`, message: host.message };
|
|
310
311
|
const legacy = existsSync(join(p.base, "ccl-skills/install-manifest.json")), manifest = readManifest(p.manifest, p.root);
|
|
311
312
|
if (legacy && manifest)
|
|
312
313
|
return { code: 3, status: "double-install", message: "legacy checkout and npm OpenCode installs are both present; keep exactly one" };
|
|
@@ -315,20 +316,22 @@ function doctor(context) {
|
|
|
315
316
|
return { code: 3, status: legacy ? "legacy-install" : "unowned-registration", message: "OpenCode ccl-skills files exist without an npm ownership receipt" };
|
|
316
317
|
return { code: 3, status: "absent", message: "ccl-skills is not installed for OpenCode" };
|
|
317
318
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
319
|
+
let drift = [], reason;
|
|
320
|
+
try {
|
|
321
|
+
drift = preflight(p.base, manifest.entries, manifest);
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
reason = String(error);
|
|
323
325
|
}
|
|
324
|
-
if (drift.length)
|
|
325
|
-
return { code: 3, status: "shared-drift", message: "OpenCode shared files changed after npm install; they will never be auto-deleted", details: { drift } };
|
|
326
|
+
if (drift.length || reason)
|
|
327
|
+
return { code: 3, status: "shared-drift", message: "OpenCode shared files changed after npm install; they will never be auto-deleted", details: { drift, ...(reason ? { reason } : {}) } };
|
|
326
328
|
return { code: 0, status: "healthy", message: `OpenCode uses @ccoalm/ccl-skills ${manifest.version}` };
|
|
327
329
|
}
|
|
328
330
|
function installOrUpdate(commandName, options, context) {
|
|
329
331
|
const p = paths(context);
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
const host = probeHostVersion("opencode", context.env || process.env);
|
|
333
|
+
if (!host.ok)
|
|
334
|
+
return { code: 4, status: `host-${host.kind}`, message: host.message };
|
|
332
335
|
let candidate;
|
|
333
336
|
try {
|
|
334
337
|
candidate = source(context);
|
|
@@ -350,7 +353,9 @@ function installOrUpdate(commandName, options, context) {
|
|
|
350
353
|
return { code: 3, status: "downgrade-refused", message: "newer OpenCode assets are installed" };
|
|
351
354
|
}
|
|
352
355
|
try {
|
|
353
|
-
preflight(p.base, candidate.entries, old);
|
|
356
|
+
const drift = preflight(p.base, candidate.entries, old);
|
|
357
|
+
if (drift.length)
|
|
358
|
+
throw new Error(`owned OpenCode paths drifted: ${drift.join(", ")}`);
|
|
354
359
|
}
|
|
355
360
|
catch (error) {
|
|
356
361
|
return { code: 3, status: "collision", message: String(error) };
|
package/dist/unified.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { probeHostVersion } from "./host-probe.js";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { runClaude } from "./claude-adapter.js";
|
|
5
5
|
import { run as runCodex } from "./operations.js";
|
|
6
6
|
import { runOpenCode } from "./opencode-adapter.js";
|
|
7
|
-
function available(host) {
|
|
8
|
-
const command = host === "opencode" ? "opencode" : host;
|
|
9
|
-
const result = spawnSync(command, ["--version"], { encoding: "utf8" });
|
|
10
|
-
return !result.error && result.status === 0;
|
|
11
|
-
}
|
|
12
7
|
function owned(host) {
|
|
13
8
|
const home = process.env.HOME;
|
|
14
9
|
if (!home)
|
|
@@ -57,8 +52,15 @@ export function runUnified(command, options = {}, codexContext = {}) {
|
|
|
57
52
|
if (options.host)
|
|
58
53
|
return dispatch(options.host, command, options, codexContext);
|
|
59
54
|
const includeOwned = command === "doctor" || command === "uninstall";
|
|
60
|
-
const
|
|
55
|
+
const candidates = ["claude", "codex", "opencode"].filter((host) => command !== "update" || owned(host));
|
|
56
|
+
const probes = candidates.map((host) => ({ host, probe: probeHostVersion(host) }));
|
|
57
|
+
const hosts = probes.filter(({ host, probe }) => probe.ok || probe.kind !== "missing" || (includeOwned && owned(host))).map(({ host }) => host);
|
|
61
58
|
if (!hosts.length)
|
|
62
|
-
return { code: 4, status: "host-missing", message: "
|
|
63
|
-
return runHostSequence(hosts, (host) =>
|
|
59
|
+
return { code: 4, status: "host-missing", message: "no Claude Code, Codex, or OpenCode CLI is available" };
|
|
60
|
+
return runHostSequence(hosts, (host) => {
|
|
61
|
+
const probe = probes.find((entry) => entry.host === host).probe;
|
|
62
|
+
if (!probe.ok && probe.kind !== "missing")
|
|
63
|
+
return { code: 4, status: `host-${probe.kind}`, message: probe.message };
|
|
64
|
+
return dispatch(host, command, { ...options, host }, codexContext);
|
|
65
|
+
});
|
|
64
66
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ccoalm/ccl-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Reusable workflows that help coding agents plan, build, test, review, and release software — for Claude Code, Codex, and OpenCode",
|
|
5
5
|
"keywords": ["skills", "agent-skills", "claude", "claude-code", "codex", "opencode", "agent", "ai", "ai-agents", "cli", "anthropic", "developer-tools"],
|
|
6
6
|
"type": "module",
|