Enforces and generates the strict API → Domain → KML → Transport data pipeline. Ensures external API data flows through clean contracts before reaching the LG rig.
Manages the end-to-end data transformation pipeline: External API → Provider Contract → Domain Model → KML Feature → KML Payload → LG Transport
Announce: "Data Pipeline skill activated. Building the clean path from API data to LG visualization."
⚠️ PROMINENT GUARDRAIL: The Critical Advisor (.agent/skills/lg-critical-advisor/SKILL.md) and LG Shield (.agent/skills/lg-shield/SKILL.md) are active at all times. If the student can't explain why we separate API providers from KML generation, STOP and invoke the Critical Advisor.
Every data visualization in an LG app follows this exact flow:
┌─────────────────────────────────────────────────────────────────┐
│ DATA PIPELINE │
│ │
│ External API lib/providers/ lib/models/ │
│ (USGS, NASA, etc.) *_provider.dart *_model.dart │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ HTTP Response → Provider Contract → Domain Model │
│ │ │
│ ▼ │
│ lib/services/ lib/services/ │
│ kml_service.dart ssh_service.dart │
│ │ │ │
│ ▼ ▼ │
│ KML Payload ────→ SSH Transport → LG Rig │
└─────────────────────────────────────────────────────────────────┘
| Layer | Input | Output | Forbidden |
|---|---|---|---|
| Provider | HTTP response (JSON/XML) | Domain model(s) | KML strings, SSH calls, widget refs |
| Domain Model | Raw data | Clean typed Dart class | Business logic, side effects |
| KML Feature | Domain model(s) | Valid KML XML string | Network calls, SSH, file I/O |
| Transport | KML string + SSH config | Command execution | KML generation, data parsing |
For each external API, create a provider class in lib/providers/:
/// lib/providers/geocoding_provider.dart
///
/// Contract for geocoding lookups. The implementation can be swapped
/// (OpenCage, Nominatim, Google Geocoding) without changing downstream code.
abstract class GeocodingProvider {
Future<List<GeocodingResult>> search(String query);
Future<GeocodingResult?> reverse(double latitude, double longitude);
}
The provider:
Create immutable data classes in lib/models/:
/// lib/models/geocoding_result.dart
class GeocodingResult {
final String name;
final double latitude;
final double longitude;
final String? country;
final String? formattedAddress;
const GeocodingResult({
required this.name,
required this.latitude,
required this.longitude,
this.country,
this.formattedAddress,
});
}
Rules:
final fields, const constructor).Each visualization type gets a dedicated KML generator method in KMLService
(or a separate feature class for complex visualizations):
/// Takes domain models, produces a KML payload string.
String generateGeocodingKML(List<GeocodingResult> results) {
// Domain model → KML XML
// Uses longitude,latitude,altitude coordinate order
// Returns complete, valid KML 2.2 document
}
KML features can compose multiple KML elements:
<gx:Tour> sequences from ordered location lists<TimeStamp> / <TimeSpan> for time-based animation<ScreenOverlay> for legends and logosThe LGService facade orchestrates the final step:
Future<void> visualizeGeocodingResults(List<GeocodingResult> results) async {
final kml = _kmlService.generateGeocodingKML(results);
await _sshService.sendKML(kml);
}
The UI calls lgService.visualizeGeocodingResults(results) — it never touches
KML strings or SSH commands.
All KML generator methods must produce payloads that:
<?xml version="1.0" encoding="UTF-8"?>xmlns="http://www.opengis.net/kml/2.2" namespacexmlns:gx="http://www.google.com/kml/ext/2.2" for tours/animationslongitude,latitude,altitude coordinate order (NOT lat,lon)&, <, >, ", ')Checklist for adding any new external API to the pipeline:
lib/providers/lib/models/KMLService (or new feature class)LGServiceconfig.dartlg-shield boundary validationFor each new API integration, produces:
docs/plans/ describing the pipelineAfter building each pipeline stage, STOP and explain:
DO NOT move to the next pipeline stage until the student can explain the current transformation.
Passes generated code to lg-code-reviewer for quality checks and to
lg-shield for boundary validation.
After the data pipeline is wired and the student passes the checkpoint, automatically offer the next stage:
"Data pipeline is solid! Clean contracts from API to KML. Now let's scaffold the Flutter screens that will use these services. Ready for the UI Scaffolder? 📱"
If student says "ready" → activate .agent/skills/lg-ui-scaffolder/SKILL.md.