reclaim/app/lib/data/live_inputs.dart
flemming-it 425a0e5790 feat(live): real live mode via HubClient.submit → outputs
HubRepository.list() now runs the inline reclaim-evaluate flow per
pilot norm via submit() and maps the returned outputs to Evaluation
— the correct path, since the hub audit log stores only hashes, not
outputs. skm/benefit get their structured input as JSON (submit
jsonInputs), so the live heatmap gets real Schaden/Nutzen axes.

- live_inputs.dart: the inline eval flow + the 5 pilot norms' inputs
  (XML asset, cohort_id, skm duties, benefit ratings) plus curated
  overrides the bund adapter can't derive (true Geltungsbereich for
  the EU/Berlin norms, freshness, jurist sign-off).
- assets/norms/*.xml: 5 gesetze-im-internet-style source documents.
- tool/live_smoke.dart: dev smoke test (5/5 evaluate against a live
  hub: Schaden 3M–450M €, Nutzen 2.0–3.8, EU/Berlin scope correct).

Needs econ.skm_score's float-population fix (chain-modules commit
80f6620).

Signed-off-by: flemming-it <sf@flemming.it>
2026-06-19 02:39:15 +02:00

169 lines
4.9 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'models.dart';
/// The Recl∆Im evaluation flow, submitted inline per norm via
/// `HubClient.submit`. No `system.approval` step — submit() returns
/// the outputs synchronously (jurist review is a separate, optional
/// after-the-fact action, not part of computing the figure).
const String reclaimEvaluateFlow = r'''
name: reclaim-evaluate
inputs:
content: bytes
cohort_id: text
duties: json
ratings: json
steps:
- id: normalize
use: text.akoma_normalize@^0
with:
content: $inputs.content
mime: "application/xml"
- id: deontic
use: text.deontic_extract@^0
with:
norm: $normalize.norm
- id: citations
use: graph.citation_extract@^0
with:
norm: $normalize.norm
- id: cohort
use: stats.cohort_size@^0
with:
cohort_id: $inputs.cohort_id
- id: frust
use: text.readability_score@^0
with:
norm: $normalize.norm
graph: $citations.citations
- id: skm
use: econ.skm_score@^0
with:
duties: $inputs.duties
- id: benefit
use: law.benefit_score@^0
with:
ratings: $inputs.ratings
outputs:
norm: $normalize.norm
skm: $skm.report
benefit: $benefit.score
frust: $frust.score
cohort: $cohort.cohort
duties: $deontic.duties
citations: $citations.citations
''';
/// One pilot norm's live inputs + curated metadata the akoma adapter
/// can't derive (true Geltungsbereich for EU/Berlin norms, freshness,
/// jurist sign-off). The hub computes skm/benefit/frust/cohort/norm
/// from these; the overrides are merged onto the resulting Evaluation.
class NormLiveInput {
const NormLiveInput({
required this.assetPath,
required this.cohortId,
required this.duties,
required this.ratings,
required this.jurisdiction,
this.freshness = Freshness.current,
this.supersededNote,
this.reviewedBy,
this.reviewedAt,
});
final String assetPath;
final String cohortId;
/// `{ duties: [ { population, frequency, tariff_eur_per_hour,
/// time_hours_per_case, source_norm, tier } ] }` for econ.skm_score.
final Map<String, Object?> duties;
/// `{ schutz, markt, rechtssicherheit, eu_binnenmarkt, sicherheit,
/// umwelt, einnahmen }` (each 0..5) for law.benefit_score.
final Map<String, Object?> ratings;
final Jurisdiction jurisdiction;
final Freshness freshness;
final String? supersededNote;
final String? reviewedBy;
final DateTime? reviewedAt;
}
Map<String, Object?> _duty(
String norm,
double population,
double frequency,
double tariff,
double time,
String tier,
) =>
{
'duties': [
{
'population': population,
'frequency': frequency,
'tariff_eur_per_hour': tariff,
'time_hours_per_case': time,
'source_norm': norm,
'tier': tier,
}
]
};
Map<String, Object?> _ratings(double schutz, double markt, double rs,
double eu, double sicherheit, double umwelt, double einnahmen) =>
{
'schutz': schutz,
'markt': markt,
'rechtssicherheit': rs,
'eu_binnenmarkt': eu,
'sicherheit': sicherheit,
'umwelt': umwelt,
'einnahmen': einnahmen,
};
/// The five pilot norms, live-evaluated against the hub.
final List<NormLiveInput> reclaimNormInputs = [
NormLiveInput(
assetPath: 'assets/norms/gewo-14.xml',
cohortId: 'berlin-kmu',
duties: _duty('GewO § 14', 180000, 1.0, 35.0, 0.5, 'T3'),
ratings: _ratings(2, 3, 3.5, 2, 1.5, 0, 2),
jurisdiction: Jurisdiction.deutschland,
),
NormLiveInput(
assetPath: 'assets/norms/kassensichv.xml',
cohortId: 'gastro-de',
duties: _duty('KassenSichV § 14', 500000, 1.0, 40.0, 1.25, 'T2'),
ratings: _ratings(3, 3, 3.5, 2.5, 3, 1, 5),
jurisdiction: Jurisdiction.deutschland,
reviewedBy: 'RA Dr. M. Kessler',
reviewedAt: DateTime.utc(2026, 1, 20),
),
NormLiveInput(
assetPath: 'assets/norms/dsgvo-art30.xml',
cohortId: 'de-kmu',
duties: _duty('DSGVO Art. 30', 3000000, 1.0, 50.0, 3.0, 'T1'),
ratings: _ratings(4, 4, 4.5, 4, 3, 2, 5),
jurisdiction: Jurisdiction.eu,
reviewedBy: 'Prof. Dr. A. Lindner',
reviewedAt: DateTime.utc(2026, 2, 3),
),
NormLiveInput(
assetPath: 'assets/norms/bauo-bln-60.xml',
cohortId: 'bauwirtschaft-be',
duties: _duty('BauO Bln § 6069', 15000, 1.0, 60.0, 80.0, 'T2'),
ratings: _ratings(4, 3, 4, 2, 4, 3, 4),
jurisdiction: Jurisdiction.berlin,
reviewedBy: 'RAin S. Brandt',
reviewedAt: DateTime.utc(2026, 1, 28),
),
NormLiveInput(
assetPath: 'assets/norms/milog-17.xml',
cohortId: 'de-kmu',
duties: _duty('MiLoG § 17', 3000000, 220.0, 30.0, 0.014, 'T1'),
ratings: _ratings(4, 3, 4, 2, 3, 1, 5),
jurisdiction: Jurisdiction.deutschland,
freshness: Freshness.superseded,
supersededNote: 'BEG IV hat die Dokumentationspflichten zum '
'1.1.2026 entschärft — diese Fassung ist neu zu bewerten.',
),
];