encodeCanonicalGraph function

String encodeCanonicalGraph({
  1. required List<GraphFlow> flows,
  2. required List<GraphNode> nodes,
  3. required List<GraphEdge> edges,
  4. String adapterName = cliAdapterName,
})

Kanonisches Graph-JSON nach DD §C: rekursiv sortierte Schlüssel, 2-Space-Indent, LF, abschließender Zeilenumbruch, kein generatedAt.

adapterName ist der meta.adapters-Eintrag: cliAdapterName für den CLI-Scan, builderAdapterName für das build_runner-Artefakt (Weg D) — ansonsten sind beide Ausgaben byte-identisch (Paritätsgarantie).

Implementation

String encodeCanonicalGraph({
  required List<GraphFlow> flows,
  required List<GraphNode> nodes,
  required List<GraphEdge> edges,
  String adapterName = cliAdapterName,
}) {
  int byId(String a, String b) => a.compareTo(b);
  final graph = <String, Object?>{
    'schemaVersion': schemaVersion,
    'flows': ([...flows]..sort((a, b) => byId(a.id, b.id)))
        .map((f) => f.toJson())
        .toList(),
    'nodes': ([...nodes]..sort((a, b) => byId(a.id, b.id)))
        .map((n) => n.toJson())
        .toList(),
    'edges': ([...edges]..sort((a, b) => byId(a.id!, b.id!)))
        .map((e) => e.toJson())
        .toList(),
    'meta': {
      'adapters': [
        {'name': adapterName, 'version': adapterVersion},
      ],
    },
  };
  final encoded =
      const JsonEncoder.withIndent('  ').convert(_canonicalize(graph));
  return '$encoded\n';
}