archal 0.9.11 → 0.9.12
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/index.cjs +232 -48
- package/package.json +8 -3
- package/skills/onboard/SKILL.md +18 -2
package/dist/index.cjs
CHANGED
|
@@ -86957,11 +86957,18 @@ function checksumDir(dir) {
|
|
|
86957
86957
|
for (const entry of entries) {
|
|
86958
86958
|
if (entry.name === MANIFEST_FILE2) continue;
|
|
86959
86959
|
const p = (0, import_node_path51.join)(dir, entry.name);
|
|
86960
|
+
const nameBytes = Buffer.from(entry.name, "utf8");
|
|
86960
86961
|
if (entry.isDirectory()) {
|
|
86961
|
-
|
|
86962
|
+
const sub = checksumDir(p) ?? "";
|
|
86963
|
+
const subBytes = Buffer.from(sub, "utf8");
|
|
86964
|
+
hash2.update(`d:${nameBytes.length}:${sub ? subBytes.length : 0}:`);
|
|
86965
|
+
hash2.update(nameBytes);
|
|
86966
|
+
hash2.update(subBytes);
|
|
86962
86967
|
} else {
|
|
86963
|
-
|
|
86964
|
-
hash2.update(
|
|
86968
|
+
const content = (0, import_node_fs51.readFileSync)(p);
|
|
86969
|
+
hash2.update(`f:${nameBytes.length}:${content.length}:`);
|
|
86970
|
+
hash2.update(nameBytes);
|
|
86971
|
+
hash2.update(content);
|
|
86965
86972
|
}
|
|
86966
86973
|
}
|
|
86967
86974
|
return hash2.digest("hex");
|
|
@@ -86992,6 +86999,16 @@ function parseTargetFlag(value) {
|
|
|
86992
86999
|
}
|
|
86993
87000
|
|
|
86994
87001
|
// src/skills/installer.ts
|
|
87002
|
+
var ARCHAL_SKILL_PREFIX = "archal-";
|
|
87003
|
+
var SAFE_SKILL_NAME_RE = /^archal-[a-z0-9][a-z0-9-]*$/;
|
|
87004
|
+
function isSafeSkillName(destName) {
|
|
87005
|
+
return SAFE_SKILL_NAME_RE.test(destName);
|
|
87006
|
+
}
|
|
87007
|
+
function isValidManifestEntry(value) {
|
|
87008
|
+
if (!value || typeof value !== "object") return false;
|
|
87009
|
+
const entry = value;
|
|
87010
|
+
return typeof entry["checksum"] === "string" && typeof entry["version"] === "string";
|
|
87011
|
+
}
|
|
86995
87012
|
var RESET8 = "\x1B[0m";
|
|
86996
87013
|
var BOLD7 = "\x1B[1m";
|
|
86997
87014
|
var DIM8 = "\x1B[2m";
|
|
@@ -87008,11 +87025,12 @@ async function runInstaller({
|
|
|
87008
87025
|
}) {
|
|
87009
87026
|
const log3 = silent ? () => {
|
|
87010
87027
|
} : (msg) => process.stdout.write(msg);
|
|
87028
|
+
const isNonInteractive = nonInteractive || !process.stdin.isTTY;
|
|
87011
87029
|
const skillDirs = (0, import_node_fs52.readdirSync)(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
87012
87030
|
const selected = await resolveTargets({
|
|
87013
87031
|
cwd,
|
|
87014
87032
|
requested: requestedTargets ?? null,
|
|
87015
|
-
nonInteractive,
|
|
87033
|
+
nonInteractive: isNonInteractive,
|
|
87016
87034
|
log: log3,
|
|
87017
87035
|
version: version3
|
|
87018
87036
|
});
|
|
@@ -87022,7 +87040,9 @@ async function runInstaller({
|
|
|
87022
87040
|
return { installed: 0, targets: [], skipped: [], version: version3 };
|
|
87023
87041
|
}
|
|
87024
87042
|
let installed = 0;
|
|
87043
|
+
let removed = 0;
|
|
87025
87044
|
const skipped = [];
|
|
87045
|
+
const sourceDestNames = new Set(skillDirs.map((s) => `${ARCHAL_SKILL_PREFIX}${s}`));
|
|
87026
87046
|
for (const target of selected) {
|
|
87027
87047
|
const platformDir = (0, import_node_path52.join)(cwd, target.skillsPath);
|
|
87028
87048
|
(0, import_node_fs52.mkdirSync)(platformDir, { recursive: true });
|
|
@@ -87034,35 +87054,44 @@ async function runInstaller({
|
|
|
87034
87054
|
};
|
|
87035
87055
|
for (const skill of skillDirs) {
|
|
87036
87056
|
const src = (0, import_node_path52.join)(skillsDir, skill);
|
|
87037
|
-
const destName =
|
|
87057
|
+
const destName = `${ARCHAL_SKILL_PREFIX}${skill}`;
|
|
87038
87058
|
const dest = (0, import_node_path52.join)(platformDir, destName);
|
|
87039
87059
|
const sourceChecksum = checksumDir(src);
|
|
87040
87060
|
const existingChecksum = checksumDir(dest);
|
|
87041
87061
|
const manifestEntry = manifest?.skills?.[destName];
|
|
87042
|
-
|
|
87062
|
+
let userEdited = false;
|
|
87063
|
+
let migrationCase = false;
|
|
87064
|
+
if (existingChecksum) {
|
|
87065
|
+
if (manifestEntry?.checksum) {
|
|
87066
|
+
userEdited = existingChecksum !== manifestEntry.checksum && existingChecksum !== sourceChecksum;
|
|
87067
|
+
} else if (existingChecksum !== sourceChecksum) {
|
|
87068
|
+
userEdited = true;
|
|
87069
|
+
migrationCase = true;
|
|
87070
|
+
}
|
|
87071
|
+
}
|
|
87043
87072
|
if (userEdited && !yes) {
|
|
87044
|
-
|
|
87045
|
-
|
|
87046
|
-
|
|
87047
|
-
|
|
87048
|
-
|
|
87049
|
-
|
|
87050
|
-
|
|
87073
|
+
const message = migrationCase ? `${target.label}: ${destName} exists from an earlier install and may contain local edits. Overwrite with archal@${version3}?` : `${target.label}: ${destName} has local edits. Overwrite?`;
|
|
87074
|
+
const skipSuffix = migrationCase ? "legacy install, --yes required" : "user-edited, --yes required";
|
|
87075
|
+
const keptSuffix = migrationCase ? "kept legacy copy" : "kept user edits";
|
|
87076
|
+
const preservedEntry = {
|
|
87077
|
+
version: manifestEntry?.version ?? (migrationCase ? "legacy" : "unknown"),
|
|
87078
|
+
checksum: manifestEntry?.checksum ?? sourceChecksum ?? "",
|
|
87079
|
+
userEdited: true
|
|
87080
|
+
};
|
|
87081
|
+
if (isNonInteractive) {
|
|
87082
|
+
skipped.push(`${target.id}/${destName} (${skipSuffix})`);
|
|
87083
|
+
nextManifest.skills[destName] = preservedEntry;
|
|
87051
87084
|
continue;
|
|
87052
87085
|
}
|
|
87053
87086
|
const { overwrite } = await (0, import_prompts.default)({
|
|
87054
87087
|
type: "confirm",
|
|
87055
87088
|
name: "overwrite",
|
|
87056
|
-
message
|
|
87057
|
-
initial: false
|
|
87089
|
+
message,
|
|
87090
|
+
initial: migrationCase ? true : false
|
|
87058
87091
|
});
|
|
87059
87092
|
if (!overwrite) {
|
|
87060
|
-
skipped.push(`${target.id}/${destName} (
|
|
87061
|
-
nextManifest.skills[destName] =
|
|
87062
|
-
version: manifestEntry?.version ?? "unknown",
|
|
87063
|
-
checksum: existingChecksum,
|
|
87064
|
-
userEdited: true
|
|
87065
|
-
};
|
|
87093
|
+
skipped.push(`${target.id}/${destName} (${keptSuffix})`);
|
|
87094
|
+
nextManifest.skills[destName] = preservedEntry;
|
|
87066
87095
|
continue;
|
|
87067
87096
|
}
|
|
87068
87097
|
}
|
|
@@ -87076,6 +87105,49 @@ async function runInstaller({
|
|
|
87076
87105
|
};
|
|
87077
87106
|
installed++;
|
|
87078
87107
|
}
|
|
87108
|
+
if (manifest?.skills) {
|
|
87109
|
+
for (const [destName, rawEntry] of Object.entries(manifest.skills)) {
|
|
87110
|
+
if (!isSafeSkillName(destName)) {
|
|
87111
|
+
continue;
|
|
87112
|
+
}
|
|
87113
|
+
if (!isValidManifestEntry(rawEntry)) {
|
|
87114
|
+
continue;
|
|
87115
|
+
}
|
|
87116
|
+
const entry = rawEntry;
|
|
87117
|
+
if (sourceDestNames.has(destName)) continue;
|
|
87118
|
+
const dest = (0, import_node_path52.join)(platformDir, destName);
|
|
87119
|
+
if (!(0, import_node_fs52.existsSync)(dest)) continue;
|
|
87120
|
+
const existingChecksum = checksumDir(dest);
|
|
87121
|
+
const userEdited = existingChecksum !== entry.checksum;
|
|
87122
|
+
if (userEdited && !yes) {
|
|
87123
|
+
const preservedEntry = {
|
|
87124
|
+
version: entry.version,
|
|
87125
|
+
checksum: entry.checksum,
|
|
87126
|
+
userEdited: true
|
|
87127
|
+
};
|
|
87128
|
+
if (isNonInteractive) {
|
|
87129
|
+
skipped.push(
|
|
87130
|
+
`${target.id}/${destName} (removed upstream, edits detected \u2014 --yes required)`
|
|
87131
|
+
);
|
|
87132
|
+
nextManifest.skills[destName] = preservedEntry;
|
|
87133
|
+
continue;
|
|
87134
|
+
}
|
|
87135
|
+
const { remove } = await (0, import_prompts.default)({
|
|
87136
|
+
type: "confirm",
|
|
87137
|
+
name: "remove",
|
|
87138
|
+
message: `${target.label}: ${destName} was removed upstream but has local edits. Delete it?`,
|
|
87139
|
+
initial: false
|
|
87140
|
+
});
|
|
87141
|
+
if (!remove) {
|
|
87142
|
+
skipped.push(`${target.id}/${destName} (kept local copy)`);
|
|
87143
|
+
nextManifest.skills[destName] = preservedEntry;
|
|
87144
|
+
continue;
|
|
87145
|
+
}
|
|
87146
|
+
}
|
|
87147
|
+
(0, import_node_fs52.rmSync)(dest, { recursive: true, force: true });
|
|
87148
|
+
removed++;
|
|
87149
|
+
}
|
|
87150
|
+
}
|
|
87079
87151
|
writeManifest(platformDir, nextManifest);
|
|
87080
87152
|
}
|
|
87081
87153
|
const targetLabels = selected.map((t) => t.label).join(", ");
|
|
@@ -87084,6 +87156,10 @@ ${GREEN5}${BOLD7}Archal skills installed${RESET8} ${DIM8}(v${version3})${RESET8}
|
|
|
87084
87156
|
`);
|
|
87085
87157
|
log3(`${DIM8}${installed} skill(s) \u2192 ${targetLabels}${RESET8}
|
|
87086
87158
|
`);
|
|
87159
|
+
if (removed > 0) {
|
|
87160
|
+
log3(`${DIM8}${removed} skill(s) removed (no longer shipped)${RESET8}
|
|
87161
|
+
`);
|
|
87162
|
+
}
|
|
87087
87163
|
if (skipped.length) {
|
|
87088
87164
|
log3(`${YELLOW4}Skipped:${RESET8}
|
|
87089
87165
|
`);
|
|
@@ -87143,7 +87219,7 @@ ${BOLD7}Install Archal skills${RESET8} ${DIM8}(v${version3})${RESET8}
|
|
|
87143
87219
|
onCancel: () => {
|
|
87144
87220
|
log3(`${YELLOW4}Cancelled.${RESET8}
|
|
87145
87221
|
`);
|
|
87146
|
-
process.exit(
|
|
87222
|
+
process.exit(130);
|
|
87147
87223
|
}
|
|
87148
87224
|
}
|
|
87149
87225
|
);
|
|
@@ -87155,11 +87231,27 @@ ${BOLD7}Install Archal skills${RESET8} ${DIM8}(v${version3})${RESET8}
|
|
|
87155
87231
|
init_version();
|
|
87156
87232
|
init_errors6();
|
|
87157
87233
|
function detectPackageManager2(cwd) {
|
|
87234
|
+
const fromPackageManager = readPackageManagerField(cwd);
|
|
87235
|
+
if (fromPackageManager) return fromPackageManager;
|
|
87158
87236
|
if ((0, import_node_fs53.existsSync)((0, import_node_path53.join)(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
87159
|
-
if ((0, import_node_fs53.existsSync)((0, import_node_path53.join)(cwd, "bun.lockb"))) return "bun";
|
|
87237
|
+
if ((0, import_node_fs53.existsSync)((0, import_node_path53.join)(cwd, "bun.lockb")) || (0, import_node_fs53.existsSync)((0, import_node_path53.join)(cwd, "bun.lock"))) return "bun";
|
|
87160
87238
|
if ((0, import_node_fs53.existsSync)((0, import_node_path53.join)(cwd, "yarn.lock"))) return "yarn";
|
|
87161
87239
|
return "npm";
|
|
87162
87240
|
}
|
|
87241
|
+
function readPackageManagerField(cwd) {
|
|
87242
|
+
try {
|
|
87243
|
+
const pkg = JSON.parse((0, import_node_fs53.readFileSync)((0, import_node_path53.join)(cwd, "package.json"), "utf8"));
|
|
87244
|
+
const raw = typeof pkg.packageManager === "string" ? pkg.packageManager : "";
|
|
87245
|
+
const name = raw.split("@")[0];
|
|
87246
|
+
if (name === "pnpm" || name === "yarn" || name === "bun" || name === "npm") {
|
|
87247
|
+
return name;
|
|
87248
|
+
}
|
|
87249
|
+
return null;
|
|
87250
|
+
} catch {
|
|
87251
|
+
return null;
|
|
87252
|
+
}
|
|
87253
|
+
}
|
|
87254
|
+
var SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
87163
87255
|
function hasPackageJson(cwd) {
|
|
87164
87256
|
return (0, import_node_fs53.existsSync)((0, import_node_path53.join)(cwd, "package.json"));
|
|
87165
87257
|
}
|
|
@@ -87171,26 +87263,61 @@ function alreadyHasArchalDep(cwd) {
|
|
|
87171
87263
|
return false;
|
|
87172
87264
|
}
|
|
87173
87265
|
}
|
|
87266
|
+
function looksLikeSkillsDir(candidate) {
|
|
87267
|
+
if (!(0, import_node_fs53.existsSync)(candidate)) return false;
|
|
87268
|
+
let entries;
|
|
87269
|
+
try {
|
|
87270
|
+
entries = (0, import_node_fs53.readdirSync)(candidate);
|
|
87271
|
+
} catch {
|
|
87272
|
+
return false;
|
|
87273
|
+
}
|
|
87274
|
+
for (const name of entries) {
|
|
87275
|
+
const child = (0, import_node_path53.join)(candidate, name);
|
|
87276
|
+
try {
|
|
87277
|
+
if (!(0, import_node_fs53.statSync)(child).isDirectory()) continue;
|
|
87278
|
+
if ((0, import_node_fs53.existsSync)((0, import_node_path53.join)(child, "SKILL.md"))) return true;
|
|
87279
|
+
} catch {
|
|
87280
|
+
}
|
|
87281
|
+
}
|
|
87282
|
+
return false;
|
|
87283
|
+
}
|
|
87284
|
+
function findRepoRoot(start) {
|
|
87285
|
+
let dir = start;
|
|
87286
|
+
for (let i = 0; i < 10; i++) {
|
|
87287
|
+
if ((0, import_node_fs53.existsSync)((0, import_node_path53.join)(dir, "pnpm-workspace.yaml"))) return dir;
|
|
87288
|
+
const parent = (0, import_node_path53.dirname)(dir);
|
|
87289
|
+
if (parent === dir) return null;
|
|
87290
|
+
dir = parent;
|
|
87291
|
+
}
|
|
87292
|
+
return null;
|
|
87293
|
+
}
|
|
87174
87294
|
function resolveSkillsDir() {
|
|
87175
87295
|
const here = typeof __dirname === "string" ? __dirname : process.cwd();
|
|
87296
|
+
const repoRoot = findRepoRoot(here) ?? findRepoRoot(process.cwd());
|
|
87176
87297
|
const candidates = [
|
|
87177
87298
|
(0, import_node_path53.resolve)(here, "..", "skills"),
|
|
87178
|
-
(0, import_node_path53.resolve)(
|
|
87179
|
-
(0, import_node_path53.resolve)(process.cwd(), "packages", "archal
|
|
87299
|
+
...repoRoot ? [(0, import_node_path53.resolve)(repoRoot, "packages", "archal", "skills")] : [],
|
|
87300
|
+
(0, import_node_path53.resolve)(process.cwd(), "packages", "archal", "skills"),
|
|
87301
|
+
(0, import_node_path53.resolve)(process.cwd(), "skills")
|
|
87180
87302
|
];
|
|
87181
87303
|
for (const candidate of candidates) {
|
|
87182
|
-
if ((
|
|
87304
|
+
if (looksLikeSkillsDir(candidate)) return candidate;
|
|
87183
87305
|
}
|
|
87184
87306
|
throw new CliRuntimeError(
|
|
87185
|
-
"Could not locate the Archal skills directory.
|
|
87307
|
+
"Could not locate the Archal skills directory. This looks like a broken archal install \u2014 reinstall with `npm install archal` (or your package manager equivalent) and retry."
|
|
87186
87308
|
);
|
|
87187
87309
|
}
|
|
87188
87310
|
function runPmAdd(pm, cwd, spec) {
|
|
87189
87311
|
const args = pm === "npm" ? ["install", "--save-dev", spec] : ["add", "-D", spec];
|
|
87190
87312
|
const result = (0, import_node_child_process10.spawnSync)(pm, args, { cwd, stdio: "inherit" });
|
|
87313
|
+
if (result.error) {
|
|
87314
|
+
throw new CliRuntimeError(
|
|
87315
|
+
`Failed to launch ${pm}: ${result.error.message}. Install ${pm} (or install \`archal\` manually) and re-run \`archal init\`.`
|
|
87316
|
+
);
|
|
87317
|
+
}
|
|
87191
87318
|
if (result.status !== 0) {
|
|
87192
87319
|
throw new CliRuntimeError(
|
|
87193
|
-
`Failed to install ${spec} with ${pm}. Install manually and re-run \`archal init\`.`
|
|
87320
|
+
`Failed to install ${spec} with ${pm} (exit ${result.status}). Install manually and re-run \`archal init\`.`
|
|
87194
87321
|
);
|
|
87195
87322
|
}
|
|
87196
87323
|
}
|
|
@@ -87209,29 +87336,71 @@ function createInitCommand() {
|
|
|
87209
87336
|
throw new CliRuntimeError(err instanceof Error ? err.message : String(err));
|
|
87210
87337
|
}
|
|
87211
87338
|
}
|
|
87212
|
-
|
|
87213
|
-
|
|
87214
|
-
|
|
87215
|
-
|
|
87216
|
-
|
|
87217
|
-
|
|
87218
|
-
|
|
87339
|
+
let cliInstalled = true;
|
|
87340
|
+
const hadPackageJson = hasPackageJson(cwd);
|
|
87341
|
+
const startedAt = Date.now();
|
|
87342
|
+
try {
|
|
87343
|
+
if (!opts.skillsOnly) {
|
|
87344
|
+
if (!SEMVER_RE.test(CLI_VERSION)) {
|
|
87345
|
+
throw new CliRuntimeError(
|
|
87346
|
+
`Invalid CLI_VERSION "${CLI_VERSION}" \u2014 refusing to install. Reinstall archal and retry.`
|
|
87347
|
+
);
|
|
87348
|
+
}
|
|
87349
|
+
if (!hadPackageJson) {
|
|
87350
|
+
process.stderr.write(
|
|
87351
|
+
"No package.json in cwd \u2014 skipping devDependency install. Install archal globally (`npm i -g archal`) or initialize a package.json first.\n"
|
|
87352
|
+
);
|
|
87353
|
+
cliInstalled = false;
|
|
87354
|
+
} else if (alreadyHasArchalDep(cwd)) {
|
|
87355
|
+
process.stdout.write(`archal already a dependency \u2014 skipping install.
|
|
87219
87356
|
`);
|
|
87220
|
-
|
|
87221
|
-
|
|
87222
|
-
|
|
87357
|
+
} else {
|
|
87358
|
+
const pm = detectPackageManager2(cwd);
|
|
87359
|
+
process.stdout.write(`Installing archal@${CLI_VERSION} with ${pm}\u2026
|
|
87223
87360
|
`);
|
|
87224
|
-
|
|
87361
|
+
runPmAdd(pm, cwd, `archal@${CLI_VERSION}`);
|
|
87362
|
+
}
|
|
87363
|
+
} else {
|
|
87364
|
+
cliInstalled = alreadyHasArchalDep(cwd);
|
|
87365
|
+
}
|
|
87366
|
+
const result = await runInstaller({
|
|
87367
|
+
cwd,
|
|
87368
|
+
targets: targets ?? void 0,
|
|
87369
|
+
nonInteractive: opts.nonInteractive === true,
|
|
87370
|
+
yes: opts.yes === true,
|
|
87371
|
+
skillsDir: resolveSkillsDir(),
|
|
87372
|
+
version: CLI_VERSION
|
|
87373
|
+
});
|
|
87374
|
+
if (opts.skillsOnly && !cliInstalled) {
|
|
87375
|
+
process.stdout.write(
|
|
87376
|
+
`Note: --skills-only left out the archal runner. Run \`npm install -D archal\` (or pnpm / yarn / bun equivalent) before \`archal run\`.
|
|
87377
|
+
`
|
|
87378
|
+
);
|
|
87225
87379
|
}
|
|
87380
|
+
captureCliEvent("cli_init_completed", {
|
|
87381
|
+
skills_only: Boolean(opts.skillsOnly),
|
|
87382
|
+
non_interactive: opts.nonInteractive === true,
|
|
87383
|
+
yes: opts.yes === true,
|
|
87384
|
+
target_count: result.targets.length,
|
|
87385
|
+
targets: result.targets,
|
|
87386
|
+
installed: result.installed,
|
|
87387
|
+
skipped: result.skipped.length,
|
|
87388
|
+
had_package_json: hadPackageJson,
|
|
87389
|
+
cli_installed: cliInstalled,
|
|
87390
|
+
duration_ms: Date.now() - startedAt
|
|
87391
|
+
});
|
|
87392
|
+
} catch (err) {
|
|
87393
|
+
captureCliEvent("cli_init_failed", {
|
|
87394
|
+
skills_only: Boolean(opts.skillsOnly),
|
|
87395
|
+
non_interactive: opts.nonInteractive === true,
|
|
87396
|
+
yes: opts.yes === true,
|
|
87397
|
+
had_package_json: hadPackageJson,
|
|
87398
|
+
error_name: err instanceof Error ? err.constructor.name : "Unknown",
|
|
87399
|
+
error_message: err instanceof Error ? err.message : String(err),
|
|
87400
|
+
duration_ms: Date.now() - startedAt
|
|
87401
|
+
});
|
|
87402
|
+
throw err;
|
|
87226
87403
|
}
|
|
87227
|
-
await runInstaller({
|
|
87228
|
-
cwd,
|
|
87229
|
-
targets: targets ?? void 0,
|
|
87230
|
-
nonInteractive: opts.nonInteractive === true,
|
|
87231
|
-
yes: opts.yes === true,
|
|
87232
|
-
skillsDir: resolveSkillsDir(),
|
|
87233
|
-
version: CLI_VERSION
|
|
87234
|
-
});
|
|
87235
87404
|
}
|
|
87236
87405
|
);
|
|
87237
87406
|
}
|
|
@@ -87359,6 +87528,20 @@ function readManifestAt(path2) {
|
|
|
87359
87528
|
return null;
|
|
87360
87529
|
}
|
|
87361
87530
|
}
|
|
87531
|
+
function compareSemver(a, b) {
|
|
87532
|
+
const parse3 = (v) => {
|
|
87533
|
+
const m = /^(\d+)\.(\d+)\.(\d+)(?:[-+][0-9A-Za-z.-]+)?$/.exec(v);
|
|
87534
|
+
if (!m) return null;
|
|
87535
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
87536
|
+
};
|
|
87537
|
+
const pa = parse3(a);
|
|
87538
|
+
const pb = parse3(b);
|
|
87539
|
+
if (!pa || !pb) return null;
|
|
87540
|
+
if (pa[0] !== pb[0]) return pa[0] - pb[0];
|
|
87541
|
+
if (pa[1] !== pb[1]) return pa[1] - pb[1];
|
|
87542
|
+
if (pa[2] !== pb[2]) return pa[2] - pb[2];
|
|
87543
|
+
return 0;
|
|
87544
|
+
}
|
|
87362
87545
|
function maybePrintSkillDriftBanner(cwd = process.cwd()) {
|
|
87363
87546
|
try {
|
|
87364
87547
|
const stale = [];
|
|
@@ -87367,7 +87550,8 @@ function maybePrintSkillDriftBanner(cwd = process.cwd()) {
|
|
|
87367
87550
|
if (!(0, import_node_fs55.existsSync)(manifestPath)) continue;
|
|
87368
87551
|
const manifest = readManifestAt(manifestPath);
|
|
87369
87552
|
if (!manifest?.version) continue;
|
|
87370
|
-
|
|
87553
|
+
const cmp = compareSemver(manifest.version, CLI_VERSION);
|
|
87554
|
+
if (cmp !== null && cmp < 0) {
|
|
87371
87555
|
stale.push(`${target.label} (v${manifest.version})`);
|
|
87372
87556
|
}
|
|
87373
87557
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "archal",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.12",
|
|
4
4
|
"description": "Test your agents & integrations against digital twins",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -45,8 +45,13 @@
|
|
|
45
45
|
"twin-assets",
|
|
46
46
|
"LICENSE"
|
|
47
47
|
],
|
|
48
|
-
"
|
|
49
|
-
"vitest": "
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"vitest": ">=2.1.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"vitest": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
50
55
|
},
|
|
51
56
|
"scripts": {
|
|
52
57
|
"verify:artifacts": "node scripts/assert-artifacts.mjs",
|
package/skills/onboard/SKILL.md
CHANGED
|
@@ -8,6 +8,19 @@ user-invocable: true
|
|
|
8
8
|
|
|
9
9
|
You are setting up Archal in this project. Archal tests AI agents against digital twins of real services (GitHub, Slack, Stripe, etc.). Handle installation and auth yourself; delegate the workflow-specific setup to the matching sub-skill.
|
|
10
10
|
|
|
11
|
+
## If this is a cold-start
|
|
12
|
+
|
|
13
|
+
The user may have landed here without running `npx archal init` first. If the
|
|
14
|
+
CLI is missing (see "Install + auth" below) AND no `.archal-manifest.json`
|
|
15
|
+
exists in `.claude/skills/`, the canonical first command is:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx archal init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
That adds `archal` as a devDependency and reinstalls these skills at the
|
|
22
|
+
right version. Re-invoke the onboard skill after it completes.
|
|
23
|
+
|
|
11
24
|
## Discover first
|
|
12
25
|
|
|
13
26
|
Before asking anything, read the repo:
|
|
@@ -25,9 +38,12 @@ Before asking anything, read the repo:
|
|
|
25
38
|
|
|
26
39
|
## Install + auth
|
|
27
40
|
|
|
41
|
+
If you're here because the user ran `npx archal init`, the CLI is already
|
|
42
|
+
a devDependency and the skills are in place. Skip to `archal login`.
|
|
43
|
+
|
|
28
44
|
```bash
|
|
29
|
-
npx archal --version #
|
|
30
|
-
|
|
45
|
+
npx archal --version # verify CLI is on PATH / in node_modules
|
|
46
|
+
npx archal init --skills-only # re-stage skills if they drifted
|
|
31
47
|
archal usage # check auth
|
|
32
48
|
archal login # OAuth browser flow, or: archal login --token <token>
|
|
33
49
|
```
|