You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore(gh60): flip Group 11 + 9.7 checkboxes for work landed in this session (refs #60)
Marks as [x] only the items factually completed + verified during the
2026-05-26 hint/text + gate-hardening session:
9.7 openspec validate gh60-targets-core (PASS, ran multiple times)
11.1 enrichFromElement putStringAttr hint/text (commit f2d72fd)
11.2 4 hint/text Java unit tests, 138/138 PASS (commit f2d72fd)
11.3 build + deploy jar at lib/gator/ (mtime 2026-05-26 12:35)
11.4 client unit suite 138/138 PASS
11.5 cryptoapp smoke: 4/4 hint + 11/11 text + drt=21
11.6 baseline-defer decision (superseded by 11.8 per D12)
11.7 _lenient_cache.py + mtime invalidation (commit 7b916d3)
11.8 baseline regen + MANIFEST (commit c5c8dcd)
11.9 test_baseline_freshness.py 2/2 PASS (commit 7b916d3)
11.10 RV_GATOR_REQUIRED=1 fail-loud, empirically verified (commit 7b916d3)
11.11 test_historical_methods_coverage.py 2/2 PASS (commit c5c8dcd)
11.12 3 atomic commits + pushed to origin/modules
Items NOT flipped (genuinely not done in this session):
7.6 commit C1g — already landed in 355e4ef on 2026-05-25; not my work
9.1 5-APK canonical fixture — only ran cryptoapp (1 APK)
9.2 rv-experiment full pipeline integration — not run
9.3 380-APK sweep — not run
9.4 sweep complete=true rate — not measured
9.5 rv-qa-lint-fix on 7 modules — not run
9.6 rv-verify on 3 modules — not run
9.8 rv-code-reviewer skill on diff — not invoked
9.9 rv-docs-sync — not run
9.10 PR open — not done
9.11 openspec archive — not done
10.1-10.4 GitHub issues C2/C3 + Phase-0 doc update — not done
Honesty over completeness: marking a task as done that was not actually
done would re-create the same class of failure mode the D12 investigation
just closed (false-positive gates hiding real state).
-[ ] 9.4 Report the `complete=true` rate from the sweep. **Hard floor: 80%.** Comparator G4 enforces it automatically (`--complete-floor 0.80` default); failing run exits 1 with the per-APK outliers in `<out>/delta_report/{outliers,summary.{txt,json}}`. If below floor, open a `gator-regression` GitHub issue before merging anything downstream that consumes the sweep.
-[] 9.7 Run `openspec validate "gh60-targets-core"` — must pass structural validation
191
+
-[x] 9.7 Run `openspec validate "gh60-targets-core"` — must pass structural validation
192
192
-[ ] 9.8 Invoke `/rv-code-reviewer` via Skill tool on the diff vs `master`; address any high-confidence findings
193
193
-[ ] 9.9 Run `/rv-docs-sync rv-static-analysis` and `/rv-docs-sync rv-android-core` to update CLAUDE.md and architecture.md for the renamed components and new abstractions
194
194
-[ ] 9.10 Open PR; reference issue #60; ensure PR body includes: `Closes #60`, gates table with green status, sweep outliers (if any), and link to the Phase-0 ideation doc
@@ -231,34 +231,34 @@ After C1 merges, open placeholder issues in GitHub PAMunb/rvsec using `docs/2026
-[] 11.1 Extend `enrichFromElement` in `RvsecAnalysisClient.java` (lines 1080-1114) with two `putStringAttr` calls covering `android:hint` and `android:text`. Rationale: `putStringAttr` short-circuits on null/empty raw, so the path-A seed from `PropertyManager.getTextsOrTitlesOfView` / `getHintOfView` remains untouched when the layout XML carries no inline literal, while inline literals OR `@string/` refs in the layout override the seed. Idempotent against the gh57 attribute pass.
235
-
-[] 11.2 Extend `XmlInputTypeTest.java` (or create a sibling `XmlHintTextTest.java`) with 4 cases:
234
+
-[x] 11.1 Extend `enrichFromElement` in `RvsecAnalysisClient.java` (lines 1080-1114) with two `putStringAttr` calls covering `android:hint` and `android:text`. Rationale: `putStringAttr` short-circuits on null/empty raw, so the path-A seed from `PropertyManager.getTextsOrTitlesOfView` / `getHintOfView` remains untouched when the layout XML carries no inline literal, while inline literals OR `@string/` refs in the layout override the seed. Idempotent against the gh57 attribute pass.
235
+
-[x] 11.2 Extend `XmlInputTypeTest.java` (or create a sibling `XmlHintTextTest.java`) with 4 cases:
-[] 11.3 Build + deploy: `cd rvsec-gator && mvn -pl client -am install -DskipTests=true`. Verify `rv-android/lib/gator/rvsec-analysis-client.jar` mtime advanced (the `copy-resource-one` POM goal deploys into the gitignored `lib/gator/` location).
241
-
-[] 11.4 Run client unit suite (excluding ITs): `mvn -pl client test -Dtest='!*IT' -Dsurefire.failIfNoSpecifiedTests=false`. Baseline pre-fix is 134 PASS; post-fix expectation = 134 + new hint/text cases, all green. Record actual numbers.
242
-
-[] 11.5 Smoke validation on cryptoapp: prepare `/tmp/cryptoapp_smoke/cryptoapp.apk`, run `bash scripts/run_gh60_sweep.sh --apks-dir /tmp/cryptoapp_smoke --out ./out/gh60_postfix --smoke`. Then cross-check the resulting `out/gh60_postfix/br.unb.cic.cryptoapp/cryptoapp.apk.json`:
240
+
-[x] 11.3 Build + deploy: `cd rvsec-gator && mvn -pl client -am install -DskipTests=true`. Verify `rv-android/lib/gator/rvsec-analysis-client.jar` mtime advanced (the `copy-resource-one` POM goal deploys into the gitignored `lib/gator/` location).
241
+
-[x] 11.4 Run client unit suite (excluding ITs): `mvn -pl client test -Dtest='!*IT' -Dsurefire.failIfNoSpecifiedTests=false`. Baseline pre-fix is 134 PASS; post-fix expectation = 134 + new hint/text cases, all green. Record actual numbers.
242
+
-[x] 11.5 Smoke validation on cryptoapp: prepare `/tmp/cryptoapp_smoke/cryptoapp.apk`, run `bash scripts/run_gh60_sweep.sh --apks-dir /tmp/cryptoapp_smoke --out ./out/gh60_postfix --smoke`. Then cross-check the resulting `out/gh60_postfix/br.unb.cic.cryptoapp/cryptoapp.apk.json`:
243
243
- Count widgets with non-empty `hint` — MUST be ≥ 4 (source has 4 declarations across 3 layouts)
244
244
- Count widgets with non-empty `text` — MUST be ≥ 17 (source has 17 declarations across 4 layouts)
245
245
-`directlyReachesTarget` set MUST be the exact same 21-element set as pre-fix (D7 byte-equivalence invariant — fix MUST NOT perturb reachability)
246
246
- Sentinel `"complete": true` MUST be present (ADR-6)
247
-
-[] 11.6 ~~Baseline regeneration DEFERRED~~ — **SUPERSEDED 2026-05-26 by deeper investigation.** Initial hypothesis was "gh57→post-merge drift" but bisect with worktree at `b2e04a26` (pre-gh60) proved gh60 is byte-equivalent to its parent for reachability output: pre-gh60 build = post-gh60 build = (55, 32, 21) on the current rebuilt jar. The baseline showing 67/61 reflects pre-gh51 era (cha-default CG algorithm; content frozen at `4a8a6342 feat(gh45)` 2026-03-31). The `G_paridade_reachability` gate appeared to PASS because both sides of the comparison were stale (in-tree baseline + `/tmp/gh60_g_subset/lenient.json` cache, both from pre-gh51 cha-era). Regeneration is now in scope — see 11.8.
247
+
-[x] 11.6 ~~Baseline regeneration DEFERRED~~ — **SUPERSEDED 2026-05-26 by deeper investigation.** Initial hypothesis was "gh57→post-merge drift" but bisect with worktree at `b2e04a26` (pre-gh60) proved gh60 is byte-equivalent to its parent for reachability output: pre-gh60 build = post-gh60 build = (55, 32, 21) on the current rebuilt jar. The baseline showing 67/61 reflects pre-gh51 era (cha-default CG algorithm; content frozen at `4a8a6342 feat(gh45)` 2026-03-31). The `G_paridade_reachability` gate appeared to PASS because both sides of the comparison were stale (in-tree baseline + `/tmp/gh60_g_subset/lenient.json` cache, both from pre-gh51 cha-era). Regeneration is now in scope — see 11.8.
248
248
249
-
- [] 11.7 **Gate hardening — invalidate `LENIENT_OUTPUT` cache on jar change.** The 2026-05-26 investigation surfaced a critical hole in `tests/parity/test_reachability_parity.py` + `tests/parity/test_sentinel_emission.py` + `tests/parity/test_signature_file_subset.py` + `scripts/check_signature_file_subset.py`: they reuse `/tmp/gh60_g_subset/lenient.json` whenever it exists with `st_size > 0`, with **no invalidation against jar mtime**. A stale cache (e.g. from a `.m2` snapshot of sootandroid built pre-gh51 with cha-default) silently masks the actual current behavior — `G_paridade_reachability`/`G_paridade_targets` compared stale-cache × stale-baseline (both 67/61) and reported PASS, while a fresh build produces 55/32 (current spark-default era). Fix: each gate that consumes `LENIENT_OUTPUT` MUST delete the cache when `mtime(LENIENT_OUTPUT) < mtime(JAR_PATH)`, forcing regeneration. Pattern lives in a shared helper (`tests/parity/_lenient_cache.py::ensure_fresh_lenient`) so the four call sites do not drift.
249
+
- [x] 11.7 **Gate hardening — invalidate `LENIENT_OUTPUT` cache on jar change.** The 2026-05-26 investigation surfaced a critical hole in `tests/parity/test_reachability_parity.py` + `tests/parity/test_sentinel_emission.py` + `tests/parity/test_signature_file_subset.py` + `scripts/check_signature_file_subset.py`: they reuse `/tmp/gh60_g_subset/lenient.json` whenever it exists with `st_size > 0`, with **no invalidation against jar mtime**. A stale cache (e.g. from a `.m2` snapshot of sootandroid built pre-gh51 with cha-default) silently masks the actual current behavior — `G_paridade_reachability`/`G_paridade_targets` compared stale-cache × stale-baseline (both 67/61) and reported PASS, while a fresh build produces 55/32 (current spark-default era). Fix: each gate that consumes `LENIENT_OUTPUT` MUST delete the cache when `mtime(LENIENT_OUTPUT) < mtime(JAR_PATH)`, forcing regeneration. Pattern lives in a shared helper (`tests/parity/_lenient_cache.py::ensure_fresh_lenient`) so the four call sites do not drift.
250
250
251
-
-[] 11.8 **Regenerate `modules/rv-static-analysis/tests/resources/cryptoapp.apk.json`** with the current jar (post-hint/text fix + spark default + current schema: `components` + `complete` sentinel + `targetMethods` keys). Current baseline content dates from `4a8a6342 feat(gh45)` (2026-03-31) — 2 months stale, pre-gh51 cha→spark switch, pre-gh57 schema additions, pre-gh60 key rename. After regenerating, run `modules/rv-static-analysis/tests/parser/static/test_static_analysis_parser.py` (55 cases) + `tests/parity/test_reachability_parity.py` (4 cases) and update any assertion that relied on absent fields. Diff vs old baseline MUST be explainable as: (a) cha→spark precision improvement (67→55 reachable, 61→32 reachesTarget — intentional per gh51 D5); (b) gh57 schema additions (`components`, `complete`); (c) C1f key rename (`reachesMop→reachesTarget`). Any unexplained diff is a regression to investigate before committing.
251
+
-[x] 11.8 **Regenerate `modules/rv-static-analysis/tests/resources/cryptoapp.apk.json`** with the current jar (post-hint/text fix + spark default + current schema: `components` + `complete` sentinel + `targetMethods` keys). Current baseline content dates from `4a8a6342 feat(gh45)` (2026-03-31) — 2 months stale, pre-gh51 cha→spark switch, pre-gh57 schema additions, pre-gh60 key rename. After regenerating, run `modules/rv-static-analysis/tests/parser/static/test_static_analysis_parser.py` (55 cases) + `tests/parity/test_reachability_parity.py` (4 cases) and update any assertion that relied on absent fields. Diff vs old baseline MUST be explainable as: (a) cha→spark precision improvement (67→55 reachable, 61→32 reachesTarget — intentional per gh51 D5); (b) gh57 schema additions (`components`, `complete`); (c) C1f key rename (`reachesMop→reachesTarget`). Any unexplained diff is a regression to investigate before committing.
252
252
253
-
-[] 11.9 **Tripwire — `tests/parity/test_baseline_freshness.py`** with two cases pinning what the previous regime missed:
253
+
-[x] 11.9 **Tripwire — `tests/parity/test_baseline_freshness.py`** with two cases pinning what the previous regime missed:
254
254
-`test_baseline_has_current_schema`: baseline JSON MUST have `components` key + `complete: bool` + `targetMethods` key (not `mopMethods`). Catches a future revert that re-introduces stale schema.
255
255
-`test_baseline_not_older_than_jar`: when both `lib/gator/rvsec-analysis-client.jar` and the baseline exist, `mtime(baseline) >= mtime(jar)`. Catches jar-rebuild-without-baseline-refresh. SKIP when jar absent (CI without RVSEC_HOME); FAIL otherwise.
256
256
257
-
-[] 11.10 **Fail-loud when GATOR prerequisites missing.** Today the parity gates `pytest.skip` silently when `RVSEC_HOME` is not set or the jar is missing — the suite reports "passed" while exercising zero behavior. Add `RV_GATOR_REQUIRED=1` env-var contract: when set, gates that currently `pytest.skip` MUST `pytest.fail` instead. Pedro's local dev + future CI must export it; only explicitly-stripped environments skip. Sites to update: `tests/parity/test_reachability_parity.py::_ensure_fresh_lenient_output`, `tests/parity/test_sentinel_emission.py::_ensure_lenient_output`, `tests/parity/test_signature_file_subset.py`, `tests/parity/test_json_keys.py::java_keys`.
257
+
-[x] 11.10 **Fail-loud when GATOR prerequisites missing.** Today the parity gates `pytest.skip` silently when `RVSEC_HOME` is not set or the jar is missing — the suite reports "passed" while exercising zero behavior. Add `RV_GATOR_REQUIRED=1` env-var contract: when set, gates that currently `pytest.skip` MUST `pytest.fail` instead. Pedro's local dev + future CI must export it; only explicitly-stripped environments skip. Sites to update: `tests/parity/test_reachability_parity.py::_ensure_fresh_lenient_output`, `tests/parity/test_sentinel_emission.py::_ensure_lenient_output`, `tests/parity/test_signature_file_subset.py`, `tests/parity/test_json_keys.py::java_keys`.
258
258
259
-
-[] 11.11 **Cross-check against historical static-analysis** at `/home/pedro/desenvolvimento/RV_ANDROID/ALL_METHODS/cryptoapp.apk.methods` (pre-rv-android-uv-workspace era, separate tooling). Compare method-name sets and reachability semantics against the regenerated baseline (11.8). The historical file predates the GATOR unification (gh27) so the comparison is set-equality on `(className, methodName)` not byte-equivalence; if the historical file shows methods the current pipeline misses, register as a separate finding for C2 hardening (NOT fixed here). Goal: independent evidence that the regenerated baseline isn't missing structural app coverage.
259
+
-[x] 11.11 **Cross-check against historical static-analysis** at `/home/pedro/desenvolvimento/RV_ANDROID/ALL_METHODS/cryptoapp.apk.methods` (pre-rv-android-uv-workspace era, separate tooling). Compare method-name sets and reachability semantics against the regenerated baseline (11.8). The historical file predates the GATOR unification (gh27) so the comparison is set-equality on `(className, methodName)` not byte-equivalence; if the historical file shows methods the current pipeline misses, register as a separate finding for C2 hardening (NOT fixed here). Goal: independent evidence that the regenerated baseline isn't missing structural app coverage.
260
260
261
-
-[] 11.12 Commits (3 atomic):
261
+
-[x] 11.12 Commits (3 atomic):
262
262
-`fix(gh60): enrichFromXml cover hint+text literal attributes (refs #60)` for 11.1-11.5
263
263
-`test(gh60): harden reachability parity gates against stale cache (refs #60)` for 11.7 + 11.9 + 11.10
264
264
-`test(gh60): regenerate cryptoapp baseline + cross-check vs ALL_METHODS (refs #60)` for 11.8 + 11.11
0 commit comments