@alphafox/cli 0.3.4 → 0.3.6

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 (39) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +27 -6
  3. package/dist/auth/loopback-callback.js +3 -3
  4. package/dist/commands/run.js +26 -2
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.js +20 -1
  7. package/dist/install/types.d.ts +8 -1
  8. package/dist/install/types.js +1 -0
  9. package/dist/install/wizard.js +91 -53
  10. package/dist/keychain/windows-credential.d.ts +1 -1
  11. package/dist/keychain/windows-credential.js +1 -1
  12. package/dist/skills/manager.d.ts +96 -0
  13. package/dist/skills/manager.js +445 -0
  14. package/dist/skills/run-command.d.ts +22 -0
  15. package/dist/skills/run-command.js +143 -0
  16. package/dist/skills-manifest.json +141 -0
  17. package/dist/update/notify.d.ts +24 -0
  18. package/dist/update/notify.js +109 -0
  19. package/dist/update/run-command.d.ts +41 -0
  20. package/dist/update/run-command.js +204 -0
  21. package/dist/version.d.ts +1 -1
  22. package/dist/version.js +1 -1
  23. package/docs/agents/issue-tracker.md +2 -2
  24. package/docs/agents/triage-labels.md +1 -1
  25. package/docs/alphafox-cli-installation-guide.md +15 -16
  26. package/docs/index.html +11 -11
  27. package/docs/release-supply-chain.md +11 -6
  28. package/package.json +2 -2
  29. package/skills/account/SKILL.md +1 -1
  30. package/skills/admin/SKILL.md +1 -1
  31. package/skills/alphafox/SKILL.md +26 -4
  32. package/skills/alphafox-shared/SKILL.md +24 -4
  33. package/skills/auth/SKILL.md +2 -2
  34. package/skills/engine-backtest/SKILL.md +1 -1
  35. package/skills/exchange/SKILL.md +1 -1
  36. package/skills/market/SKILL.md +1 -1
  37. package/skills/notification/SKILL.md +1 -1
  38. package/skills/strategy/SKILL.md +1 -1
  39. package/skills/trading/SKILL.md +1 -1
