diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ca6d51..464811a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,37 @@ jobs: shell: powershell run: ./skills/scripts/test-bootstrap-supply-chain.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$') { throw 'offline sample did not keep offline network mode' } + if ($raw -notmatch '(?m)^- ready_for_act: true$') { throw 'offline sample did not become ready_for_act' } + ./skills/scripts/case-guard.ps1 -CaseRoot (Join-Path $scratch 'work/offline-sample') + + ./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 + if ($LASTEXITCODE -eq 0) { throw '-Force bypassed auth.status hard gate' } + - name: Smoke (verify + parse + quick route) shell: pwsh run: ./skills/scripts/smoke.ps1 @@ -86,6 +117,37 @@ 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" + + # 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" \ @@ -107,16 +169,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" \ @@ -143,6 +195,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: |