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 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.3` 时:
75
+ 修改源码并更新 `package.json` 的版本,提交、push 后创建对应版本的 tag。例如版本为 `0.1.8` 时:
74
76
 
75
77
  ```sh
76
- git tag v0.1.3
77
- git push origin v0.1.3
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,6 +1,6 @@
1
1
  {
2
2
  "name": "global-app-skill",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Thin skill bootstrap and GitHub resource runner for overseas Android app research",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -1,23 +1,51 @@
1
1
  ---
2
2
  name: global-app-analysis
3
- description: 调研海外 Android App 的业务流程、功能入口、字段权限,或为 UED 提取整款 App/指定范围的原始界面图册;也支持仅下载/导出 APK。
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;设备/AVD 门槛由解析后的工作流检查。
8
+ 需要 Node.js >=22.12、`python3` >=3.9。第 1 步会强制检查 Android 真机/模拟器或完整 AVD;不满足时立即中断,不转成“只下载不运行”。
9
9
 
10
- 按目标选择 `download`(仅取包)、`research`(业务调研,含同时需要图册)或 `ued`(仅界面图册),执行:
10
+ ## 执行顺序
11
11
 
12
- ```sh
13
- npx -y --prefer-online global-app-skill@latest context resolve --mode MODE
14
- ```
12
+ 1. 选模式:`download`(仅取包/导出)、`research`(业务流程、入口、字段权限;同时要图册也用它)、`ued`(仅页面图册)。判断看用户要的答案,不看职位;“整款 App”是范围,不是分支。
13
+ 2. 解析资源:
15
14
 
16
- CLI 自动发现已安装的 skill 并同步入口,检查 `skillUpdate` 并报告失败;新入口在客户端重新加载后采用。依次读取全部 `mustRead`,以 `resourceRoot` 解析资源并按流程执行。新任务重新 resolve,同一任务沿用已读快照。资源更新或校验失败时停止依赖工作,不静默使用旧资源。
15
+ ```sh
16
+ npx -y --prefer-online global-app-skill@latest context resolve --mode MODE
17
+ ```
17
18
 
18
- 脚本通过 `npx -y --prefer-online global-app-skill@latest run SCRIPT --mode MODE --resource-root RESOURCE_ROOT -- 参数` 执行;参数见解析后的 CLI 文档。业务判断与页面操作由 agent 按文档编排,CLI 成功不代表调研完成;关键进度仍须输出到聊天正文。
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
- 解析资源后,先读取当前 `resourceRoot` 下的 `references/rules.md`。读取失败时暂停依赖该规则的工作。
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, { requireRules = true } = {}) {
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
- if (requireRules) required.unshift(RULES_PATH, 'references/delivery-record.md', 'scripts/check_delivery.py');
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 = [RULES_PATH, 'references/cli.md', 'references/guide.md', 'references/orchestration.md', MODES[mode]]
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, { requireRules: !options.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) => {