@@ -0,0 +1,141 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "packageName": "@alphafox/cli",
4
+ "packageVersion": "0.3.6",
5
+ "contractVersion": "2026-08-13",
6
+ "bundleHash": "1eb4c16a941eee4c125efc6bb64ed7bb0db1d12b71f71cae66e55e64f600cf9a",
7
+ "skills": [
8
+ {
9
+ "name": "alphafox",
10
+ "version": "0.3.6",
11
+ "files": [
12
+ {
13
+ "path": "SKILL.md",
14
+ "sha256": "a60f579e6321533d4f965c607f1158ddb50d1a89905d8793eca0b401b3f67fd2",
15
+ "size": 3055
16
+ }
17
+ ],
18
+ "hash": "c47e6e2d6154e831a681b731e123053c2d20c6c77654191f0a78ae2137ce5304"
19
+ },
20
+ {
21
+ "name": "alphafox-account",
22
+ "version": "0.3.6",
23
+ "files": [
24
+ {
25
+ "path": "SKILL.md",
26
+ "sha256": "c60baab539cca008ccc48d53f0262d7a019db82b3945402d16b5ac84624b475f",
27
+ "size": 783
28
+ }
29
+ ],
30
+ "hash": "e828192ec19a24bc18ce64d07a583eaba498e6a0c356214dbe18ccae6e9f6a6d"
31
+ },
32
+ {
33
+ "name": "alphafox-admin",
34
+ "version": "0.3.6",
35
+ "files": [
36
+ {
37
+ "path": "SKILL.md",
38
+ "sha256": "87bbc12b803be021d94ad8161293263ce69e1d6c50f887a245ebe5c0a285e4f6",
39
+ "size": 787
40
+ }
41
+ ],
42
+ "hash": "2881be10858efaad4543ffbe94f3bf87a91d4b0a4f3d905c3e0a5b8463e8756b"
43
+ },
44
+ {
45
+ "name": "alphafox-auth",
46
+ "version": "0.3.6",
47
+ "files": [
48
+ {
49
+ "path": "SKILL.md",
50
+ "sha256": "99e954df23206b0deb32761ce39396897d5af2ee8852e3a8340ed1b9c2e88a46",
51
+ "size": 1919
52
+ }
53
+ ],
54
+ "hash": "659ca92bdfa0b31bcd1d39d7af151c308f1f9e7cd541bd38cf89326a825a38b8"
55
+ },
56
+ {
57
+ "name": "alphafox-engine-backtest",
58
+ "version": "0.3.6",
59
+ "files": [
60
+ {
61
+ "path": "SKILL.md",
62
+ "sha256": "176c329a665709461403671d34e73dd5b58bf389a328010c8a32cec5b949a9c5",
63
+ "size": 7346
64
+ }
65
+ ],
66
+ "hash": "23db5ab285f8600a43561ce3d4b7641ea45cd55c7c3b16d9f6fb7ff0c862b379"
67
+ },
68
+ {
69
+ "name": "alphafox-exchange",
70
+ "version": "0.3.6",
71
+ "files": [
72
+ {
73
+ "path": "SKILL.md",
74
+ "sha256": "089db4794cd55ba04278d4616cd6d5e92bc4c1d4c7c183001ea363bc4eeba578",
75
+ "size": 743
76
+ }
77
+ ],
78
+ "hash": "d4b0fe876ced82185eb477a23420cb24a8990f3dcbb6d4d5e9412dfd4cd2c279"
79
+ },
80
+ {
81
+ "name": "alphafox-market",
82
+ "version": "0.3.6",
83
+ "files": [
84
+ {
85
+ "path": "SKILL.md",
86
+ "sha256": "79fd7431c119b9d9318566c0419e2820ad9b06f0fda2882fdf9d1d7f4c1b9566",
87
+ "size": 1801
88
+ }
89
+ ],
90
+ "hash": "8814883b9b5bfb7eab4406fe1236091410dcb1130d4904dae8756e1302a02687"
91
+ },
92
+ {
93
+ "name": "alphafox-notification",
94
+ "version": "0.3.6",
95
+ "files": [
96
+ {
97
+ "path": "SKILL.md",
98
+ "sha256": "9a90360b83b72bb252349612cb052ffded40d00e07ca8568b76a6b13479252ac",
99
+ "size": 698
100
+ }
101
+ ],
102
+ "hash": "99f8309b235b2b89734ed49d0a9e0e8981b5216025815fbe69f9101cf4f412cc"
103
+ },
104
+ {
105
+ "name": "alphafox-shared",
106
+ "version": "0.3.6",
107
+ "files": [
108
+ {
109
+ "path": "SKILL.md",
110
+ "sha256": "60051a6c9b789e306ec968d3c8762a75039c34a0db2470dfddd1063bf2a3553f",
111
+ "size": 5071
112
+ }
113
+ ],
114
+ "hash": "20832738f9f15063291309871197b6274fd24f2630bd2525092ac017f7491b68"
115
+ },
116
+ {
117
+ "name": "alphafox-strategy",
118
+ "version": "0.3.6",
119
+ "files": [
120
+ {
121
+ "path": "SKILL.md",
122
+ "sha256": "e4188e115eca6610c482bbcdf11ab1eb455cb5b6f242af96d1d8090e6ce9ce9d",
123
+ "size": 1450
124
+ }
125
+ ],
126
+ "hash": "878fd5c365eb33a431e91f6922a8cf45bcf94a7136b0105d50f3b487112c3573"
127
+ },
128
+ {
129
+ "name": "alphafox-trading",
130
+ "version": "0.3.6",
131
+ "files": [
132
+ {
133
+ "path": "SKILL.md",
134
+ "sha256": "098e0f975ae9f0169b0da696b76e74ffd3c6748e898e7c4f8c8f8a33aec47dc8",
135
+ "size": 1435
136
+ }
137
+ ],
138
+ "hash": "99b72870808f871ddeffd69ee89872e8532f2847494a0e5ad83de48ad58c675a"
139
+ }
140
+ ]
141
+ }
@@ -0,0 +1,24 @@
1
+ export declare const UPDATE_CHECK_INTERVAL_MS: number;
2
+ export interface UpdateCheckState {
3
+ readonly schemaVersion: 1;
4
+ readonly checkedAt: string;
5
+ readonly currentVersion: string;
6
+ readonly latestVersion: string | null;
7
+ readonly updateAvailable: boolean;
8
+ }
9
+ export interface UpdateNoticeResult {
10
+ readonly checked: boolean;
11
+ readonly notified: boolean;
12
+ readonly latestVersion: string | null;
13
+ }
14
+ export interface UpdateNoticeDeps {
15
+ readonly env?: NodeJS.ProcessEnv;
16
+ readonly currentVersion?: string;
17
+ readonly now?: Date;
18
+ readonly fetchLatest?: () => Promise<string>;
19
+ readonly writeNotice?: (line: string) => void;
20
+ }
21
+ export declare function updateCheckStatePath(env?: NodeJS.ProcessEnv): string;
22
+ export declare function formatUpdateNotice(currentVersion: string, latestVersion: string): string;
23
+ export declare function shouldSkipUpdateCheck(command: string | undefined, env?: NodeJS.ProcessEnv): boolean;
24
+ export declare function maybeNotifyCliUpdate(deps?: UpdateNoticeDeps): Promise<UpdateNoticeResult>;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UPDATE_CHECK_INTERVAL_MS = void 0;
4
+ exports.updateCheckStatePath = updateCheckStatePath;
5
+ exports.formatUpdateNotice = formatUpdateNotice;
6
+ exports.shouldSkipUpdateCheck = shouldSkipUpdateCheck;
7
+ exports.maybeNotifyCliUpdate = maybeNotifyCliUpdate;
8
+ const node_fs_1 = require("node:fs");
9
+ const node_path_1 = require("node:path");
10
+ const profiles_1 = require("../config/profiles");
11
+ const exec_1 = require("../install/exec");
12
+ const wizard_1 = require("../install/wizard");
13
+ const version_1 = require("../version");
14
+ exports.UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
15
+ const NPM_VIEW_TIMEOUT_MS = 4_000;
16
+ function updateCheckStatePath(env = process.env) {
17
+ return (0, node_path_1.join)((0, profiles_1.defaultConfigDir)(env), "update-check.json");
18
+ }
19
+ function formatUpdateNotice(currentVersion, latestVersion) {
20
+ return `[alphafox] update available: ${currentVersion} -> ${latestVersion}. After the user confirms, run: alphafox update --format json --no-input`;
21
+ }
22
+ function shouldSkipUpdateCheck(command, env = process.env) {
23
+ if (env.ALPHAFOX_SKIP_UPDATE_CHECK === "1")
24
+ return true;
25
+ return command === "update" || command === "install";
26
+ }
27
+ async function maybeNotifyCliUpdate(deps = {}) {
28
+ const env = deps.env ?? process.env;
29
+ const currentVersion = deps.currentVersion ?? version_1.CLI_VERSION;
30
+ const now = deps.now ?? new Date();
31
+ const writeNotice = deps.writeNotice ??
32
+ ((line) => {
33
+ process.stderr.write(`${line}\n`);
34
+ });
35
+ const previous = loadUpdateCheckState(updateCheckStatePath(env));
36
+ if (previous &&
37
+ now.getTime() - Date.parse(previous.checkedAt) < exports.UPDATE_CHECK_INTERVAL_MS) {
38
+ return {
39
+ checked: false,
40
+ notified: false,
41
+ latestVersion: previous.latestVersion,
42
+ };
43
+ }
44
+ let latestVersion = null;
45
+ try {
46
+ latestVersion = await (deps.fetchLatest ?? defaultFetchLatest)(env);
47
+ }
48
+ catch {
49
+ saveUpdateCheckState(updateCheckStatePath(env), {
50
+ schemaVersion: 1,
51
+ checkedAt: now.toISOString(),
52
+ currentVersion,
53
+ latestVersion: previous?.latestVersion ?? null,
54
+ updateAvailable: false,
55
+ });
56
+ return {
57
+ checked: true,
58
+ notified: false,
59
+ latestVersion: previous?.latestVersion ?? null,
60
+ };
61
+ }
62
+ const updateAvailable = (0, wizard_1.semverLessThan)(currentVersion, latestVersion);
63
+ saveUpdateCheckState(updateCheckStatePath(env), {
64
+ schemaVersion: 1,
65
+ checkedAt: now.toISOString(),
66
+ currentVersion,
67
+ latestVersion,
68
+ updateAvailable,
69
+ });
70
+ if (updateAvailable) {
71
+ writeNotice(formatUpdateNotice(currentVersion, latestVersion));
72
+ }
73
+ return {
74
+ checked: true,
75
+ notified: updateAvailable,
76
+ latestVersion,
77
+ };
78
+ }
79
+ function loadUpdateCheckState(path) {
80
+ if (!(0, node_fs_1.existsSync)(path))
81
+ return null;
82
+ try {
83
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(path, "utf8"));
84
+ if (parsed.schemaVersion !== 1 ||
85
+ typeof parsed.checkedAt !== "string" ||
86
+ Number.isNaN(Date.parse(parsed.checkedAt))) {
87
+ return null;
88
+ }
89
+ return parsed;
90
+ }
91
+ catch {
92
+ return null;
93
+ }
94
+ }
95
+ function saveUpdateCheckState(path, state) {
96
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(path, ".."), { recursive: true });
97
+ (0, node_fs_1.writeFileSync)(path, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
98
+ }
99
+ async function defaultFetchLatest(env) {
100
+ const runner = (0, exec_1.createDefaultInstallRunner)(env, []);
101
+ const { stdout } = await runner.exec("npm", ["view", version_1.CLI_PACKAGE, "version"], {
102
+ timeoutMs: NPM_VIEW_TIMEOUT_MS,
103
+ });
104
+ const version = stdout.trim();
105
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
106
+ throw new Error(`invalid npm version: ${version}`);
107
+ }
108
+ return version;
109
+ }
@@ -0,0 +1,41 @@
1
+ import type { InstallRunner } from "../install/types";
2
+ import type { SkillsSyncResult } from "../skills/manager";
3
+ export interface UpdateArgs {
4
+ readonly check: boolean;
5
+ readonly help: boolean;
6
+ readonly version?: string;
7
+ }
8
+ export interface UpdateExecutionFlags {
9
+ readonly yes: boolean;
10
+ readonly dryRun: boolean;
11
+ }
12
+ export interface UpdateCliFlags extends UpdateExecutionFlags {
13
+ readonly format: "json" | "jsonl" | "text";
14
+ readonly noInput: boolean;
15
+ readonly jq?: string;
16
+ }
17
+ export interface UpdateDeps {
18
+ readonly runner?: InstallRunner;
19
+ readonly packageHasSkills?: (packageRoot: string) => boolean;
20
+ readonly sync?: (packageRoot: string, runner: InstallRunner) => Promise<SkillsSyncResult>;
21
+ }
22
+ export interface CliUpdateResult {
23
+ readonly currentVersion: string | null;
24
+ readonly targetVersion: string;
25
+ readonly updateAvailable: boolean;
26
+ readonly checkOnly: boolean;
27
+ readonly dryRun: boolean;
28
+ readonly cli: {
29
+ readonly action: "available" | "planned" | "updated" | "current";
30
+ readonly previousVersion: string | null;
31
+ readonly version: string;
32
+ };
33
+ readonly skills: SkillsSyncResult | {
34
+ readonly action: "not-run";
35
+ readonly reason: "check-only" | "dry-run";
36
+ };
37
+ readonly restartRequired: boolean;
38
+ }
39
+ export declare function parseUpdateArgs(args: readonly string[]): UpdateArgs;
40
+ export declare function executeCliUpdate(args: UpdateArgs, flags: UpdateExecutionFlags, env?: NodeJS.ProcessEnv, deps?: UpdateDeps): Promise<CliUpdateResult>;
41
+ export declare function cmdUpdate(args: string[], flags: UpdateCliFlags, env?: NodeJS.ProcessEnv, deps?: UpdateDeps): Promise<number>;
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseUpdateArgs = parseUpdateArgs;
4
+ exports.executeCliUpdate = executeCliUpdate;
5
+ exports.cmdUpdate = cmdUpdate;
6
+ const envelope_1 = require("../envelope");
7
+ const exec_1 = require("../install/exec");
8
+ const package_root_1 = require("../install/package-root");
9
+ const wizard_1 = require("../install/wizard");
10
+ const run_command_1 = require("../skills/run-command");
11
+ const version_1 = require("../version");
12
+ const NPM_TIMEOUT_MS = 120_000;
13
+ function parseUpdateArgs(args) {
14
+ let check = false;
15
+ let help = false;
16
+ let version;
17
+ for (let i = 0; i < args.length; i += 1) {
18
+ const arg = args[i];
19
+ if (arg === "--check") {
20
+ check = true;
21
+ }
22
+ else if (arg === "--version") {
23
+ version = args[++i];
24
+ if (!version)
25
+ throw updateUsage("--version requires a value");
26
+ }
27
+ else if (arg.startsWith("--version=")) {
28
+ version = arg.slice("--version=".length);
29
+ }
30
+ else if (arg === "--help" || arg === "-h" || arg === "help") {
31
+ help = true;
32
+ }
33
+ else {
34
+ throw updateUsage(`Unknown update argument: ${arg}`);
35
+ }
36
+ }
37
+ if (version && !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
38
+ throw updateUsage(`Invalid version: ${version}`);
39
+ }
40
+ return { check, help, ...(version ? { version } : {}) };
41
+ }
42
+ async function executeCliUpdate(args, flags, env = process.env, deps = {}) {
43
+ const runner = deps.runner ??
44
+ (0, exec_1.createDefaultInstallRunner)(env, [__dirname, process.cwd()]);
45
+ const currentVersion = await readGlobalVersion(runner);
46
+ const targetVersion = await readTargetVersion(runner, args.version);
47
+ const updateAvailable = args.version
48
+ ? currentVersion !== targetVersion
49
+ : currentVersion == null || (0, wizard_1.semverLessThan)(currentVersion, targetVersion);
50
+ const effectiveVersion = updateAvailable ? targetVersion : (currentVersion ?? targetVersion);
51
+ if (args.check) {
52
+ return {
53
+ currentVersion,
54
+ targetVersion,
55
+ updateAvailable,
56
+ checkOnly: true,
57
+ dryRun: false,
58
+ cli: {
59
+ action: updateAvailable ? "available" : "current",
60
+ previousVersion: currentVersion,
61
+ version: effectiveVersion,
62
+ },
63
+ skills: { action: "not-run", reason: "check-only" },
64
+ restartRequired: false,
65
+ };
66
+ }
67
+ if (updateAvailable &&
68
+ args.version &&
69
+ currentVersion &&
70
+ (0, wizard_1.semverLessThan)(targetVersion, currentVersion) &&
71
+ !flags.yes) {
72
+ throw Object.assign(new Error(`Downgrading ${version_1.CLI_PACKAGE} from ${currentVersion} to ${targetVersion} requires --yes`), {
73
+ type: "confirmation",
74
+ subtype: "cli_downgrade_confirmation_required",
75
+ });
76
+ }
77
+ if (flags.dryRun) {
78
+ return {
79
+ currentVersion,
80
+ targetVersion,
81
+ updateAvailable,
82
+ checkOnly: false,
83
+ dryRun: true,
84
+ cli: {
85
+ action: updateAvailable ? "planned" : "current",
86
+ previousVersion: currentVersion,
87
+ version: effectiveVersion,
88
+ },
89
+ skills: { action: "not-run", reason: "dry-run" },
90
+ restartRequired: updateAvailable,
91
+ };
92
+ }
93
+ if (updateAvailable) {
94
+ await runner.exec("npm", ["install", "-g", `${version_1.CLI_PACKAGE}@${targetVersion}`], { timeoutMs: NPM_TIMEOUT_MS });
95
+ const installedVersion = await readGlobalVersion(runner);
96
+ if (installedVersion !== targetVersion) {
97
+ throw Object.assign(new Error(`npm reported ${installedVersion ?? "no global install"} after updating to ${targetVersion}`), {
98
+ type: "install",
99
+ subtype: "cli_update_verify_failed",
100
+ });
101
+ }
102
+ }
103
+ const packageRoot = await resolveUpdatedPackageRoot(runner, deps.packageHasSkills ?? package_root_1.packageHasSkills, !updateAvailable);
104
+ const sync = deps.sync ??
105
+ (async (root, activeRunner) => await (0, run_command_1.syncCurrentSkills)({ force: false, dryRun: false }, env, { runner: activeRunner, packageRoot: root }));
106
+ const skills = await sync(packageRoot, runner);
107
+ return {
108
+ currentVersion,
109
+ targetVersion,
110
+ updateAvailable,
111
+ checkOnly: false,
112
+ dryRun: false,
113
+ cli: {
114
+ action: updateAvailable ? "updated" : "current",
115
+ previousVersion: currentVersion,
116
+ version: effectiveVersion,
117
+ },
118
+ skills,
119
+ restartRequired: updateAvailable || skills.restartRequired,
120
+ };
121
+ }
122
+ async function cmdUpdate(args, flags, env = process.env, deps = {}) {
123
+ const parsed = parseUpdateArgs(args);
124
+ if (parsed.help) {
125
+ (0, envelope_1.writeSuccess)({
126
+ name: "update",
127
+ usage: [
128
+ "alphafox update --check",
129
+ "alphafox update [--dry-run]",
130
+ "alphafox update --version <version> [--yes]",
131
+ ],
132
+ notes: [
133
+ "Updates @alphafox/cli through npm, then syncs the verified co-versioned Skills bundle",
134
+ "A downgrade requires --yes",
135
+ "No Skills are downloaded independently from GitHub",
136
+ ],
137
+ }, { format: flags.format, jq: flags.jq });
138
+ return 0;
139
+ }
140
+ const result = await executeCliUpdate(parsed, flags, env, deps);
141
+ (0, envelope_1.writeSuccess)(result, { format: flags.format, jq: flags.jq });
142
+ return result.skills.action !== "not-run" &&
143
+ result.skills.blocked.length > 0
144
+ ? 1
145
+ : 0;
146
+ }
147
+ async function readGlobalVersion(runner) {
148
+ try {
149
+ const { stdout, stderr } = await runner.exec("npm", ["list", "-g", version_1.CLI_PACKAGE, "--depth=0"], { timeoutMs: 15_000 });
150
+ return (0, wizard_1.parseNpmListVersion)(`${stdout}\n${stderr}`);
151
+ }
152
+ catch {
153
+ return null;
154
+ }
155
+ }
156
+ async function readTargetVersion(runner, requested) {
157
+ const spec = requested ? `${version_1.CLI_PACKAGE}@${requested}` : version_1.CLI_PACKAGE;
158
+ const { stdout } = await runner.exec("npm", ["view", spec, "version"], {
159
+ timeoutMs: 15_000,
160
+ });
161
+ const version = stdout.trim();
162
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
163
+ throw Object.assign(new Error(`npm returned an invalid version for ${spec}`), {
164
+ type: "install",
165
+ subtype: "npm_version_invalid",
166
+ });
167
+ }
168
+ return version;
169
+ }
170
+ async function resolveUpdatedPackageRoot(runner, packageHasSkills, allowCurrentFallback) {
171
+ try {
172
+ const { stdout } = await runner.exec("npm", ["root", "-g"], {
173
+ timeoutMs: 15_000,
174
+ });
175
+ const root = (0, package_root_1.globalPackageRoot)(stdout.trim());
176
+ if (packageHasSkills(root))
177
+ return root;
178
+ }
179
+ catch {
180
+ // Fall back to the currently executing package for repair-only updates.
181
+ }
182
+ if (!allowCurrentFallback) {
183
+ throw Object.assign(new Error("Updated @alphafox/cli package does not contain Skills"), {
184
+ type: "install",
185
+ subtype: "updated_skills_missing",
186
+ });
187
+ }
188
+ const current = (0, run_command_1.resolveCurrentSkillsPackageRoot)(runner.packageSearchDirs().length > 0
189
+ ? runner.packageSearchDirs()
190
+ : [__dirname, process.cwd()]);
191
+ if (packageHasSkills(current))
192
+ return current;
193
+ throw Object.assign(new Error("Updated @alphafox/cli package does not contain Skills"), {
194
+ type: "install",
195
+ subtype: "updated_skills_missing",
196
+ });
197
+ }
198
+ function updateUsage(message) {
199
+ return Object.assign(new Error(message), {
200
+ type: "usage",
201
+ subtype: "invalid_update_args",
202
+ status: 64,
203
+ });
204
+ }
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export declare const CLI_NAME = "alphafox";
2
2
  export declare const CLI_PACKAGE = "@alphafox/cli";
