Skip to content

feat(plan): add a plain-language Markdown report #144

Description

@bwl21

Problem

ct plan currently has two useful projections:

  • the terminal diff, aimed at the operator running ct; and
  • --json, aimed at machines and CI tooling.

Neither is a good review artifact for non-technical ChurchTools stakeholders. A ministry lead or master-data owner should be able to review, in plain language:

  • what will be created or changed;
  • what an automatic group will do;
  • whether existing data is touched;
  • whether anything could be deleted; and
  • what must be checked before somebody runs apply.

A consumer-repository proof of concept, churchtools-processes/tools/render-plan-report.mjs, already turns ct plan --json into a German Markdown report. It demonstrates the value, but it is deliberately project-specific: it focuses on newly created groups and group-member fields, contains fixed wording and role assumptions, knows selected dynamic-group internals, refers to ct-dev, and must reconstruct display names from raw plan data. This should become a generic projection owned and tested by ct-cli, not a script every consumer repository has to reinvent.

Proposed interface

Add a first-class Markdown output format:

ct plan --format markdown > plan.md
ct plan --env prod --format markdown > plan-prod.md

Prefer a general format selector:

--format text|json|markdown

Keep --json as a backward-compatible alias for --format json; reject conflicting combinations clearly.

The first concrete consumer needs German (de-DE) wording. The implementation should avoid organization-specific vocabulary and keep human-facing labels in a small locale dictionary so English or another locale can be added without changing plan semantics. The exact locale flag/default can be decided during design, but it must be explicit and deterministic in CI.

Architectural constraint

Markdown is a presentation of the same structured plan result used by terminal and JSON output:

plan/application result
    ├── terminal renderer
    ├── JSON serializer
    └── Markdown renderer

The renderer must not:

  • invoke ct plan --json as a subprocess;
  • parse terminal output;
  • fetch ChurchTools data itself;
  • recalculate plan actions, drift, completeness, permission diffs or safety policy; or
  • introduce resource behavior that differs from terminal/JSON output.

If the structured plan result does not currently contain a display name or context needed for a good report, enrich the shared result once rather than reconstructing it independently in Markdown.

Report content

The Markdown report should include:

  1. Context

    • environment, ChurchTools host/version and config path where available;
    • generation timestamp with an injectable clock for deterministic tests;
    • a prominent statement that this is only a plan and nothing has been written yet.
  2. Plain-language summary

    • create/update/delete-candidate/no-op counts;
    • counts grouped by human-readable resource type;
    • permission grants and revocations;
    • a clear “no changes required” result when applicable.
  3. Creates and updates

    • display name first, technical key/ID second;
    • readable old → new field values for updates;
    • hierarchy and logical references shown by name where the shared result can resolve them;
    • source attribution (config, drift, config+drift) explained in non-technical language;
    • useful semantic summaries for dynamic groups and group-member fields, without assuming specific group names, role IDs or field reference names.
  4. Permissions

    • grants/revocations grouped by their domain (group role, group-type role, status);
    • right names and scopes in readable form;
    • preserved/unknown rights described without implying that ct will revoke them.
  5. Safety and review

    • dropped config resources clearly described as not deleted by apply;
    • incomplete plans/unreadable resources shown as a blocking warning, never as a clean plan;
    • relevant catalog/portability warnings included or referenced without being lost on stderr;
    • a short review checklist before apply.
  6. Technical appendix

    • logical keys, ChurchTools IDs and other diagnostic detail useful to the operator;
    • generic fallback rendering for every current and future resource type.

The main report should not dump raw nested JSON when a value can be described meaningfully. Unknown future fields/types may use an escaped, deterministic fallback in the technical appendix so the renderer never silently omits a planned change.

Resource metadata

Avoid a growing project-specific if (type === "group") script. Reuse or extend the resource registry with presentation metadata where appropriate, for example:

  • singular/plural display labels;
  • display-name field;
  • field labels;
  • generic value/reference formatters; and
  • optional type-specific detail renderers for genuinely semantic structures such as dynamic rulesets.

Every resource must have a generic fallback. Adding a new managed resource should not require a Markdown renderer change merely to make that resource visible.

Acceptance criteria

  • ct plan --format markdown writes a complete Markdown document to stdout.
  • --json remains backward compatible; --format json produces the same documented JSON shape.
  • Markdown and JSON/terminal projections originate from the same plan computation and agree on actions, summaries, drift, permissions and completeness.
  • The report is useful without understanding logical keys, numeric IDs or raw dynamic-group JSON; those details remain available in an appendix.
  • All managed resource types are represented, with a safe fallback for an unknown/future type.
  • Creates, updates, drift, delete candidates, permission changes, no-op plans and incomplete plans are covered.
  • Markdown tables/cells/headings safely escape pipes, line breaks, backticks and user-controlled names.
  • Output ordering is deterministic; timestamps/locales are injectable or controllable in tests.
  • Snapshot/fixture tests cover at least:
    • no changes;
    • a mixed create/update plan;
    • drift and config+drift;
    • delete candidates and preventDestroy context;
    • permission grant/revoke/preserved entries;
    • an incomplete plan with fetch errors;
    • dynamic groups and group-member fields;
    • unknown resource/field fallback; and
    • Markdown escaping.
  • Documentation includes examples for saving the report and publishing it as a CI/PR artifact.
  • No ChurchTools token or other secret can appear in the report.

Non-goals

  • Applying changes from Markdown.
  • Replacing the operator-oriented terminal diff.
  • Rendering organization-specific approval text or hard-coded ministry/group names.
  • Hiding technical warnings to make a report look simpler.

Why this belongs in ct-cli

Only ct-cli has the complete semantic context: resource registry, logical references, action attribution, permission catalog, protected environments and the distinction between a delete candidate and what apply actually does. Owning the renderer here prevents consumer repositories from duplicating that knowledge and drifting away from the real plan semantics.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageUnsorted intake — decide in the weekly sweep

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions