CodeVetter · Repo Unpack · Contributor handoff
flutter/flutter
This repo punishes agents that skip the bootstrap layer: the CLI only works from a real git clone with git on PATH, and editing flutter_tools' pubspec triggers a full snapshot rebuild on next run. Shell logic is duplicated between .sh and .bat files and must be kept in sync. The DI layer (context.get/globals + overrides) is the sanctioned way to reach services — do not construct singletons directly. Most engine-facing changes need a local engine build via --local-engine flags. Tests run through dev/bots/test.dart with SHARD/SUBSHARD, and the authoritative CI config is .ci.yaml, not .github/workflows.
- Read first (tool work): bin/internal/shared.sh (bootstrap+locking), packages/flutter_tools/lib/executable.dart (command table + overrides), lib/runner.dart (error/exit semantics), lib/src/runner/flutter_command.dart + flutter_command_runner.dart (arg plumbing), lib/src/base/context.dart + globals.dart (DI).
- The tool hard-fails if $FLUTTER_ROOT/.git is missing or git is not on PATH — packaged archives rely on a different code path, so test changes against a real clone.
- Editing packages/flutter_tools/pubspec.yaml invalidates the tool snapshot (mtime check) — the next `flutter` invocation rebuilds it; commit pubspec.lock consistently or users hit unexpected rebuilds.
- Keep paired scripts in sync by convention: bin/flutter <-> flutter.bat, shared.sh <-> shared.bat, update_dart_sdk.sh <-> .ps1, update_engine_version.sh <-> .ps1 — headers explicitly demand parity.
- Files under packages/flutter_tools/lib/src/isolated are excluded from google3; anything depending on dwds/devtools sources must stay there or be injected via the overrides map — moving imports out silently breaks internal builds.
- Run tests the repo's way: `dart dev/bots/test.dart` with SHARD=/SUBSHARD= (e.g. SHARD=tool_tests SUBSHARD=general), or `flutter test` inside a package dir; pass --local-engine=host_debug_unopt when validating against a locally built engine.
- Framework edits: source in packages/flutter/lib/src/<area> mirrors tests in packages/flutter/test/<area>; golden-image changes flow through packages/flutter_goldens and Skia Gold — expect golden tests to fail until images are triaged.
- Engine edits live in engine/src/flutter (GN/Ninja, not pub): unit tests are *_unittests.cc beside sources; DEPS holds pinned dep revisions that should be rolled with the documented tooling rather than hand-edited.
- Lint/style: every Dart file starts with the BSD license header; root analysis_options.yaml/analysis_options_common.yaml enforce strict lints; dev/bots/analyze.dart plus cross-import checkers run in CI — run them before pushing.
- CI truth source is .ci.yaml + dev/bots/test.dart shards; .github/workflows only runs auxiliary PR checks — adding a CI target means editing .ci.yaml (and likely registering a suite runner), not a GitHub workflow.
- Error paths are contractual: throw ToolExit/throwToolExit for user-facing failures (maps to exit codes), UsageException gives exit 64 — never call exit() directly from command code because shutdown hooks and crash reporting are bypassed.
- Common trap: 'files scanned' inventories miss most of this repo — the file walk capped at 4000 of a much larger tree; rely on grep/glob inside packages/flutter_tools/lib/src and engine/src/flutter rather than assuming a small codebase. (inferred)