Merge pull request #92 from jhuang-tw/fix/cross-platform-case-contract

fix: make case setup consistent across Windows, Linux, and macOS

Owner integration: preserve routing.json SSoT, keep reports optional by default, and require offline samples to resolve to real local files.
This commit is contained in:
zhaoxuya520
2026-08-19 11:46:55 +08:00
12 changed files with 359 additions and 109 deletions
+99 -10
View File
@@ -49,6 +49,51 @@ jobs:
shell: pwsh
run: ./skills/scripts/test-workflow-title-safety.ps1
- name: Offline sample case contract (Windows PowerShell 5.1)
if: runner.os == 'Windows'
shell: powershell
run: |
$scratch = Join-Path $env:RUNNER_TEMP ("reverse-skill-offline-" + [guid]::NewGuid().ToString('n'))
New-Item -ItemType Directory -Force -Path $scratch | Out-Null
$sample = Join-Path $scratch 'sample.apk'
Set-Content -Path $sample -Value 'fixture' -Encoding ASCII
./skills/scripts/case-init.ps1 `
-Hint "offline apk" `
-CaseName "offline-sample" `
-ProjectRoot $scratch `
-Preset offline-sample `
-Sample $sample
$scope = Join-Path $scratch 'work/offline-sample/scope.md'
$raw = Get-Content $scope -Raw
if ($raw -notmatch '(?m)^- mode: offline\r?$') { throw 'offline sample did not keep offline network mode' }
if ($raw -notmatch '(?m)^- ready_for_act: true\r?$') { throw 'offline sample did not become ready_for_act' }
./skills/scripts/case-guard.ps1 -CaseRoot (Join-Path $scratch 'work/offline-sample')
try {
./skills/scripts/case-init.ps1 `
-Hint "missing offline apk" `
-CaseName "missing-sample" `
-ProjectRoot $scratch `
-Preset offline-sample `
-Sample (Join-Path $scratch 'missing.apk')
throw 'missing offline sample was accepted'
} catch {
if ($_.Exception.Message -eq 'missing offline sample was accepted') { throw }
}
./skills/scripts/case-init.ps1 `
-Hint "pending offline apk" `
-CaseName "force-auth" `
-ProjectRoot $scratch `
-Sample $sample
& powershell -NoProfile -ExecutionPolicy Bypass -File ./skills/scripts/case-guard.ps1 `
-CaseRoot (Join-Path $scratch 'work/force-auth') `
-Force
$guardExit = $LASTEXITCODE
if ($guardExit -eq 0) { throw '-Force bypassed auth.status hard gate' }
$global:LASTEXITCODE = 0
- name: Smoke (verify + parse + quick route)
shell: pwsh
run: ./skills/scripts/smoke.ps1
@@ -94,6 +139,47 @@ jobs:
scratch="$(mktemp -d)"
trap 'rm -rf "$scratch"' EXIT
# Fresh Linux journey: no pwsh required, artifacts stay in caller project.
caller="$scratch/caller-project"
mkdir -p "$caller"
printf 'fixture' > "$scratch/sample.apk"
(
cd "$caller"
bash "$GITHUB_WORKSPACE/skills/scripts/master-route.sh" --hint "offline apk"
bash "$GITHUB_WORKSPACE/skills/scripts/case-init.sh" \
--hint "offline apk" \
--case-name "caller-default" \
--preset offline-sample \
--sample "$scratch/sample.apk"
)
test -f "$caller/work/caller-default/scope.md"
grep -Eq '^- project_root: .*/caller-project$' "$caller/work/caller-default/scope.md"
grep -Eq '^- mode: offline$' "$caller/work/caller-default/scope.md"
grep -Eq '^- ready_for_act: true$' "$caller/work/caller-default/scope.md"
bash skills/scripts/case-guard.sh --case-root "$caller/work/caller-default"
test ! -e "$GITHUB_WORKSPACE/work/caller-default"
if bash skills/scripts/case-init.sh \
--hint "missing offline apk" \
--case-name "missing-sample" \
--project-root "$caller" \
--preset offline-sample \
--sample "$scratch/missing.apk"; then
echo "missing offline sample was accepted" >&2
exit 1
fi
# Compatibility: legacy --package-root still pins the work root.
bash skills/scripts/case-init.sh \
--hint "authorized web review" \
--case-name "network-default" \
--package-root "$scratch/project" \
--auth-granted \
--target-url "https://example.test/"
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/network-default/scope.md"
grep -Eq '^- ready_for_act: true$' "$scratch/project/work/network-default/scope.md"
bash skills/scripts/case-guard.sh --case-root "$scratch/project/work/network-default"
if bash skills/scripts/case-init.sh \
--hint "offline apk" \
--case-name "../case-escape" \
@@ -115,16 +201,6 @@ jobs:
exit 1
fi
bash skills/scripts/case-init.sh \
--hint "authorized web review" \
--case-name "network-default" \
--package-root "$scratch/project" \
--auth-granted \
--target-url "https://example.test/"
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/network-default/scope.md"
grep -Eq '^- ready_for_act: true$' "$scratch/project/work/network-default/scope.md"
bash skills/scripts/case-guard.sh --case-root "$scratch/project/work/network-default"
bash skills/scripts/case-init.sh \
--hint "authorized web review" \
--case-name "uppercase-network" \
@@ -151,6 +227,19 @@ jobs:
exit 1
fi
# --force is compatibility-only and must not bypass the hard auth gate.
(
cd "$caller"
bash "$GITHUB_WORKSPACE/skills/scripts/case-init.sh" \
--hint "pending offline apk" \
--case-name "force-auth" \
--sample "$scratch/sample.apk"
)
if bash skills/scripts/case-guard.sh --case-root "$caller/work/force-auth" --force; then
echo "case-guard --force bypassed auth.status hard gate" >&2
exit 1
fi
- name: PowerShell syntax check (PSParser, all tracked .ps1)
shell: pwsh
run: |
+22 -15
View File
@@ -6,37 +6,44 @@
用户任务命中安全/逆向关键词时:
1. `skills/MASTER-ROUTING.md` 或 `powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/master-route.ps1 -Hint "<任务>"` → PRIMARY
1. `skills/MASTER-ROUTING.md` 或平台对应入口 → PRIMARY:
- Windows:`powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/master-route.ps1 -Hint "<任务>"`
- Linux / macOS / Kali:`bash skills/scripts/master-route.sh --hint "<任务>"`
2. 歧义时读 `skills/routing.md` 全矩阵(三轴:目标类型 / 用户意图 / 工具链)
3. 路由规则唯一事实源:`skills/config/routing.json`(改路由只改这里)
## 授权门禁(硬性)
- 对任何目标动手前:`powershell -File skills/scripts/case-init.ps1 -Hint "<任务>"` 生成 `work/<case>/scope.md`
- `auth.status=granted` + `network_profile` 就绪前**禁止 ACT**
- 对任何目标动手前,按平台初始化当前分析项目的 `work/<case>/scope.md`:
- Windows:`powershell -File skills/scripts/case-init.ps1 -Hint "<任务>"`
- Linux / macOS / Kali:`bash skills/scripts/case-init.sh --hint "<任务>"`
- 本地离线样本可使用 `offline-sample` preset;`auth.status=granted` + 明确 sample 才可进入 ACT。
- `auth.status=granted` + 合法 `network_profile` / offline sample 就绪前**禁止 ACT**;`case-guard --force` / `-Force` 不得绕过这个硬门。
- 证据链:`skills/ops/evidence-finding-path.md`;角色:`skills/ops/role-map.md`
## 首次运行
`skills/tool-index.md` 是 gitignored 的生成文件,首次使用前运行:
`skills/tool-index.md` 是 gitignored 的生成文件,首次使用前按平台运行:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/refresh-tool-index.ps1
```text
Windows: powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/refresh-tool-index.ps1
Linux / macOS: bash skills/scripts/refresh-tool-index.sh
Kali: bash kali/scripts/refresh-tool-index.sh
```
缺工具 → `skills/scripts/bootstrap-reverse.ps1`(清单能力,禁止猜路径)。
缺工具 → 使用同平台 bootstrap:Windows `skills/scripts/bootstrap-reverse.ps1`;Linux / macOS `skills/scripts/bootstrap-reverse.sh`;Kali `kali/scripts/bootstrap-reverse.sh`(清单能力,禁止猜路径)。
## 测试(改动后必跑)
```powershell
# 路由回归(routing-benchmark.json,修改 routing.json 后必跑)
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/test-routing.ps1
```text
Windows / PowerShell(路由回归读取 routing-benchmark.json):
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/test-routing.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/verify-routing-coherence.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/smoke.ps1
# 结构一致性 + 供应链 pin gate
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/verify-routing-coherence.ps1
# 冒烟(verify + 脚本解析 + 快速路由)
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/smoke.ps1
Linux / macOS routing parity:
bash skills/scripts/test-routing.sh
bash skills/scripts/test-bootstrap-manifest.sh
```
## 客户端边界
+55 -30
View File
@@ -24,7 +24,7 @@ AI Community: https://linux.do
### Automatic Configuration Process
```text
0. ⚠️ Run refresh-tool-index first to generate skills/tool-index.md (see warning above)
0. ⚠️ Run the platform-native refresh-tool-index first to generate skills/tool-index.md (see warning above)
1. Detect the actual installation path of this package (derived from the location of this file, i.e., the directory containing README.md)
2. Detect the local operating system and distribution:
- Windows → continue with this README and the PowerShell script path
@@ -33,13 +33,15 @@ AI Community: https://linux.do
- macOS → read docs/platforms/macos.md
- Other / unknown → read docs/PLATFORMS.md and choose the closest deployment path
3. Follow the platform-specific deployment document to check toolchains, script entry points, MCP configuration, and path conventions
4. If the current system supports Bash, prefer the parity bootstrap entry: bash skills/scripts/bootstrap-reverse.sh <capability>; for index refresh only, run: bash skills/scripts/refresh-tool-index.sh
4. Use the native bootstrap entry for the current platform; Linux/macOS do not require PowerShell for the core routing/case flow
5. Read RULES.md → execute all instructions inside it (CRITICAL block, global injection, precedent-auth, routing)
6. Route via skills/MASTER-ROUTING.md or:
- Windows: `powershell -File skills/scripts/master-route.ps1 -Hint "<task>"`
- Linux/macOS/Kali: open MASTER-ROUTING.md (or run the same script under pwsh if available)
7. **Ops gate (MUST):** `powershell -File skills/scripts/case-init.ps1 -Hint "<task>"` (or hand-write `work/<case>/scope.md` per `skills/ops/scope-contract.md`).
Set `auth.status=granted` + `network_profile` before any target ACT. Evidence chain: `skills/ops/evidence-finding-path.md`. Roles: `skills/ops/role-map.md`. Identity: `skills/ops/IDENTITY.md`.
- Linux/macOS/Kali: `bash skills/scripts/master-route.sh --hint "<task>"`
7. **Ops gate (MUST):** initialize the case using the native platform entry:
- Windows: `powershell -File skills/scripts/case-init.ps1 -Hint "<task>"`
- Linux/macOS/Kali: `bash skills/scripts/case-init.sh --hint "<task>"`
Both default case artifacts to the caller analysis project's `work/<case>/`. Set `auth.status=granted` + a valid network profile before target ACT. An authorized local sample may remain `offline` when an explicit sample is supplied through the `offline-sample` preset. `-Force`/`--force` never bypasses the scope hard gate. Evidence chain: `skills/ops/evidence-finding-path.md`. Roles: `skills/ops/role-map.md`. Identity: `skills/ops/IDENTITY.md`.
8. Open PRIMARY SKILL.md → execute ACTION REQUIRED. Append timeline/workitems under the case dir.
9. Before report handoff, run `python3 skills/case-review/scripts/review_case.py work/<case> --verify-hashes --strict` and resolve every error.
10. Continue the behavior chain → report via docs-generator + field-journal.
@@ -49,10 +51,10 @@ AI Community: https://linux.do
| Detection result | Signal | Required deployment document | Detection / deployment entry |
|---|---|---|---|
| Windows | PowerShell, `$env:OS`, Windows paths | `README_AI.md` | `skills/scripts/*.ps1` |
| Kali Linux | `/etc/os-release` contains `kali` | `kali/README-kali.md` | `kali/scripts/bootstrap-reverse.sh` / `kali/scripts/refresh-tool-index.sh` |
| Ubuntu / Debian / Mint / Pop!_OS | `/etc/os-release` contains the distro ID | `docs/platforms/linux.md` | `skills/scripts/bootstrap-reverse.sh` / `skills/scripts/refresh-tool-index.sh` |
| macOS | `uname -s` = `Darwin` | `docs/platforms/macos.md` | `skills/scripts/bootstrap-reverse.sh` / `skills/scripts/refresh-tool-index.sh` |
| Windows | PowerShell, `$env:OS`, Windows paths | `README_AI.md` | `skills/scripts/master-route.ps1` / `case-init.ps1` / `bootstrap-reverse.ps1` / `refresh-tool-index.ps1` |
| Kali Linux | `/etc/os-release` contains `kali` | `kali/README-kali.md` | `skills/scripts/master-route.sh` / `case-init.sh`; Kali bootstrap/refresh under `kali/scripts/` |
| Ubuntu / Debian / Mint / Pop!_OS | `/etc/os-release` contains the distro ID | `docs/platforms/linux.md` | `skills/scripts/master-route.sh` / `case-init.sh` / `bootstrap-reverse.sh` / `refresh-tool-index.sh` |
| macOS | `uname -s` = `Darwin` | `docs/platforms/macos.md` | `skills/scripts/master-route.sh` / `case-init.sh` / `bootstrap-reverse.sh` / `refresh-tool-index.sh` |
| Other / unknown | Cannot identify confidently | `docs/PLATFORMS.md` | Choose the closest platform, then continue |
> RULES.md contains the full behavior chain (steps 0–14). After reading this file, first complete OS detection and platform-document routing, then read RULES.md and start executing. Do not stop at "configuration completed."
@@ -74,7 +76,7 @@ AI Community: https://linux.do
**Tool index**: <tool-index.md / tool-index.json path>
**Rules written to**: <write location>
**Note**: Future reverse-engineering / penetration-testing / security tasks will be routed automatically. Missing tools will be installed automatically when needed.
**Ops**: Before target ACT, ensure case scope (`case-init` / `ops/scope-contract`) has auth granted + network_profile.
**Ops**: Before target ACT, ensure case scope (`case-init` / `ops/scope-contract`) has auth granted + a valid network/offline-sample profile.
```
---
@@ -92,18 +94,21 @@ It solves two problems:
| Platform | Status | Entry |
|---|---|---|
| Windows | Full primary path | `README_AI.md`, PowerShell scripts |
| Kali Linux | Specialized support | `kali/README-kali.md`, `kali/scripts/bootstrap-reverse.sh`, `kali/scripts/refresh-tool-index.sh` |
| Ubuntu / Debian Linux | Generic support | `docs/platforms/linux.md`, `skills/scripts/bootstrap-reverse.sh`, `skills/scripts/refresh-tool-index.sh` |
| macOS | Generic support | `docs/platforms/macos.md`, `skills/scripts/bootstrap-reverse.sh`, `skills/scripts/refresh-tool-index.sh` |
| Windows | Full primary path | `README_AI.md`, `skills/scripts/master-route.ps1`, `case-init.ps1`, PowerShell bootstrap/refresh |
| Kali Linux | Specialized support | `skills/scripts/master-route.sh`, `case-init.sh`, `kali/README-kali.md`, Kali bootstrap/refresh |
| Ubuntu / Debian Linux | Generic support | `docs/platforms/linux.md`, `skills/scripts/master-route.sh`, `case-init.sh`, Bash bootstrap/refresh |
| macOS | Generic support | `docs/platforms/macos.md`, `skills/scripts/master-route.sh`, `case-init.sh`, Bash bootstrap/refresh |
Generic Linux/macOS users can list bootstrap capabilities with:
Generic Linux/macOS users can run the core routing/case path without installing PowerShell:
```bash
bash skills/scripts/master-route.sh --hint "offline apk"
bash skills/scripts/case-init.sh --hint "offline apk" --case-name my-sample --preset offline-sample --sample ./app.apk
bash skills/scripts/case-guard.sh --case-root work/my-sample
bash skills/scripts/bootstrap-reverse.sh --list
```
Kali users should use the dedicated Kali entrypoint:
Kali users should use the dedicated Kali bootstrap entrypoint:
```bash
bash kali/scripts/bootstrap-reverse.sh
@@ -272,10 +277,12 @@ Full dependency table with paths in the original [README.md](README.md).
### Refresh the Tool Index
Do not trust someone else's scan result for long. After migrating to a new machine, refresh it first:
Do not trust someone else's scan result for long. After migrating to a new machine, refresh it first with the native platform entry:
```powershell
powershell -File "<SKILL_ROOT>\skills\scripts\refresh-tool-index.ps1"
```text
Windows: powershell -File "<SKILL_ROOT>\skills\scripts\refresh-tool-index.ps1"
Linux / macOS: bash <SKILL_ROOT>/skills/scripts/refresh-tool-index.sh
Kali: bash <SKILL_ROOT>/kali/scripts/refresh-tool-index.sh
```
After success, check:
@@ -403,19 +410,23 @@ The key is to inject: package path, key entry files, MCP addresses, and "route f
If you have configured `.claude\settings.local.json` or `.claude\scripts\route-reverse.ps1`, update all old paths after migration.
### Tool Index
After migration, run again:
```powershell
powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
After migration, run the native refresh command again:
```text
Windows: powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
Linux / macOS: bash <your skill root>/skills/scripts/refresh-tool-index.sh
Kali: bash <your skill root>/kali/scripts/refresh-tool-index.sh
```
---
## Recommended Verification Checklist
```powershell
Core runtime checks:
```text
java -version
python --version
pip --version
python --version # or python3 --version
node -v
npx -v
jadx --version
@@ -424,14 +435,28 @@ adb version
frida-ps -U
```
IDA chain:
Core routing/case contract:
```text
Windows:
powershell -File skills/scripts/master-route.ps1 -Hint "offline apk"
powershell -File skills/scripts/case-init.ps1 -Hint "offline apk" -CaseName verify-sample -Preset offline-sample -Sample ".\sample.apk"
Linux / macOS / Kali:
bash skills/scripts/master-route.sh --hint "offline apk"
bash skills/scripts/case-init.sh --hint "offline apk" --case-name verify-sample --preset offline-sample --sample ./sample.apk
```
IDA chain on Windows:
```powershell
powershell -File "<your skill root>\ida-reverse\scripts\start.ps1"
```
Tool index:
```powershell
powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
```text
Windows: powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
Linux / macOS: bash <your skill root>/skills/scripts/refresh-tool-index.sh
Kali: bash <your skill root>/kali/scripts/refresh-tool-index.sh
```
---
@@ -512,7 +537,7 @@ When the AI tries to auto-complete installation and still fails, it **must not s
### AI Failure-Handling Flow
```text
1. Call bootstrap-reverse.ps1 to attempt automatic installation
1. Call the platform-native bootstrap (`bootstrap-reverse.ps1` on Windows, `bootstrap-reverse.sh` on Linux/macOS, Kali bootstrap under `kali/scripts/`)
2. Verify whether the tool is usable after installation
3. If it is still unavailable → do not retry → immediately output structured guidance
```
@@ -577,4 +602,4 @@ This project (`reverse-skill`) is primarily licensed under the **MIT License**.
This package is intended only for legally authorized security research, learning, and CTF competitions.
- Users must ensure all operations are within legal boundaries
- Unauthorized penetration testing against other people's systems is illegal
- The package author is not responsible for misuse
- The package author is not responsible for misuse
+24 -21
View File
@@ -12,11 +12,13 @@
After reading this file, you MUST NOW (immediately) execute:
```
```text
1. NOW: This file's directory is the package root
2. NOW: Run skills/scripts/master-route.ps1 -Hint "<task>" → PRIMARY (SSoT: skills/config/routing.json)
3. NEXT: case-init.ps1 until scope.md has auth.status=granted and a legal network_profile. Mentioning a target is NOT granted.
4. ACT: Open PRIMARY SKILL.md and execute ACTION REQUIRED. Tools only from tool-index.md; missing → bootstrap-reverse.ps1
2. NOW: Run the platform-native router → PRIMARY (SSoT: skills/config/routing.json)
- Windows: powershell -File skills/scripts/master-route.ps1 -Hint "<task>"
- Linux/macOS/Kali: bash skills/scripts/master-route.sh --hint "<task>"
3. NEXT: Run the platform-native case-init until scope.md has auth.status=granted plus a legal network_profile, or an explicitly authorized offline-sample scope is ready. Mentioning a target is NOT granted. -Force/--force never bypasses the gate.
4. ACT: Open PRIMARY SKILL.md and execute ACTION REQUIRED. Tools only from tool-index.md; missing → platform-native bootstrap.
Optional later (do NOT preload):
- Ambiguous PRIMARY → skills/routing.md (advisory matrix only)
@@ -27,7 +29,7 @@ Optional later (do NOT preload):
IMPORTANT — Shared installation:
- tool-index.md is the SINGLE SOURCE OF TRUTH for tool availability
- If another CLI already installed tools (tool-index shows "yes"), DO NOT reinstall
- Only run refresh-tool-index.ps1 if you suspect tool-index is stale (e.g., user says "I just installed X")
- Only run the platform-native refresh-tool-index if you suspect tool-index is stale (e.g., user says "I just installed X")
- Only run bootstrap for tools that are BOTH needed AND marked "no"
Conditional reads (load only when needed, do NOT preload):
@@ -147,19 +149,19 @@ Hot path only:
## Canonical Behavior Chain (All other files reference THIS version)
```
```text
1. Identify task as security/reverse type → trigger this routing rule
2. Detect package root path (derive from this file's location)
3. master-route.ps1 -Hint → PRIMARY from skills/config/routing.json
4. case-init.ps1 / scope.md (ops/scope-contract) — auth.status=granted + network_profile before any target ACT. precedent-auth.md does not grant.
3. Platform-native master-route (`.ps1` Windows / `.sh` Linux, macOS, Kali) → PRIMARY from skills/config/routing.json; use routing.md only when ambiguous
4. Platform-native case-init / scope.md (ops/scope-contract) — auth.status=granted + valid network profile, or explicit authorized offline sample, before any target ACT; Force never bypasses the hard gate
5. Open PRIMARY SKILL.md ACTION REQUIRED
6. Route not matched → propose new skill (edit routing.json + benchmark; do not hand-edit routing.md as SSoT)
7. tool-index.md → real paths; missing (first run) → template + refresh-tool-index
8. Missing tools → platform bootstrap (Windows ps1 / Linux sh / Kali sh)
9. Execute PRIMARY workflow (timeline/workitems; Evidence→Finding→Path)
7. Read tool-index.md → confirm local tool status. If missing (first run) → template + platform-native refresh-tool-index
8. Missing tools → platform bootstrap + refresh (Windows ps1 / Linux sh / Kali sh)
9. Enter skill workflow → execute (timeline/workitems; Evidence→Finding→Path per ops/)
10. Continuously report progress (do NOT go silent)
13. Task complete → Completion Checklist (report must include Evidence chain)
14. Output final results
11. Task complete → Completion Checklist (report must include Evidence chain)
12. Output final results
```
---
@@ -225,7 +227,6 @@ After task completion (vulnerability verified / reverse complete / flag captured
| "IAT repair keeps failing; I'll grind more static unpackers" | **IAT repair iron rule:** try auto/semi-auto repair first; on tool error or unreable binary after repair, STOP static IAT, record E-iat-repair-fail, switch to dynamic API breakpoints. FORBIDDEN infinite static IAT thrash. |
| "No import table (.NET) so the hard gate does not apply" | **Equivalent anchor still MUST:** .NET → dnSpy/IL/metadata summary into E-imports slot; DLL/SYS → E-exports alongside imports. FORBIDDEN to skip the gate. |
---
## Self-Audit Before Claiming "Complete"
@@ -271,7 +272,7 @@ Before saying "task complete" or "done", MUST self-check:
## Context Window Layout Rules (Attention Optimization)
LLM attention distribution (high→low):
```
```text
[First 10%] ████████████ ← Highest attention — put "immediate action" instructions here
[Middle 80%] ████░░░░░░░░ ← Attention decays — put reference materials here
[Last 10%] ████████████ ← Attention recovers — put "MUST NOT skip" and Checklist here
@@ -291,7 +292,7 @@ When tool parameters MUST be passed exactly as given, use opaque identifiers (co
- **MUST NOT**: Let Agent freely rewrite semantic parameters (e.g., changing strict/deny to lenient synonyms)
Example:
```
```text
alpha -> --scope authorized-only
beta -> --approval required
gamma -> --destructive false
@@ -383,15 +384,17 @@ bash <SKILL_ROOT>/kali/scripts/refresh-tool-index.sh
### Post-Trigger Execution (Compact — do NOT re-run first-time setup!)
```
1. NOW: Run <SKILL_ROOT>/skills/scripts/master-route.ps1 -Hint "<task>" → PRIMARY
2. NEXT: case-init.ps1 / scope.md — auth.status=granted + network_profile; MUST NOT ACT against targets until ready
3. ACT: Open PRIMARY SKILL.md
```text
1. NOW: Run the platform-native master-route (.ps1 on Windows / .sh on Linux, macOS, Kali) → PRIMARY from routing.json
2. NEXT: If ambiguous, open <SKILL_ROOT>/skills/routing.md
3. NEXT: Use platform-native case-init / scope.md — set auth.status=granted + valid network profile, or an explicit authorized offline-sample scope; Force never bypasses the hard gate
4. ACT: Open PRIMARY SKILL.md; timeline/workitems + Evidence→Finding→Path (ops/*)
```
### Core Rules (Compact)
- **MUST**: case scope (case-init / ops/scope-contract) before ACT; auth.status=granted + network_profile required
- **MUST**: case scope (platform-native case-init / ops/scope-contract) before ACT; auth.status=granted + valid network/offline-sample scope required
- **MUST**: `-Force` / `--force` never bypasses authorization, scope, network, or readiness gates
- **MUST**: Missing tools → bootstrap, NEVER guess paths
- **MUST NOT**: Treat precedent-auth.md or "user named a target" as granted
- **MUST NOT**: Reply "understood, tell me your task" after reading rules
+25 -2
View File
@@ -1,6 +1,6 @@
# reverse-skill PRIMARY 快路径
> 与 `scripts/master-route.ps1` 保持一致。
> `scripts/master-route.ps1` 与 `scripts/master-route.sh` 必须保持相同路由契约;平台只改变执行入口,不改变 routing semantics。
## 执行契约
@@ -15,6 +15,8 @@
8. 未命中 → 读 routing.md 全表或提议新 skill
```
### Windows
```powershell
powershell -File skills\scripts\master-route.ps1 -Hint "<用户任务>"
# 默认写出当前项目的 work/master-route-<ts>/route-scope.md;从其他目录调用时显式指定项目根
@@ -24,15 +26,36 @@ powershell -File skills\scripts\case-init.ps1 -Hint "<用户任务>" -CaseName "
powershell -File skills\scripts\case-init.ps1 -Hint "<用户任务>" -CaseName "my-case" -ProjectRoot "C:\path\to\analysis-project"
# 一次成型可 ACT(授权 + 目标 + 网络档):
powershell -File skills\scripts\case-init.ps1 -Hint "<任务>" -CaseName "my-case" -AuthGranted -TargetUrl "https://target/" -NetworkProfile authorized_target_only
# 本地离线样本:
powershell -File skills\scripts\case-init.ps1 -Hint "offline apk" -CaseName "my-sample" -Preset offline-sample -Sample ".\app.apk"
# 冒烟:verify + 脚本解析 + 路由矩阵(含中文 Hint)
powershell -File skills\scripts\smoke.ps1
# ACT 前轻量 scope 门禁(未就绪 exit 2;-Force 仅警告)
# ACT 前轻量 scope 门禁(未就绪 exit 2;-Force 为兼容参数,不能绕过硬门)
powershell -File skills\scripts\case-guard.ps1 -CaseRoot work\my-case
# Evidence 追加
powershell -File skills\scripts\append-evidence.ps1 -CaseRoot work\my-case -Id E-001 -Title "..." -ReproCommand "..."
python3 skills/case-review/scripts/review_case.py work/<case> --verify-hashes --strict
```
### Linux / macOS / Kali
不要求为了核心 route/case 流程安装 PowerShell:
```bash
bash skills/scripts/master-route.sh --hint "<用户任务>"
bash skills/scripts/master-route.sh --hint "<用户任务>" --project-root "/path/to/analysis-project"
bash skills/scripts/case-init.sh --hint "<用户任务>" --case-name "my-case"
bash skills/scripts/case-init.sh --hint "<用户任务>" --case-name "my-case" --project-root "/path/to/analysis-project"
# 本地离线样本:
bash skills/scripts/case-init.sh --hint "offline apk" --case-name "my-sample" --preset offline-sample --sample ./app.apk
# ACT 前轻量 scope 门禁(--force 为兼容参数,不能绕过硬门):
bash skills/scripts/case-guard.sh --case-root work/my-sample
# 路由 parity:
bash skills/scripts/test-routing.sh
bash skills/scripts/test-bootstrap-manifest.sh
python3 skills/case-review/scripts/review_case.py work/<case> --verify-hashes --strict
```
## 作战契约(ops)
| 文档 | 用途 |
+18 -7
View File
@@ -10,10 +10,10 @@ description: Routes reverse engineering, exploitation, penetration testing, malw
读完本文件后,不允许只回复“已读/已理解”。必须按顺序执行:
1. `NOW`:跑 `scripts/master-route.ps1 -Hint "..."`(SSoT:`config/routing.json`)定 PRIMARY。
2. `NOW`:`scripts/case-init.ps1` 落地 `work/<case>/scope.md`;**auth 未 granted 禁止对目标 ACT**。点名目标 ≠ granted。
1. `NOW`:跑平台原生 router(Windows `scripts/master-route.ps1`;Linux/macOS/Kali `scripts/master-route.sh`),从 `config/routing.json` 定 PRIMARY;疑难再读 `routing.md` 三轴附录。
2. `NOW`:平台原生 `case-init` 落地当前分析项目的 `work/<case>/scope.md`;**auth 未 granted 禁止对目标 ACT**。本地离线样本使用 `offline-sample` preset + explicit sample;Force 不得绕过硬门。
3. `ACT`:立即打开 PRIMARY `SKILL.md` 执行 ACTION REQUIRED。
4. `NEXT`:工具路径只认 `tool-index.md`;缺工具 → `bootstrap-reverse.ps1`(仅 manifest)。
4. `NEXT`:工具路径只认 `tool-index.md`;缺工具 → 平台原生 bootstrap(仅 manifest)。
5. 结论用 Evidence→Finding→Path。报告/journal 是 SHOULD,除非用户要交付物。
**身份**:见 `ops/IDENTITY.md`(轻量路由包 + 工具自举 + journal;**不是** Z3r0 式平台)。
@@ -82,10 +82,10 @@ description: Routes reverse engineering, exploitation, penetration testing, malw
遇到逆向、CTF、抓包、前端签名、APK 改包、二进制分析类任务时,先按这个顺序进入:
1. `scripts/master-route.ps1` → PRIMARY(`config/routing.json`)
2. `case-init.ps1` → `scope.md`
1. 平台原生 router(Windows `scripts/master-route.ps1`;Linux/macOS/Kali `scripts/master-route.sh`)→ PRIMARY(`config/routing.json`)
2. 平台原生 `case-init` → `scope.md`
3. 打开 PRIMARY `SKILL.md`
4. 需要本机路径时再读 `tool-index.md`
4. 疑难时读 `routing.md`,需要本机路径时读 `tool-index.md`
## 工作思路
@@ -136,12 +136,23 @@ description: Routes reverse engineering, exploitation, penetration testing, malw
## 按需自举
当 workflow 发现缺少工具时,不要直接报错。统一调用:
当 workflow 发现缺少工具时,不要直接报错。统一调用平台原生 bootstrap:
Windows:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File "<skill-root>\scripts\bootstrap-reverse.ps1" -Capability @('工具名') -StartServices
```
Linux / macOS:
```bash
bash <skill-root>/scripts/bootstrap-reverse.sh 工具名 --start-services
```
Kali:
```bash
bash <package-root>/kali/scripts/bootstrap-reverse.sh 工具名 --start-services
```
支持的能力(以 `scripts/bootstrap-manifest.json` 为准):jadx、apktool、jeb-pro、frida、frida-ps、idalib-mcp、reqable-mcp、jshookmcp、anything-analyzer、idapro、r2、rabin2、adb、agent-browser、ghidra-mcp、seclists、proxycat、burpsuite-mcp、nmap、pentestswarm、binwalk、yara、pwntools、bkcrack
> JEB Pro 已登记为**手动许可安装**能力:bootstrap 只输出指引,绝不下载或规避商业许可。Reqable MCP 仅登记固定版本的官方运行时,仍需要用户自行安装 Reqable 桌面客户端。
+27 -3
View File
@@ -1,17 +1,38 @@
# 通用 Scope 契约(任务启动硬门槛)
> **MUST**:任何安全/逆向/渗透任务在 **ACT 之前** 在用户项目或 `work/<case>/` 落地 `scope.md`。
> 无 scope → 只允许读文档/路由,**禁止** 对目标主动扫描、Hook、利用。
> **MUST**:任何安全/逆向/渗透任务在 **ACT 之前** 在当前用户分析项目的 `work/<case>/` 落地 `scope.md`。
> 无 scope → 只允许读文档/路由,**禁止** 对目标主动扫描、Hook、利用。
> 模板可复制;字段名保持英文键,便于脚本校验。
## 如何初始化
Windows:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1 -Hint "<任务一句话>" -CaseName "my-case"
# 默认产出:当前分析项目的 work/<case>/scope.md 等
# 从其他目录调用 skill 时显式指定:-ProjectRoot "C:\path\to\analysis-project"
# 合法本地离线样本:auth granted + offline + explicit sample → ready_for_act=true
powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1 `
-Hint "offline apk" -CaseName "my-sample" -Preset offline-sample -Sample ".\app.apk"
```
Linux / macOS / Kali:
```bash
bash skills/scripts/case-init.sh --hint "<任务一句话>" --case-name "my-case"
# 默认产出:caller 当前分析项目的 work/<case>/scope.md 等
# 从其他目录调用时显式指定:--project-root "/path/to/analysis-project"
# 合法本地离线样本
bash skills/scripts/case-init.sh \
--hint "offline apk" --case-name "my-sample" \
--preset offline-sample --sample ./app.apk
```
`-PackageRoot` / `--package-root` 保留为兼容参数;新流程应以 `ProjectRoot` / `--project-root` 表示 case artifact 的归属项目。
## scope.md 完整模板
```markdown
@@ -21,6 +42,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1
- case_id: {YYYYMMDD-short}
- created: {ISO-8601}
- operator: {name or local}
- project_root: {caller analysis project}
- primary_skill: {from master-route}
- lead_role: lead # see ops/role-map.md
- specialist_roles: [] # e.g. cie, cpe, cre
@@ -73,11 +95,13 @@ powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1
```text
RULES / MASTER-ROUTING / SKILL:
1) master-route → PRIMARY
2) case-init 或手写 scope.md
2) 平台原生 case-init 或手写 scope.md
3) auth 未 granted → STOP,只允许补授权材料
4) ready_for_act = true → 打开 PRIMARY SKILL.md → ACT
```
`case-guard -Force` / `case-guard --force` 是兼容参数,**不得**绕过 `auth.status`、合法 scope、network profile 或 `ready_for_act` 硬门。
## network_profile 速查
| mode | 允许 | 禁止 |
+3 -4
View File
@@ -2,7 +2,7 @@
# Lightweight scope gate before ACT. Exit 0 = ok, 2 = not ready, 1 = usage/error.
# Usage:
# powershell -File skills/scripts/case-guard.ps1 -CaseRoot work\my-case
# powershell -File skills/scripts/case-guard.ps1 -CaseRoot work\my-case -Force # warn but exit 0
# powershell -File skills/scripts/case-guard.ps1 -CaseRoot work\my-case -Force # compatibility flag; never bypasses scope hard gates
param(
[Parameter(Mandatory = $true)]
[string] $CaseRoot,
@@ -94,9 +94,8 @@ Write-Host ("CASE-GUARD NOT READY: {0}" -f $CaseRoot) -ForegroundColor Yellow
foreach ($i in $issues) { Write-Host (" - {0}" -f $i) -ForegroundColor Yellow }
if ($Force) {
Write-Host 'CASE-GUARD: -Force set; continuing with warnings only.' -ForegroundColor Yellow
exit 0
Write-Host 'CASE-GUARD: -Force does not bypass scope hard gates.' -ForegroundColor Yellow
}
Write-Host 'Fix scope (or re-run case-init -AuthGranted -TargetUrl ...) or pass -Force.' -ForegroundColor Yellow
Write-Host 'Fix scope (or re-run case-init -AuthGranted -TargetUrl ...).' -ForegroundColor Yellow
exit 2
+3 -4
View File
@@ -2,7 +2,7 @@
# Lightweight scope gate before ACT. Exit 0=ok, 2=not ready, 1=usage/error.
# Usage:
# bash skills/scripts/case-guard.sh --case-root work/my-case
# bash skills/scripts/case-guard.sh --case-root work/my-case --force
# bash skills/scripts/case-guard.sh --case-root work/my-case --force # compatibility flag; never bypasses scope hard gates
set -euo pipefail
CASE_ROOT=""
@@ -120,9 +120,8 @@ echo "CASE-GUARD NOT READY: $CASE_ROOT"
for i in "${ISSUES[@]}"; do echo " - $i"; done
if [[ $FORCE -eq 1 ]]; then
echo "CASE-GUARD: --force set; continuing with warnings only."
exit 0
echo "CASE-GUARD: --force does not bypass scope hard gates."
fi
echo "Fix scope (or re-run case-init with --auth-granted --target-url ...) or pass --force."
echo "Fix scope (or re-run case-init with --auth-granted --target-url ...)."
exit 2
+58 -8
View File
@@ -4,6 +4,9 @@
# Ready-to-act example:
# powershell -File skills/scripts/case-init.ps1 -Hint "web pentest" -CaseName my-case `
# -AuthGranted -TargetUrl "https://app.example/" -NetworkProfile authorized_target_only
# Offline sample ready-to-act example:
# powershell -File skills/scripts/case-init.ps1 -Hint "offline apk" -CaseName my-sample `
# -Preset offline-sample -Sample ".\app.apk"
param(
[string] $Hint = '',
[string] $CaseName = '',
@@ -15,6 +18,8 @@ param(
[string] $AuthBasis = 'own_system',
[string] $EvidenceOfAuth = '',
[string] $TargetUrl = '',
[string] $Sample = '',
[string] $Preset = '',
[string[]] $InScopeAssets = @(),
[string] $NetworkProfile = '',
[switch] $ReadyForAct
@@ -37,6 +42,43 @@ $requestedProjectRoot = if (-not [string]::IsNullOrWhiteSpace($ProjectRoot)) {
}
$projectRoot = Resolve-ReverseProjectRoot -RequestedRoot $requestedProjectRoot
if (-not [string]::IsNullOrWhiteSpace($Sample)) {
try {
$Sample = [System.IO.Path]::GetFullPath($Sample)
} catch {
throw "Invalid -Sample path '$Sample': $($_.Exception.Message)"
}
if (-not (Test-Path -LiteralPath $Sample -PathType Leaf)) {
throw "Local -Sample file not found: $Sample"
}
}
# Cross-platform case presets. Keep semantics aligned with case-init.sh.
$presetNormalized = $Preset.Trim().ToLowerInvariant()
if ($presetNormalized -in @('offline-sample', 'own-sample', 'local-sample')) {
$AuthGranted = $true
$AuthStatus = 'granted'
$AuthBasis = 'own_system'
if ([string]::IsNullOrWhiteSpace($NetworkProfile)) { $NetworkProfile = 'offline' }
if ([string]::IsNullOrWhiteSpace($EvidenceOfAuth)) {
$EvidenceOfAuth = 'preset:offline-sample (owner-operated local file)'
}
} elseif ($presetNormalized -in @('ctf-public', 'ctf')) {
$AuthGranted = $true
$AuthStatus = 'granted'
$AuthBasis = 'ctf_public'
if ([string]::IsNullOrWhiteSpace($NetworkProfile)) { $NetworkProfile = 'authorized_target_only' }
if ([string]::IsNullOrWhiteSpace($EvidenceOfAuth)) { $EvidenceOfAuth = 'preset:ctf-public' }
} elseif ($presetNormalized -in @('own-system', 'lab-only')) {
$AuthGranted = $true
$AuthStatus = 'granted'
$AuthBasis = 'own_system'
if ([string]::IsNullOrWhiteSpace($NetworkProfile)) { $NetworkProfile = 'lab_only' }
if ([string]::IsNullOrWhiteSpace($EvidenceOfAuth)) { $EvidenceOfAuth = 'preset:own-system/lab' }
} elseif (-not [string]::IsNullOrWhiteSpace($Preset)) {
Write-Host ("WARN: unknown -Preset '{0}' (allowed: offline-sample|ctf-public|own-system)" -f $Preset) -ForegroundColor Yellow
}
if (-not $CaseName) {
$slug = if ($Hint) {
($Hint.ToLowerInvariant() -replace '[^a-z0-9]+', '-').Trim('-')
@@ -92,6 +134,9 @@ $evidenceAuth = if (-not [string]::IsNullOrWhiteSpace($EvidenceOfAuth)) {
$assets = New-Object System.Collections.Generic.List[string]
if (-not [string]::IsNullOrWhiteSpace($TargetUrl)) { [void]$assets.Add($TargetUrl.Trim()) }
if (-not [string]::IsNullOrWhiteSpace($Sample) -and -not $assets.Contains($Sample.Trim())) {
[void]$assets.Add($Sample.Trim())
}
foreach ($a in @($InScopeAssets)) {
if (-not [string]::IsNullOrWhiteSpace($a) -and -not $assets.Contains($a.Trim())) {
[void]$assets.Add($a.Trim())
@@ -105,8 +150,8 @@ if ($assets.Count -eq 0 -and $Hint -match 'https?://([^\s/]+)') {
$networkMode = 'offline'
if (-not [string]::IsNullOrWhiteSpace($NetworkProfile)) {
$networkMode = $NetworkProfile.Trim()
} elseif ($assets.Count -gt 0 -and $authStatusResolved -eq 'granted') {
# training labs / intentional vulns often use lab_only; default authorized_target_only
} elseif ($assets.Count -gt 0 -and $authStatusResolved -eq 'granted' -and [string]::IsNullOrWhiteSpace($Sample)) {
# Authorized network targets default to target-only. Explicit local samples remain offline.
$networkMode = 'authorized_target_only'
}
# normalize common aliases
@@ -124,19 +169,21 @@ if ($networkMode -notin $allowedNetworkModes) {
throw "Invalid -NetworkProfile '$NetworkProfile'. Allowed: offline, lab_only, authorized_target_only, unrestricted_lab (aliases: lab, authorized, auth, offline_only)."
}
# ready_for_act requires auth granted + assets + non-offline network.
# -ReadyForAct cannot skip auth (would bypass hard gate).
# ready_for_act requires auth granted + assets. Network targets need a non-offline
# profile; an explicit local sample is valid in offline mode. -ReadyForAct never
# bypasses auth or scope.
$ready = $false
$netAllowsAct = ($networkMode -ne 'offline' -and -not [string]::IsNullOrWhiteSpace($networkMode))
if ($authStatusResolved -eq 'granted' -and $assets.Count -gt 0 -and $netAllowsAct) {
$offlineSampleReady = ($networkMode -eq 'offline' -and -not [string]::IsNullOrWhiteSpace($Sample) -and $assets.Count -gt 0)
if ($authStatusResolved -eq 'granted' -and $assets.Count -gt 0 -and ($netAllowsAct -or $offlineSampleReady)) {
$ready = $true
} elseif ($ReadyForAct) {
if ($authStatusResolved -ne 'granted') {
Write-Host 'WARN: -ReadyForAct ignored because auth.status is not granted' -ForegroundColor Yellow
} elseif ($assets.Count -eq 0) {
Write-Host 'WARN: -ReadyForAct ignored because in_scope.assets is empty' -ForegroundColor Yellow
} elseif (-not $netAllowsAct) {
Write-Host 'WARN: -ReadyForAct ignored because network_profile is offline/empty' -ForegroundColor Yellow
} elseif (-not $netAllowsAct -and -not $offlineSampleReady) {
Write-Host 'WARN: -ReadyForAct ignored because offline mode requires an explicit -Sample' -ForegroundColor Yellow
}
}
@@ -197,6 +244,7 @@ $scope = @"
- lead_role: lead
- specialist_roles: []
- hint: $Hint
- preset: $(if ([string]::IsNullOrWhiteSpace($Preset)) { 'none' } else { $Preset })
## auth
- status: $authStatusResolved
@@ -297,7 +345,9 @@ $readmeNext = if ($ready) {
"@
} else {
@"
1. Edit ``scope.md`` — set auth.status=granted and in_scope (or re-run with -AuthGranted -TargetUrl)
1. Edit ``scope.md`` — set auth.status=granted and in_scope
- network target: re-run with ``-AuthGranted -TargetUrl <url>``
- local sample: re-run with ``-Preset offline-sample -Sample <path>``
2. Set ready_for_act when checklist complete
3. Open primary skill: skills/$primary
4. Append ``timeline.md``; update ``workitems.md``
+23 -3
View File
@@ -9,6 +9,8 @@ set -euo pipefail
HINT=""
CASE_NAME=""
PACKAGE_ROOT=""
PROJECT_ROOT=""
PACKAGE_ROOT_BOUND=0
AUTH_STATUS=""
AUTH_GRANTED=0
AUTH_BASIS="unknown"
@@ -23,7 +25,8 @@ while [[ $# -gt 0 ]]; do
case "$1" in
-Hint|--hint) HINT="${2:-}"; shift 2 ;;
-CaseName|--case-name) CASE_NAME="${2:-}"; shift 2 ;;
-PackageRoot|--package-root) PACKAGE_ROOT="${2:-}"; shift 2 ;;
-PackageRoot|--package-root) PACKAGE_ROOT="${2:-}"; PACKAGE_ROOT_BOUND=1; shift 2 ;;
-ProjectRoot|--project-root) PROJECT_ROOT="${2:-}"; shift 2 ;;
-AuthStatus|--auth-status) AUTH_STATUS="${2:-}"; shift 2 ;;
-AuthGranted|--auth-granted) AUTH_GRANTED=1; shift ;;
-AuthBasis|--auth-basis) AUTH_BASIS="${2:-}"; shift 2 ;;
@@ -46,6 +49,22 @@ SKILLS_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
if [[ -z "$PACKAGE_ROOT" ]]; then
PACKAGE_ROOT="$(cd "$SKILLS_ROOT/.." && pwd)"
fi
if [[ -z "$PROJECT_ROOT" ]]; then
if [[ $PACKAGE_ROOT_BOUND -eq 1 ]]; then
PROJECT_ROOT="$PACKAGE_ROOT"
else
PROJECT_ROOT="$(pwd -P)"
fi
fi
if [[ -n "$SAMPLE" ]]; then
if [[ ! -f "$SAMPLE" ]]; then
echo "Local --sample file not found: $SAMPLE" >&2
exit 2
fi
sample_dir="$(cd "$(dirname "$SAMPLE")" && pwd -P)"
SAMPLE="$sample_dir/$(basename "$SAMPLE")"
fi
# Presets: reduce "AI refuses to work" friction for legitimate local/CTF work.
case "$PRESET" in
@@ -104,7 +123,7 @@ if [[ -n "$NETWORK_PROFILE" ]]; then
esac
fi
CASE_ROOT="$PACKAGE_ROOT/work/$CASE_NAME"
CASE_ROOT="$PROJECT_ROOT/work/$CASE_NAME"
mkdir -p "$CASE_ROOT/evidence" "$CASE_ROOT/notes" "$CASE_ROOT/report"
auth_status_resolved="pending"
@@ -165,7 +184,7 @@ primary="reverse-engineering/SKILL.md"
primary_id="R0"
if [[ -f "$SCRIPT_DIR/master-route.sh" ]]; then
set +e
bash "$SCRIPT_DIR/master-route.sh" --hint "$HINT" --out-dir "$ROUTE_TMP" >/dev/null 2>&1
bash "$SCRIPT_DIR/master-route.sh" --hint "$HINT" --project-root "$PROJECT_ROOT" --out-dir "$ROUTE_TMP" >/dev/null 2>&1
set -e
if [[ -f "$ROUTE_TMP/route-scope.md" ]]; then
rt="$(cat "$ROUTE_TMP/route-scope.md")"
@@ -215,6 +234,7 @@ cat > "$CASE_ROOT/scope.md" <<EOF
- case_id: $CASE_NAME
- created: $created
- operator: local
- project_root: $PROJECT_ROOT
- primary_skill: $primary
- primary_id: $primary_id
- lead_role: lead
+2 -2
View File
@@ -148,7 +148,7 @@ foreach ($zc in $zhCases) {
else { Bad ("zh route miss {0}: {1}" -f $zc.Expect, ($raw.Substring(0, [Math]::Min(120, $raw.Length)))) }
}
# 9) case-guard: ready case exits 0; bare pending exits 2
# 9) case-guard: ready case exits 0; bare pending exits 2 even with -Force
$cg = Join-Path $scriptDir 'case-guard.ps1'
& $HostExe -NoProfile -ExecutionPolicy Bypass -File $cg -CaseRoot $caseRoot 2>&1 | Out-Null
if ($LASTEXITCODE -eq 0) { Ok 'case-guard ready exit 0' } else { Bad "case-guard ready exit $LASTEXITCODE" }
@@ -156,7 +156,7 @@ $bareRoot = Join-Path $PackageRoot ("work\{0}" -f $bareName)
& $HostExe -NoProfile -ExecutionPolicy Bypass -File $cg -CaseRoot $bareRoot 2>&1 | Out-Null
if ($LASTEXITCODE -eq 2) { Ok 'case-guard pending exit 2' } else { Bad "case-guard pending expected 2 got $LASTEXITCODE" }
& $HostExe -NoProfile -ExecutionPolicy Bypass -File $cg -CaseRoot $bareRoot -Force 2>&1 | Out-Null
if ($LASTEXITCODE -eq 0) { Ok 'case-guard -Force exit 0' } else { Bad "case-guard -Force exit $LASTEXITCODE" }
if ($LASTEXITCODE -eq 2) { Ok 'case-guard -Force cannot bypass hard gate' } else { Bad "case-guard -Force expected 2 got $LASTEXITCODE" }
# 10) AuthGranted must not be clobbered by junk AuthStatus / multi-asset lab init
# Note: -ProjectRoot is passed explicitly to prevent the -InScopeAssets array