V2 - #1
Merged
Merged
Conversation
- Added full plugin packaging capabilities, including Java/Kotlin source compilation and dependency resolution. - Introduced multi-dex handling with support for multiple DEX files in APKs. - Updated version to 0.1.6 and modified build command to package all plugins by default. - Enhanced dependency cache to handle AndroidX multiplatform artifacts and improved error handling. - Added tests for multi-dex packaging and dependency resolution.
Opt-in resolution pass for the dry-run: composes the plugin dependency plan from declared inputs (gradle-parsed + conditionally deduplicated roots, pipeline.extra_deps, flutter-embedding set) and resolves it through the same DependencyCache the build uses. - extract PluginPackager.collectDeclaredDeps so packaging and the plan share one collector (no parser drift) - MavenResolver.resolveWithTransitives gains onFailure: per-artifact failure isolation stays, but failures become observable (were verbose-only) - cache-only by default (offline-safe; misses are non-fatal warnings); --network opts into full resolution where hard failures exit 1 - typed DependencyPlanReport (entries/resolved/findings), no new YAML keys - ADR-0008 + docs (index, build guide Q&A, hardening roadmap, checklist) - tests: test/dependency_plan_test.dart (8) over mobile_scanner fixture
- docs/PHASE_CHECKLIST.md now lists only items to address: cargo-apk hybrid removal (ADR-0009, proposed) + multi-dex determinism, with follow-ups - completed ADR-0006/0007/0008 phases with evidence archived under docs/archive/PHASE_CHECKLIST_adr0006-0008.md (sidebar path unchanged) - ADR-0009 (proposed): full rust/cargo inventory — zero production usage, quarantine test fails every CI run — and complete removal plan, awaiting sign-off
Completes ADR-0001's demotion: the no-Gradle pipeline is the only build path. Removed: - rust_wrapper/ (NativeActivity experiment, unused by every build path) - test/cargo_apk_manifest_test.dart (the known-failing quarantine test — dart test is now fully green, no baseline caveat, CI stops failing) - CargoApkManifest + barrel export (zero production callers) - CargoApkConfig + OkaConfig.cargoApk getter + barrel export (zero callers) - FlutterAndroidBuilder compatibility wrapper (only refused the cargo path) - example/oka.yaml dead cargo_apk section; stale cargo comments/docs Docs: ADR-0009 accepted+executed, ADR-0001 annotated, design FAQ / why_this_repo_matters / contribution guide / AGENTS.md updated (the rust_wrapper non-negotiable is moot). Evidence: dart test 178/178 green; grep cargo over bin/lib/packages/lib/test clean (RuStore vendor routing unrelated); example oka explain unchanged. BREAKING CHANGE: CargoApkConfig/CargoApkManifest removed from oka_core and oka_android public barrels; oka.yaml cargo_apk key is no longer read.
Research: oka.yaml base config (android:/flutter:) can move into the project Dart pipeline because every config consumer reads ctx.config — an OkaConfig extension type over a map — so typed values materializing that map plug in with zero step-layer changes. Missing pieces: writable AndroidBuild/ FlutterBuild values, precedence merge in okaRun, hook discovery without oka.yaml (convention, no new YAML key), oka init --from-yaml migration tool. Staged: oka_core values -> example app -> last_answer -> doctor/init.
All stages executed: Stage 1 (oka_core): AndroidBuild + FlutterBuild — const-constructible, copyWith, toConfigMap() materializing the exact oka.yaml-shaped map. New PlatformPipeline.configOverrides seam: okaRun deep-merges typed config over oka.yaml over defaults; steps keep reading ctx.config (zero step-layer changes). --print-config on okaRun emits the merged config as JSON. Stage 2 (example app): full-Dart migration — config/flutterConfig/overrides in example/tool/oka_pipeline.dart (renamed from bin/custom_pipeline.dart, now also the discovery target), oka.yaml deleted. Byte-equivalence gate: same-hook A/B (yaml-config vs AndroidBuild) → badging, AndroidManifest.xml, resources.arsc, classes.dex all identical; residual diffs are only the example's timestamped build_info.txt stamp (custom step) + signature cascade. Stage 3: oka init --from-yaml converts oka.yaml 1:1 into the typed entrypoint (last_answer migration path); oka init --dart scaffolds full-Dart. Stage 4: entrypoint discovery (explicit dart_entrypoint → tool/oka_pipeline.dart → bin/oka_pipeline.dart) wired into build/explain/doctor; oka debug step materializes full-Dart config via the hook's --print-config. ADR fix: the parallel hot-reload ADR collided on number 0010 → renumbered to 0011 (file, plan, checklist, index, AGENTS, charter references). Docs: ADR-0010 accepted + executed; build guide gains a Full-Dart config Q&A (field mapping, precedence, migration); checklist/README/AGENTS updated. Evidence: dart test 189/189 green; dart analyze 0 errors; check-contracts green; example explain/doctor/debug-step verified live. BREAKING CHANGE: none for API consumers — additive (AndroidBuild/FlutterBuild, configOverrides). example/oka.yaml removed (hook is the config); yaml projects unaffected.
…0010) last_answer (first production app, 18 plugins) is now full-Dart config: tool/oka_pipeline.dart generated via oka init --from-yaml, oka.yaml deleted. Gate: yaml-config vs Dart-config debug builds are byte-equivalent (badging + zip entries identical); explain/doctor/debug-step verified without oka.yaml. Adoption surfaced three real gaps, all fixed behavior-preserving: 1. archive ^3.4.10 -> ^4.0.9: host apps depending on image ^4.5 (e.g. flutter_native_splash) couldn't resolve oka_android. API migration: ZipEncoder().encode -> encodeBytes, compress -> CompressionType (resources.arsc stays STORED — install -124 invariant kept), encode no longer nullable. 2. Explicit steps: lists dropped fast-settings (pre-existing ADR-0006 gap): AndroidPipeline.run now seeds the merged PipelineOverrides into PipelineState (runtime scope) and steps fall back to it when their constructor values are unset — exclude_plugins, extra_deps, manifest, icon, res_dirs, signing, resource_configs, extra_assets, local_aars, max_size_mb. _ExtraDepsStep/_LocalAarsStep are public ExtraDepsStep/ LocalAarsStep; defaultSteps gains extra-deps/local-aars/extra-assets/ post-build-lint so hooks using [...defaultSteps] get the full surface. 3. flutter assemble subprocesses now receive the located ANDROID_SDK_ROOT/ ANDROID_HOME — projects with a stale android/local.properties (like last_answer's dead sdk.dir) no longer fail the build_hooks target. Docs: checklist evidence updated; AndroidPipeline.run merge also threads res_dirs/exclude_plugins/max_size_mb. Tests: 191/191 green (13 ADR-0010 incl. overrides-seeding + ExtraAssetsStep fallback); analyze clean; check-contracts green.
… publish readiness oka init (ADR-0010): - default flow scaffolds tool/oka_pipeline.dart (typed config derived from pubspec name/version) — no oka.yaml; discovery needs no YAML key - --yaml opts into the legacy YAML-first flow (AI gradle conversion kept) - --from-yaml unchanged; overwrite prompts are TTY-gated (non-interactive sessions cancel gracefully; --force forces) Multi-dex determinism (ADR-0007 open item, closed): - d8 program/lib jar lists sorted: parallel dependency resolution made argument order vary, and d8 partitions classesN.dex in argument order, so part count + content distribution were non-reproducible - zipStagingToApk / zipBundle write entries in sorted path order instead of filesystem order — APK/AAB bytes are now reproducible - test/determinism_test.dart: byte-identical APK/AAB across runs and directory orders; real-d8 reproducibility when an SDK is present OSS publish readiness (ADR-0006 package split): - oka_core/oka_android: LICENSE, README, CHANGELOG; oka_android declares hosted oka_core ^0.1.6 (path deps block publishing); root resolves siblings via dependency_overrides for local development - pub_publish workflow: per-package dry-run preflight + publish train oka_core -> oka_android -> oka; check_version_sync extended to the split packages - host bootstrap (pre-first-release dependency_overrides) documented in the build guide; design FAQ gains the determinism rationale Evidence: dart test 195/195 green; analyze 0 errors; check-contracts green; publish dry-run — oka_core/oka publishable, oka_android resolves once oka_core's first release is up.
…roid first - README: leads with the north star (typed, composable, agent-operable platform builds), Android-first status with production evidence, the agent surface table (explain/compare/debug step/doctor/dev), packages table, and 'The long game' — criteria-gated platform expansion (depth before breadth, abstraction hygiene, iOS as second-platform candidate, stay in the Flutter+agent-native+no-Gradle wedge) - charter (why_this_repo_matters): the three design words (declarative/ compositional/AI-native) as design law, 'What oka does not own' updated (iOS/desktop criteria-gated, not forever-never), expansion criteria section - design FAQ: what carries over to future platforms - AGENTS.md: north-star one-liner No code changes; all gates green (195 tests, analyze clean, contracts).
Oka was created not because Gradle is slow but because platform build configs are locked, scattered across a dozen untyped formats, endlessly repeated per project, and impossible to unify or copy. The reframe: - README 'Why oka was created': the config chaos is the disease; one typed, composable, copyable Dart surface is the cure; speed (~23s incremental, no daemon) is a consequence, not the pitch - charter: 'The problem oka was created for' rewritten (lock-in + unmanageability + repetition across projects); success metrics now lead with 'one copyable Dart file' instead of raw speed; future generations named as pushing more per-platform noise into the single Dart surface - AGENTS.md one-liner updated to match No code changes; all gates green.
…enchmarks - steward.yaml (adopted via steward adopt --archetype cli_tool, aligned with the mcp_flutter pattern): governance charter AGENTS.md, adr_dir docs/decisions, validate make check-contracts, registry skills.sh.json, evidence .steward/benchmark-summaries - four typed contract actions wrapping the release gates (version-sync, docs-drift, changelog-markdown, no-personal-paths) + contract smoke scenario oka.contract-status-smoke with safe-first probe - tool/benchmarks/build_benchmarks.sh + make bench: wall-clock benchmarks for the agent-loop primitives (explain / incremental build / compare / debug step) with environment metadata, summaries in .steward/benchmark-summaries (gitignored, machine-local) - skills.json lists the installable oka-maintenance skill steward doctor: config valid; benchmark durability requires committed contract artifacts, hence this commit precedes the first recorded run.
… phase items Secrets: dart-define/fromEnvironment/define-from-file stay first-class for app-visible non-secrets; credential contents are build-host files referenced by PATH (asset pattern), resolved via an ordered doctor-printable policy (config path -> OKA_<TARGET>_* env -> ~/.oka/credentials); doctor secret audit + gitignore gate; PublishTarget conformance laws (dry-run without credentials, no stdin, no secret values in state). refactor: CLI platform-leakage ratchet emptied (ADR-0015 follow-up) get/compare/doctor/build are parse-and-delegate shims; SDK install mechanics -> oka_android provisioning.dart, doctor checks -> doctor_checks.dart, aapt2 resolution absorbed into compareArtifacts. Allowlist deleted except one documented flag-name exception (--skip-badging). Outputs byte-identical. 338 tests passing, analyze clean, contract gates green.
… audit (P0) ADR-0014 P0: PublishTarget with dry-run conformance law, CredentialRef (redacting) + ordered credential-path policy (config path -> OKA_<TARGET>_* env -> ~/.oka/credentials), dart-define secret audit, credential-file gitignore check, expectPublishConformance helper. Doctor outputs via parse-and-delegate; leakage gate respected. Evidence: test counts + doctor audit + dry-run plan in PHASE_CHECKLIST.
…idation (P2) ADR-0014 P1: packages/oka_conformance (shared publish-target conformance suite: dry-run-without-credentials, no-stdin, no-secret-values-in-state); packages/oka_play (PlayPublishTarget, androidpublisher/v3 Edits flow over injectable transport, JWT->OAuth via googleapis_auth, offline-tested). ADR-0014 P2: packages/oka_huawei (HuaweiPublishTarget, AGC REST flow offline- tested, redaction on dumps/errors); GMS-exclusion variant via new oka_android seam (gms-dep artifacts) — validator catches GMS-dependent steps in excluded compositions before any tool runs. CLI untouched (targets project-declared per ADR-0015). Tests: root 390 + oka_play 27 + oka_conformance 11 + oka_huawei 31 — all green, analyze clean, contract gates green.
…yer e2e (ADR-0011) H0: debug APK hot-reload audit — kernel_blob.bin/static assertions + live emulator probe (VM service reachable, attach --machine reaches app.started; parser handles both 'is listening'/'is available' spellings). Decision recorded: H3 uses attach --machine (Gradle-free). H1: run_session.json (schema 1) recorded at build time; oka dev validates and refuses mismatch (dart_defines, engine drift); flutter binary resolved from recorded SDK path, never ambient PATH. H2: 25 command-construction/parser/failure tests over scripted-fake adb; live e2e on a provisioned API 34 emulator (oka run device -> install/ launch/logscan -> VM probe OK). System image fetched via parallel curl (sdkmanager pathologically slow); one-time human commands recorded. Evidence in PHASE_CHECKLIST + hot_reload_plan.md.
…art, doctor (ADR-0011) H3: flutter attach --machine daemon adapter (protocol corrected by live probe: both reload and restart are app.restart with fullRestart; app.reload does not exist in flutter_tools 3.47) — human TTY loop + --json agent stream; one session per device; attach child gets recorded-SDK tools on PATH. Live e2e on h0test AVD: session.ready -> reload ~130ms -> restart ~625ms -> detach clean. H4: --watch change classification (Dart -> reload; native/res/manifest -> honest rebuild routing, reload never suggested) + --rebuild-on-native loop; 17 table/debounce/routing tests. H5: doctor [Dev Loop] readiness section; docs updated with the three-flow story: oka run device (one-shot) / oka launch (alias) / oka dev (session). Also (publish-gaps agent): okaRun prints publish plans on dry-run dispatch (ADR-0014 law); AAB fallback path fixed in oka_play/oka_huawei to the real oka output layout with typed override. 456 tests green, analyze clean, contract gates passed.
…sts) Physical-device testing surfaced that -d/--device was silently dropped and every device step ran bare adb (works on single-device hosts only; 'more than one device' errors with two attached): - adb arg builders + AdbTool gain serial (-s), threaded through install/launch/logcat/forward/VM-service operations - DeviceTarget gains typed deviceId; steps carry it - Target contract gains supportedInvocationArgs/applyInvocationArgs — typed invocation-time overrides via --oka-target-arg key=value; okaRun parses -d/--device + --oka-target-arg in target dispatch - oka launch -d now FORWARDS instead of dropping; bare --device is a usage error; unknown invocation args rejected naming accepted keys - launch alias fixture/models updated; serial + contract tests 522 tests passing, analyze clean.
…R-0011 follow-ups) 1. oka dev now writes the forwarded VM-service endpoint to .oka_cache/dev/vm.uri (one line, written on session.ready, cleared on exit) so verification/inspection tools (flutter_mcp_cli, agents) attach without scraping the --json stream. 2. Hot-restart relaunch fallback: on physical devices attach-mode app.restart(fullRestart) can stop the app instead of restarting it (flutter_tools lacks relaunch data when attached). The session races the restart against app.stop; on a mid-restart stop it hands back to DevFlow with DevSessionOutcome.relaunchRequested — relaunch + re-attach, no rebuild. Scripted-fake test with a silent app.restart reproduces the device failure mode end-to-end. 524 tests passing, analyze clean.
…-0013/0015) oka run emulator: typed target (avdName/apiLevel/abi/headless/createIfMissing, invocation-arg device=<serial>) compiling to ensure-avd + boot-emulator steps; idempotent reuse of a running instance; boot-wait via sys.boot_completed; provides the emulator-serial artifact for multi-device downstream steps; StopEmulatorStep for teardown targets. Fail-closed non-interactive provisioning remediation (yes | sdkmanager --licenses; sdkmanager <image>). Found by the live smoke test: ensure-avd initially passed the emulator's -list-avds flag to avdmanager — existence check always missed (spurious --force re-create). Fixed with avdmanager list avd + Name: parsing. 16 tests (argv builders, scripted-fake boot/idempotence/remediation, invocation args); example composition updated. 556 tests passing, gates green.
…egation; emulator target landed
…cements; control-port default Newer Flutter announces only 'The Dart VM service is listening on http://host:port/TOKEN/' — no ws:// line. The H2 scrape stored that URI without the /ws path, so downstream ws clients (flutter_mcp_cli) got connection failures. VmServiceInfo.wsUri and forwardedVmServiceUri now normalize to the ws endpoint (token path + /ws). Also: oka dev --control-port defaults to ephemeral (0); control-server lint cleanups. Integration smoke verified delegated reload through flutter_mcp_cli (delegated:true, runner:oka-dev-session).
…er-session.json) Dependency inversion: the toolkit defines the generic 'dev session' contract; oka is a conforming runner (writes the file, never embedded in the toolkit). Runner file moves from .oka_cache/dev/session.json to <project>/.flutter_mcp/runner-session.json with the optional 'runner' display field; .oka_cache/dev/vm.uri stays internal. Wire protocol unchanged. 557 tests, gates green. Integration smoke: delegated reload with runner:oka-dev from the file, oracle PASS.
|
To preview the documentation for this pull request, visit the following URL:
|
…tic test key, zero analyzer infos - dart pub get --no-example in CI: dart >= 3.13 resolves example/ by default; example is a Flutter app and cannot resolve without the Flutter SDK (flutter_test is sdk-sourced). The root suite skips gracefully without Flutter/Android SDKs. - dart publish → dart pub publish in the validate job (dart publish is not a command). - false_secrets: pub's leak detector flags the SYNTHETIC Play test key fixture in packages/oka_play/test/synthetic_credentials.dart when the root archive (which includes workspace members) is validated. - dart fix + manual cleanup: zero analyzer issues so --fatal-infos holds (unnecessary_async kept future-error semantics via Future<Never>.error).
… not a package Why: pub now fails validation for any archive containing a top-level docs/ directory (plural-name convention error), and the root package archive necessarily included docs/ (plus workspace members). The docs/ directory stays — it is the docs.page source — so the published CLI moves instead, mirroring the mcp_flutter layout (workspace root with publish_to: none + published packages). - packages/oka: bin/, lib/, CHANGELOG.md, LICENSE, pubspec (name: oka, executables: oka). The pub.dev 'oka' package continues unchanged. - Root pubspec: name oka_workspace, publish_to: none; cross-package ADR conformance tests stay at the root and depend on workspace members. - false_secrets moved into packages/oka_play (the synthetic key fixture is only in its own archive now). - CI: root suite + every member package suite; publish dry-runs loop over publishable members; pub_publish.yml publishes packages/oka and uses 'dart pub publish' (dart publish is not a command). - Version sync/changelog contracts + release-please config track packages/oka. - install.sh: curl | bash installer (dart pub global activate; --from-git for main @ HEAD); README quickstart shows both paths. - Test harness paths updated (packages/oka/bin/oka.dart, lib/src/cli).
… are absent (CI without Android SDK)
The step resolves adb + emulator from PATH/toolchain before the injected
scripted runner matters, so the 4 emulator-lifecycle tests failed on CI
('adb/emulator not found' instead of the scripted behavior). Applies the
determinism_test skip-guard pattern.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.