3
- export declare const CLI_VERSION = "0.3.4";
3
+ export declare const CLI_VERSION = "0.3.6";
4
4
  export { CATALOG_VERSION as CLI_CONTRACT_VERSION } from "./catalog/operations";
package/dist/version.js CHANGED
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CLI_CONTRACT_VERSION = exports.CLI_VERSION = exports.CLI_PACKAGE = exports.CLI_NAME = void 0;
4
4
  exports.CLI_NAME = "alphafox";
5
5
  exports.CLI_PACKAGE = "@alphafox/cli";
6
- exports.CLI_VERSION = "0.3.4";
6
+ exports.CLI_VERSION = "0.3.6";
7
7
  var operations_1 = require("./catalog/operations");
8
8
  Object.defineProperty(exports, "CLI_CONTRACT_VERSION", { enumerable: true, get: function () { return operations_1.CATALOG_VERSION; } });
@@ -1,6 +1,6 @@
1
1
  # Issue tracker: Feishu Tasks
2
2
 
3
- Issues and specs for this repo live as tasks in the **Alphafox-Issues** Feishu (Lark) tasklist. Use the `lark-cli` CLI ([`@larksuite/cli`](https://github.com/larksuite/cli)) for all operations, always with `--as user` — a task created by the bot identity is invisible in the human's task centre.
3
+ Issues and specs for this repo live as tasks in the **AlphaFox-Issues** Feishu (Lark) tasklist. Use the `lark-cli` CLI ([`@larksuite/cli`](https://github.com/larksuite/cli)) for all operations, always with `--as user` — a task created by the bot identity is invisible in the human's task centre.
4
4
 
5
5
  List: <https://applink.feishu.cn/client/todo/task_list?guid=6d628d79-cdfe-47cc-98f7-35561944494b>
6
6
 
@@ -46,7 +46,7 @@ Every other label is an option on the single-select `Type` field. Address an opt
46
46
  ## Conventions
47
47
 
48
48
  - **Shared-list title** — prefix every issue/task title with `[alphafox-cli]` so the repository remains identifiable on the shared board.
49
- - **Tracker boundary** — Matt Skills issues, specs, tickets, triage items, and wayfinder maps belong in `Alphafox-Issues`, not a quarterly execution list. If quarterly planning initiated the work, link its absolute Feishu task URL instead of duplicating workflow state.
49
+ - **Tracker boundary** — Matt Skills issues, specs, tickets, triage items, and wayfinder maps belong in `AlphaFox-Issues`, not a quarterly execution list. If quarterly planning initiated the work, link its absolute Feishu task URL instead of duplicating workflow state.
50
50
 
51
51
  - **Create an issue** — one call sets body, section (triage role) and `Type`:
52
52
 
@@ -1,6 +1,6 @@
1
1
  # Triage Labels
2
2
 
3
- The skills speak in terms of five canonical triage roles. On this repo's tracker (Feishu Tasks) a role is not a label but a **section** of the Alphafox-Issues tasklist — a task sits in exactly one, so the state machine can't be violated. `issue-tracker.md` holds the section GUIDs and the command that moves a task between them.
3
+ The skills speak in terms of five canonical triage roles. On this repo's tracker (Feishu Tasks) a role is not a label but a **section** of the AlphaFox-Issues tasklist — a task sits in exactly one, so the state machine can't be violated. `issue-tracker.md` holds the section GUIDs and the command that moves a task between them.
4
4
 
5
5
  | Label in mattpocock/skills | Section in our tracker | Meaning |
6
6
  | -------------------------- | ---------------------- | ---------------------------------------- |
@@ -1,4 +1,4 @@
1
- # Alphafox CLI installation guide
1
+ # AlphaFox CLI installation guide
2
2
 
3
3
  The following steps are designed for AI Agents. Some steps require the user
4
4
  to complete a browser or Device Flow approval. Always use
@@ -20,26 +20,25 @@ Skills do **not** register with Cursor / Claude Code / Codex from
20
20
  # Install CLI
21
21
  npm install -g @alphafox/cli
22
22
 
23
- # Install CLI SKILL (required) project-local, current workspace
24
- npx -y skills add "$(npm root -g)/@alphafox/cli" -y
23
+ # Verify and globally sync the exact co-versioned Skills bundle
24
+ alphafox skills sync --format json --no-input
25
25
  ```
26
26
 
27
- If the local package path fails (older tarball without `skills/`, or
28
- `npm root -g` is wrong), fall back to the public GitHub source:
27
+ Do not install Skills from GitHub `main` as a fallback. The CLI verifies the
28
+ manifest and hashes inside the npm package before syncing. If sync fails, stop
29
+ and report the error rather than downloading a different Skills version.
29
30
 
30
- ```shell
31
- npx -y skills add alphafoxai/alphafox-cli -y
32
- ```
33
-
34
- To install Skills for every project on this machine instead of the current
35
- repo, add `-g`:
31
+ For future updates:
36
32
 
37
33
  ```shell
38
- npx -y skills add "$(npm root -g)/@alphafox/cli" -y -g
34
+ alphafox update --check --format json --no-input
35
+ alphafox update --format json --no-input
39
36
  ```
40
37
 
41
- Do not invent a second catalog. Skills must stay co-versioned with the CLI
42
- that was just installed.
38
+ `alphafox update` upgrades the npm CLI first, then syncs its bundled Skills.
39
+ Modified Skills are preserved and reported. Only use
40
+ `alphafox skills sync --force --yes` when the user explicitly wants to replace
41
+ them; a backup is created before replacement.
43
42
 
44
43
  ## Step 2: Login
45
44
 
@@ -88,7 +87,7 @@ Parse the JSON envelope: `ok === true` means success. Errors land on
88
87
  ## Step 4: Tell the user to restart
89
88
 
90
89
  Ask the user to **restart the AI tool** so the new Skills are loaded.
91
- Then they can ask the Agent to use Alphafox. The entry skill `alphafox` routes
90
+ Then they can ask the Agent to use AlphaFox. The entry skill `alphafox` routes
92
91
  to auth, market, engine-backtest, strategy, trading, and the rest.
93
92
 
94
93
  ## Human wizard (do not run this from an Agent)
@@ -100,6 +99,6 @@ stepping through the commands above:
100
99
  npx @alphafox/cli@latest install
101
100
  ```
102
101
 
103
- That wizard installs the CLI globally, runs `npx skills add -y -g`,
102
+ That wizard installs the CLI globally, verifies and syncs the packaged Skills,
104
103
  and may prompt for `alphafox auth login --browser`. It is TTY-oriented.
105
104
  Agents must follow Steps 1–4 in this document rather than the wizard.