global-app-skill 0.1.7 → 0.1.8
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 +6 -4
- package/package.json +1 -1
- package/skills/global-app-analysis/SKILL.md +39 -11
- package/src/protocol.mjs +14 -2
- package/src/resources.mjs +1 -1
- package/src/run.mjs +1 -1
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ npx -y --prefer-online global-app-skill@latest run preflight --mode research --r
|
|
|
46
46
|
| `src/` | npm CLI:安装、资源解析、校验、脚本运行 |
|
|
47
47
|
| `resources/global-app-analysis/references/` | 主流程和各阶段操作文档 |
|
|
48
48
|
| `resources/global-app-analysis/scripts/` | 原有 Python 脚本及回归测试 |
|
|
49
|
-
| `resources/global-app-analysis/examples/` |
|
|
49
|
+
| `resources/global-app-analysis/examples/` | 业务报告模板与审查记录模板 |
|
|
50
50
|
| `scripts/build-resources.mjs` | 生成确定性的资源包与清单 |
|
|
51
51
|
| `.github/workflows/publish.yml` | tag 触发的构建、GitHub Release 和 npm 发布 |
|
|
52
52
|
| `scripts/release.mjs` | tag 校验、打包、校验和及发布资产核对 |
|
|
@@ -68,13 +68,15 @@ npm run release:prepare
|
|
|
68
68
|
|
|
69
69
|
Python 回归测试中的长图部分需要 Pillow。CLI 无第三方 Node 依赖。`--feed` 可指定 HTTPS 清单,测试允许 loopback HTTP。`release:prepare` 在本地预演与 Actions 相同的构建,默认 tag 为 `v<package.json.version>`,也可指定 `RELEASE_TAG`。构建结果进入忽略的 `dist/release/`,不手工上传。
|
|
70
70
|
|
|
71
|
+
`npm run resources:check` 只校验已生成的 `dist/resources`,本地需先执行 `npm run resources:build`;`release:prepare` 会自动重建并核对。
|
|
72
|
+
|
|
71
73
|
### 发布 CLI、薄入口与资源
|
|
72
74
|
|
|
73
|
-
修改源码并更新 `package.json` 的版本,提交、push 后创建对应版本的 tag。例如版本为 `0.1.
|
|
75
|
+
修改源码并更新 `package.json` 的版本,提交、push 后创建对应版本的 tag。例如版本为 `0.1.8` 时:
|
|
74
76
|
|
|
75
77
|
```sh
|
|
76
|
-
git tag v0.1.
|
|
77
|
-
git push origin v0.1.
|
|
78
|
+
git tag v0.1.8
|
|
79
|
+
git push origin v0.1.8
|
|
78
80
|
```
|
|
79
81
|
|
|
80
82
|
`publish.yml` 校验 tag 与 package.json 一致,执行 Node/Python 测试,从 tag 源码生成以下资产:
|
package/package.json
CHANGED
|
@@ -1,23 +1,51 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: global-app-analysis
|
|
3
|
-
description: 调研海外 Android App
|
|
3
|
+
description: 调研海外 Android App 的业务流程、功能入口、字段权限与原始界面:当用户给出 App 名称、Google Play 链接、包名或 APK,要求分析借款/开户/下单等业务链路、竞品功能与字段权限,或要导出全部/指定页面截图、制作 UED 界面图册,或仅下载/导出 APK 时使用;需要拆包、恢复代码或运行原包定位页面时也使用。执行需要 Node.js、python3,以及可用的 Android 设备或完整 AVD(仅下载也要求设备门槛);本 skill 只做 Android,不适用于 iOS。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 海外 App 分析
|
|
7
7
|
|
|
8
|
-
需要 Node.js >=22.12、`python3` >=3.9
|
|
8
|
+
需要 Node.js >=22.12、`python3` >=3.9。第 1 步会强制检查 Android 真机/模拟器或完整 AVD;不满足时立即中断,不转成“只下载不运行”。
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## 执行顺序
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
```
|
|
12
|
+
1. 选模式:`download`(仅取包/导出)、`research`(业务流程、入口、字段权限;同时要图册也用它)、`ued`(仅页面图册)。判断看用户要的答案,不看职位;“整款 App”是范围,不是分支。
|
|
13
|
+
2. 解析资源:
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
```sh
|
|
16
|
+
npx -y --prefer-online global-app-skill@latest context resolve --mode MODE
|
|
17
|
+
```
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
3. 在开始任何分析前,按顺序读完返回的全部 `mustRead`:`cli → guide → orchestration → 模式文档 → rules`。`resourceRoot` 是只读快照,所有相对路径都以它为准;同一任务沿用它,新任务重新 resolve。资源更新或校验失败时停止依赖工作,不静默使用旧资源。
|
|
20
|
+
4. 按 `guide.md` 的十步主流程执行。第 5 步前读 `references/completion.md`;第 5–9 步读 `references/ui-extraction.md`,截图调用 `references/screenshot-workflow.md`;第 9 步按 `references/review-workflow.md` 的 9.1–9.5 执行。
|
|
21
|
+
5. 任务目录确定后执行 `check_delivery.py init`;重试/返工前领取额度(搜索用 `attempts.py`,其他用 `reserve`);交付前过 `check-ledger`(纯下载)或 `review`/`deliver`(业务/UED)。细节和未通过时的回退见下表与 `references/rules.md`。
|
|
22
|
+
6. 7 个脚本优先用 `npx ... run SCRIPT` 执行;直接运行的条件见 `cli.md`。`check_delivery.py` 直接用 `$RESOURCE_ROOT/scripts/check_delivery.py`。
|
|
23
|
+
7. 每个阶段开始、完成、等待、失败/跳过时,把真实动作和结果输出到聊天正文。脚本退出码、日志或 `environment.json` 不是正文进度;CLI 成功也不代表调研完成。
|
|
19
24
|
|
|
20
|
-
##
|
|
25
|
+
## 强制门槛
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
下表 `详见` 的文件都在 `references/` 下。
|
|
28
|
+
|
|
29
|
+
| 时点 | 必须通过 | 未过时 | 详见 |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| 开始分析前 | 快照校验通过;`mustRead` 全部读完 | 停止依赖工作,报告错误 | `cli.md` |
|
|
32
|
+
| 第 1 步,任何商店/搜索前 | `preflight` 返回 0、`status=passed`、`downstream_allowed=true` | 中断调研,不转纯下载 | `guide.md#环境硬门槛` |
|
|
33
|
+
| 任务目录确定后(第 2 步) | `check_delivery.py init`;纯下载也要 | 补齐账本再继续 | `loop-budget.md` |
|
|
34
|
+
| 第 4 步,进入分析前 | `verify` 通过 | 回第 3 步 | `verification.md` |
|
|
35
|
+
| 第 5 步前 | 已读 `completion.md`;页面范围按 `ui-extraction.md` 开始 | 补齐再进入 | `completion.md` |
|
|
36
|
+
| 每次重试/返工前 | `reserve` 成功(搜索轮次用 `attempts.py search-round`);超限按回路暂停 | 校验账本返回 3、搜索脚本返回 1 时等用户 | `loop-budget.md` |
|
|
37
|
+
| 纯下载交付前(第 4 步) | `check-ledger` 通过 | 补齐账本;按回路处理 | `rules.md`、`delivery-record.md` |
|
|
38
|
+
| 业务/UED 交付前 | `review` 至少两轮通过;`deliver` 通过;阶段性交付两次校验都加 `--partial` | 回 9.3/9.1 补证;账本或成品按对应流程重验 | `review-workflow.md`、`delivery-record.md` |
|
|
39
|
+
|
|
40
|
+
逐项命令和未通过时的回退见 `references/rules.md`;节点证据要求见各节点文档。
|
|
41
|
+
|
|
42
|
+
## 不可协商
|
|
43
|
+
|
|
44
|
+
- 环境门槛不过就停,即使本地已有 APK。
|
|
45
|
+
- 没读完 `mustRead` 不开始分析。
|
|
46
|
+
- 业务/UED 没有 `review`/`deliver` 通过不交付;纯下载没有 `check-ledger` 通过不交付;复用、重发、阶段性交付也一样。
|
|
47
|
+
- 不为完成而缩小范围、删候选,或把未知/待确认写成肯定结论。
|
|
48
|
+
- 脚本成功、截图存在、日志退出码,都不等于事实或交互已验证。
|
|
49
|
+
- Mock、本地回调或隔离场景只证明客户端行为,不写成真实审批、放款、到账或生产启用。
|
|
50
|
+
- 长图只用原帧拼接,不重绘;无法完整就保留原帧并标记缺口。
|
|
51
|
+
- 真实生产借款/还款/身份/生物资料提交不执行,改用隔离 Mock。
|
package/src/protocol.mjs
CHANGED
|
@@ -22,7 +22,7 @@ export function validateMode(mode) {
|
|
|
22
22
|
return mode;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export function validateManifest(manifest, {
|
|
25
|
+
export function validateManifest(manifest, { requireReviewWorkflow = true } = {}) {
|
|
26
26
|
const hash = /^[a-f0-9]{64}$/;
|
|
27
27
|
if (manifest?.schemaVersion !== 1 || !RELEASE_TAG.test(manifest.releaseTag) || !hash.test(manifest.resourceHash) ||
|
|
28
28
|
!/^\d+\.\d+\.\d+$/.test(manifest.minCliVersion) ||
|
|
@@ -44,8 +44,20 @@ export function validateManifest(manifest, { requireRules = true } = {}) {
|
|
|
44
44
|
}
|
|
45
45
|
if (identity(manifest.files) !== manifest.resourceHash) throw new Error('Resource manifest hash mismatch');
|
|
46
46
|
const required = ['references/guide.md', 'references/cli.md', 'references/orchestration.md',
|
|
47
|
+
'references/completion.md', 'references/ui-extraction.md', 'references/screenshot-workflow.md',
|
|
48
|
+
'references/review-workflow.md', 'references/review-checklist.md', 'references/loop-budget.md',
|
|
49
|
+
'references/business-ui-report.md', 'references/report-review-workflow.md',
|
|
50
|
+
'references/package-analysis.md', 'references/runtime-and-mock.md',
|
|
51
|
+
'references/network-and-devices.md', 'references/download-sources.md', 'references/verification.md',
|
|
52
|
+
'examples/business-results-report/README.md', 'examples/business-results-report/report.html',
|
|
53
|
+
'examples/business-results-report/main-flow.mmd',
|
|
47
54
|
...Object.values(MODES), ...SCRIPTS.map(name => `scripts/${name}.py`), 'scripts/apk_utils.py', 'scripts/progress.py'];
|
|
48
|
-
|
|
55
|
+
// These files were introduced with the review ledger. A task pinned to an
|
|
56
|
+
// older snapshot may still finish on it, so only fresh resolutions require them.
|
|
57
|
+
if (requireReviewWorkflow) required.unshift(RULES_PATH, 'references/delivery-record.md', 'scripts/check_delivery.py',
|
|
58
|
+
'examples/review-record/README.md', 'examples/review-record/review.json',
|
|
59
|
+
'examples/review-record/review-mixed.json', 'examples/review-record/scope.json',
|
|
60
|
+
'examples/review-record/results.json');
|
|
49
61
|
const missing = required.filter(name => !seen.has(name));
|
|
50
62
|
if (missing.length) throw new Error(`Resource manifest is missing workflow files: ${missing.join(', ')}`);
|
|
51
63
|
const installed = VERSION.split('.').map(Number);
|
package/src/resources.mjs
CHANGED
|
@@ -107,7 +107,7 @@ export async function resolveContext({ mode, feed = FEED, cacheDir, progress = (
|
|
|
107
107
|
}
|
|
108
108
|
await readSnapshot(resourceRoot);
|
|
109
109
|
progress(updated ? 'Resource snapshot ready' : 'Verified cached snapshot is current');
|
|
110
|
-
const mustRead = [
|
|
110
|
+
const mustRead = ['references/cli.md', 'references/guide.md', 'references/orchestration.md', MODES[mode], RULES_PATH]
|
|
111
111
|
.map(name => path.join(resourceRoot, name));
|
|
112
112
|
return { ok: true, source: url.origin === 'https://github.com' ? 'github' : 'custom', feed: url.href,
|
|
113
113
|
mode, releaseTag: manifest.releaseTag, resourceHash: manifest.resourceHash, resourceRoot,
|
package/src/run.mjs
CHANGED
|
@@ -8,7 +8,7 @@ export async function runScript(script, args, options = {}) {
|
|
|
8
8
|
if (!SCRIPTS.includes(script)) throw new Error(`Unknown script; choose ${SCRIPTS.join(', ')}`);
|
|
9
9
|
const resourceRoot = options.resourceRoot ? path.resolve(options.resourceRoot) : (await resolveContext(options)).resourceRoot;
|
|
10
10
|
// A task that already resolved an earlier snapshot may finish on it.
|
|
11
|
-
await readSnapshot(resourceRoot, {
|
|
11
|
+
await readSnapshot(resourceRoot, { requireReviewWorkflow: !options.resourceRoot });
|
|
12
12
|
await promisify(execFile)('python3', ['-c', 'import sys; sys.exit(0 if sys.version_info >= (3, 9) else 1)'])
|
|
13
13
|
.catch(() => { throw new Error('Python >=3.9 must be available as python3'); });
|
|
14
14
|
return new Promise((resolve, reject) => {
|