gcheck_core

Checklist and reference document engine of the Duniter/Ğ1 ecosystem, for Dart and Flutter applications such as Ğecko and Ginkgo.

It reads a gcheck checklist (YAML or JSON), resolves its options, selects the questions to ask and turns the answers into a verdict (pass, warning or fail). It also serves the reference documents — the Ğ1 licence and the smith and technical committee commitments — in markdown, as an HTML fragment and as a standalone HTML page, with a content hash and the earlier versions, so an application can tell whether the user accepted an outdated version and show what changed since.

Checklists and documents are embedded and come from the source of truth, g1_monetary_license: updating this dependency is enough to get the latest questions and texts. An application can also provide its own, which take precedence.

Same engine as the TypeScript, Rust and Python ports; the four share their business test cases, so they answer exactly the same thing, hash included.

Running a checklist

import 'package:gcheck_core/gcheck_core.dart';

final engine = GcheckEngine();
final checklist = getChecklist(memberCertification, 'fr')!;

final quiz = engine.prepare(checklist.content);
for (final question in quiz.questions) {
  print(question.text); // ask the user, then collect the answers
}

final verdict = engine.evaluate(quiz, {'ownKeys': true, 'meetsInPerson': false});
if (verdict.verdict == VerdictStatus.fail) {
  for (final issue in verdict.issues) {
    print('${issue.text} → ${issue.message}');
  }
}

checklist.hash() is worth storing after a successful run: it tells you later whether the checklist has changed and should be taken again.

Showing a reference document

final document = getDocument(memberCommitment, 'fr')!;

document.markdown;   // raw text
document.fragment;   // HTML to insert in an existing page
document.page();     // standalone HTML page
document.hash;       // store it once the user has accepted

// Later, with what the application kept of that acceptance
switch (document.state(Acceptance(acceptedHash))) {
  case AcceptanceState.never:    // never accepted
  case AcceptanceState.outdated: // accepted in an earlier version
  case AcceptanceState.current:  // up to date
}

// What changed since, to show before asking for a new acceptance
final changes = document.changesSince(acceptedHash);
for (final block in changes?.blocks ?? const []) {
  // EqualBlock: unchanged, ChangeBlock: removed/added, MovedBlock: moved elsewhere
}

changes.exact says whether the comparison starts from the very version the user accepted; when that version is no longer shipped, it starts from the closest kept one before it — showing a little more than what the user has not read yet, never less.

Within a rewritten line, compareWords(before, after) marks each piece as unchanged, changed or simply moved, so an application can highlight without mistaking a move for a rewrite.

Application-provided content

final catalog = Catalog.embedded()..addContent('my-checklist', yamlOrJson);
final checklist = catalog.get('my-checklist', 'fr');

// Or from files (needs dart:io, so not on the web)
import 'package:gcheck_core/gcheck_core_io.dart';
Catalog.embedded().addDir('/path/to/checklists');

Catalog() and DocumentCatalog() start empty, for an application that only uses its own content.

Licence

AGPL-3.0-or-later, like the rest of gcheck.

Libraries

gcheck_core
Moteur de checklists et de documents de référence de l'écosystème Duniter/Ğ1.
gcheck_core_io
Lecture de checklists depuis des fichiers.