RFC: Android Kotlin → Rust/Gossamer migration#97
Conversation
Draft RFC for owner review before any bulk conversion. Maps each of the 7 Kotlin files + 3 *.gradle.kts to a Rust/Tauri replacement, calls out the unavoidable JVM-bytecode surface (Service / BroadcastReceiver / AppWidgetProvider), and proposes a 9-PR landing sequence gated on CI-exemption coordination for Tauri-generated Java shims under src-tauri/gen/android/. No Kotlin deleted, no Tauri scaffolding generated — pure planning artefact. Both banned-language CI gates remain red until the sequenced sub-PRs land in order. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Owner correction: estate target is Gossamer (Hyperpolymath's Zig+Ephapax+ webview framework), not Tauri. Rewrites the RFC accordingly: - Component mapping now references GossamerActivity / GossamerBridge from hyperpolymath/gossamer (MPL-2.0), not Tauri 2. - Sub-PR sequence rewritten: gossamer-rs crate + gossamer.conf.json scaffolding (panll precedent at src-gossamer/) rather than `cargo tauri android init`. - New "Upstream-vs-downstream scope" section. Gossamer Phase 3 (Mobile) is webview-only upstream; foreground service, AppWidgetProvider, BroadcastReceiver, SensorManager integration have no Gossamer support today and no open Gossamer issues. RFC recommends building all seven downstream in neurophone's android/ tree as application-specific Java shims, not blocking on Gossamer upstream PRs. - SPDX clash section removed; everything is MPL-2.0 per owner. - Gradle DSL question added (Groovy *.gradle vs Kotlin *.gradle.kts). Still draft, still no Kotlin deleted. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Maps every external fun in NativeLib.kt to (a) the Rust JNI export we'll write in crates/neurophone-android/src/lib.rs and (b) the underlying neurophone-core API it composes. Surfaces 5 gaps: 1. No start/stop/is_running lifecycle on NeuroSymbolicSystem → keep as JNI-layer concept (bool in static state holder). 2. Sensor-type int→string mapping currently in Kotlin → move into Rust JNI layer as const lookup. 3. query() uses heuristic prefer_local; Kotlin queryLocal/queryClaude expect hard routing → introduce QueryRoute enum on core. 4. No get_neural_context() on core → add method composing from get_state(). 5. No reset() on core → JNI layer replaces held instance. Estimated sub-PR #4 size: ~250 LoC new Rust + ~10 LoC core change + JNI roundtrip tests. Shovel-ready when sub-PRs #2 (CI exemption) + #3 (Gossamer scaffolding) land. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Added Maps all 11
Estimated sub-PR #4 size: ~250 LoC new Rust + ~10 LoC core change. Shovel-ready when sub-PRs #2 + #3 land. |
…igration in flight) (#105) ## Summary The `android/` subtree is owner-authored Kotlin/Gradle work-in-flight currently being migrated to Gossamer (see RFC PR #97). It is not vendored upstream — it is intentional code. Two complementary governance checks currently treat it as a banned-language violation: - `Check for Banned Languages` (this repo's `.github/workflows/language-policy.yml` — self-contained `find -name '*.kt' ...`) - `governance / Language / package anti-pattern policy` (the standards reusable's `Check banned-language files` step — honours `.hypatia-ignore` + `.hypatia-baseline.json`) This PR adds a coordinated carve-out for both. After it lands on `main`, the recently-merged PR #101 (ESN spectral-radius scaling — obligation 1.1) inherits the carve-out for any follow-up CI runs, and future Android-touching PRs go green by default until the Gossamer migration lands and `android/` is removed. ## Changes **Commit 1 — `chore(cicd): add android/** carve-out to .hypatia-ignore`** Adds two complementary exemption files at the repo root: - `.hypatia-baseline.json` — canonical glob form (`file_pattern: "android/**"`) with `tracking_issue: "#97"`. Consumed by the standards governance-reusable workflow's `in_baseline()` helper (glob → regex translation: `**` → `.*`). - `.hypatia-ignore` — legacy per-file enumeration (10 lines, one per currently-tracked `.kt`/`.kts` file). Belt-and-braces for any tool that only reads the flat-file form (the governance reusable's `is_exempt()` checks both; `grep -qxF` requires literal lines, not globs). **Commit 2 — `ci(language-policy): exclude android/ from Java/Kotlin banned-language scan (Gossamer migration in flight — RFC #97)`** Edits the `Check for Java/Kotlin files` step in `.github/workflows/language-policy.yml`. The inline workflow does not read `.hypatia-ignore`, so it needs its own path exclusion. Replaces the single-line `find -name '*.kt' ...` with a `-prune` + `-o` form that excludes `./android/` and `./.git/`: ```bash VIOLATIONS=$(find . \ \( -path './android' -o -path './android/*' -o -path './.git/*' \) -prune -o \ \( -name "*.java" -o -name "*.kt" -o -name "*.kts" \) -type f -print) ``` ## Verification Local verification before push: - New `find` pattern returns empty on the current tree. - Old `find` would have caught 10 files under `android/`. - `git ls-files '*.kt' '*.kts' '*.java' | grep -v '^android/'` returns empty — no non-Android Kotlin/Java anywhere, so the carve-out is precise. ## Rollback condition Once the Gossamer migration (RFC PR #97) lands and `android/` is removed from the repo, all three additions (`.hypatia-baseline.json`, `.hypatia-ignore`, and the `find -prune` clause in `language-policy.yml`) should be removed together. ## Related - RFC PR #97 — Android Kotlin → Rust/Gossamer migration (the work that makes this carve-out time-bounded). - PR #101 — ESN spectral-radius scaling (already MERGED; the two governance checks were the last red on it).
|
Sub-PR #2 opened as #107 (draft). Path 2B per the RFC: deletes the local Java/Kotlin check, relies on the estate-wide reusable. Companion to hyperpolymath/standards#341 which adds the Merge order: standards#341 first → neurophone auto-consumes via After both merge, sub-PR #3 (Gossamer scaffolding) becomes unblocked. |
Q1: estate-wide CI exemption (standards#341).
Q2: self-answered.
Q3: drop widget-configure activity.
Q4: Groovy *.gradle.
Q5: emulator+Termux for dev, Oppo Reno 13 for final close-out.
Q6: contribute upstream — `gossamer-android-services` companion in
hyperpolymath/gossamer with four shim base classes (Service,
BroadcastReceiver, AppWidgetProvider, Activity-with-bridge).
Q6 changes the sub-PR sequence: a new #2b — Gossamer companion PR —
blocks the original #3 (neurophone Gossamer scaffolding). Revised
9-step sequence captured in the new "Sequencing implications of Q6"
section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Q6 unblocker filed upstream: hyperpolymath/gossamer#71 — design + planning issue for the The issue contains the full API sketch (Java + Zig), motivating neurophone use case, native-side surface, sequencing, and 4 owner sign-off asks. Per the revised RFC sequence, neurophone sub-PR #3 (Gossamer scaffolding) is gated on the Gossamer companion landing. No neurophone work can proceed past sub-PR #2 (already in #117) until gossamer#71 lands. This completes the in-session planning ladder. Three-system propagation infrastructure also in flight (.git-private-farm#66 + hypatia#418 + gitbot-fleet#248 + .git-private-farm#67) but those are orthogonal. |
…117) ## Why PR #105 added the android/** carve-out via **two** mechanisms: - (a) Prune `android/` from a local `find` step in `.github/workflows/language-policy.yml` - (b) Add `.hypatia-baseline.json` with `file_pattern: "android/**"` The estate-wide reusable at `hyperpolymath/standards/.github/workflows/governance-reusable.yml` (called from this repo's `governance.yml`) **already** reads `.hypatia-baseline.json` and exempts matched paths in its own `language-policy` job (see `governance-reusable.yml:91-285`). **(b) alone is sufficient.** (a) is a duplicate that uses the brittle `find` mechanism the reusable explicitly warns against — `git ls-files` respects `.gitignore` correctly. ## What this PR does Removes the local `Check for Java/Kotlin files` step. The neurophone `.hypatia-baseline.json` carve-out continues to handle the android/** exemption via the estate-wide reusable. ## Net behaviour change **Zero.** The local check duplicated the estate check. Both gate on Java/Kotlin files; both exempt android/** via different mechanisms. Removing the local check means there's one mechanism instead of two, and the remaining mechanism is the auditable baseline file. ## Properties preserved - Kotlin (`.kt`, `.kts`) is still fully banned — by the estate-wide reusable's `enforce "Java/Kotlin files"` block. - Non-Android Java (e.g. a stray `Foo.java` at repo root) is still blocked — same path. - The `android/**` carve-out is still respected via `.hypatia-baseline.json`. ## Stale-entry cleanup at end of migration When the Gossamer migration completes and `android/` is removed, the baseline entry will become stale. The reusable's `Detect stale baseline entries` job (`governance-reusable.yml:127+`) will warn. The entry can be removed in the same PR that deletes `android/` (i.e. sub-PR #9 of the migration sequence in RFC PR #97). ## Supersedes - `hyperpolymath/standards#341` (closed) — estate-wide grep change was redundant given the baseline mechanism already exists. - `#107` (closed) — same intent as this PR but pre-#105; rebase would have been a different change. ## Test plan - [x] Workflow YAML is well-formed (visually verified). - [ ] CI passes — local language-policy.yml runs without the Java/Kotlin step; estate-wide reusable runs and exempts android/** via baseline. - [ ] Negative test: a hypothetical `Foo.java` at repo root would still trigger the estate-wide `Language / package anti-pattern policy` job (verified by inspection of `governance-reusable.yml:345` + `enforce()` at line 310 + `is_exempt()` at line 292). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Status
DRAFT — RFC only. Awaiting owner review BEFORE any bulk conversion.
No Kotlin deleted, no Gossamer scaffolding generated, no behaviour change.
Supersedes #96 (was titled "Tauri 2" — owner correction: Gossamer is the
estate target).
Why
android/ships 7 Kotlin files + 3*.gradle.ktsfiles, all banned by theHyperpolymath language policy. Two CI gates permanently red:
Check for Banned Languages(.github/workflows/language-policy.yml:87-94)governance / Language / package anti-pattern policy(estate-wide)What this PR contains
A single document —
docs/migrations/RFC-ANDROID-KOTLIN-TO-RUST.adoc—mapping every Kotlin component to its Gossamer replacement and proposing
a 9-PR landing sequence.
Component mapping (one-line summary)
MainActivity.ktNeurophoneMainActivity extends GossamerActivityNeurophoneService.ktServiceshim → JNI into RustBootReceiver.ktBroadcastReceivershim → JNINativeLib.ktcrates/neurophone-android/src/lib.rsNeurophoneAppWidget.ktAppWidgetProvidershimNeurophoneWidgetActions.ktBroadcastReceivershimNeurophoneWidgetConfigureActivity.ktActivityshim (or drop)*.gradle.kts*.gradle(matches Gossamer upstream)Key structural finding
Gossamer Android is webview-only today. ROADMAP Phase 3 (Mobile)
lists Android as Partially Implemented — only
GossamerActivity+GossamerBridgeexist upstream. The 7 platform-integration surfacesneurophone needs (service, widget, receivers, sensors, intent dispatch,
prefs, deep-links) have no upstream Gossamer support and no open
Gossamer issues.
Recommendation: build all 7 downstream in neurophone's own
android/tree as small Java shims that JNI immediately into Rust. Don't block
neurophone on Gossamer upstream PRs. Estimated total shim surface: < 250
LoC of Java vs. current 926 LoC of Kotlin.
Estate precedent
panllmigratedsrc-tauri/→src-gossamer/(commit598d537,ADR-0001 in
b935727). Webview UI unchanged; swappedtauricratefor
gossamer-rs,tauri.conf.jsonforgossamer.conf.json,cargo tauri buildfordeno task buildinvoking thegossamerCLI.service or home-screen widget surfaces; neurophone will be the first.
Sub-PR sequence (proposed)
android/**/*.java(coordinated withhyperpolymath/standards).gossamer-rsworkspace dep,gossamer.conf.json,NeurophoneMainActivityJava shim loading placeholder HTML.NativeLibKotlin →crates/neurophone-android/src/lib.rs.NeurophoneService→ Java shim + Rust impl.BootReceiver.android/tree — both CI gates green.PRs 2 & 3 sequenced; 4–7 parallelizable after 3; 8 needs 4; 9 gated on all.
Open questions for owner
hyperpolymath/standardsor neurophone-local? Linchpin question.
callable in standards?
*.gradle(matches Gossamer upstream) orkeep Kotlin
*.gradle.ktsunder a separate exemption?a
gossamer-android-servicescompanion as we go?Constraints honoured
Test plan
🤖 Generated with Claude Code