Skip to Content

gtmesh plan

Computes the deterministic, read-only diff between your desired state and what’s committed, prints it, and writes the planfile.

gtmesh plan # print the plan (like `terraform plan`); also writes the planfile gtmesh plan --json | jq . # machine output gtmesh plan > plan.md # keep the rendered plan

What it does

plan computes the same registry-to-registry diff that apply will enact — but changes nothing, so you can run it as often as you like. The printed plan opens with a one-line summary (Plan: 105 to recompute, 15 to propose-retire), then the catalogue/create breakdown by page type, then Changes grouped by action kind — the groups needing human review first, each line naming the page by slug — and finally the Cannibalization and Unresolved lists (pages that matched no sections_map/page_types rule — including fresh demand the topic gate parked in backlog awaiting a topic, since that’s work rather than an out-of-scope park).

Retirement needs a positive observation, never silence. A pull is scoped to one root topic (gtmesh pull demand --topic <value>), so most pulls never ask about most keywords. Only pulls that covered a root the keyword has been seen under count toward retirement.dwell_pulls — a keyword whose root simply has not been re-pulled is stale, not faded, and plan says so and tells you to re-pull it rather than proposing to retire the page.

A BUILT page is never proposed for retirement. A page that has been written, sealed and published is work, and an orphaned built page has almost always been reclassified, not faded — the bag carries every keyword it has ever seen forward, so a page keeps its demand group until something regroups it (an aliases edit under entity_aware, a changed question_page_min_volume, a question fold). plan reports it as “its demand group is now empty” and leaves it alone: the node stays, the page keeps rendering, and gtmesh page retire remains the deliberate way to remove one. Unbuilt catalogued pages still propose-retire as before.

Advisories — folded question demand, frozen slugs whose head keyword moved on, ambiguous identities — go to stderr, grouped by class so each explanation is stated once with its occurrences listed under it. That keeps stdout pipeable: gtmesh plan > plan.md captures the plan alone.

The engine never guesses: if a keyword is unresolved, fix the config rule (or add a seed/override) and re-plan until the unresolved list is what you expect. Re-planning is free.

plan is optional — apply computes the same diff itself. Run plan whenever you want a read-only preview; you never need it between a change and an apply.

Arguments & flags

OptionDescriptionDefault
--out <file>Override the plan.json output path.gtmesh/plan.json

The global --json switches stdout to machine-readable output.

Reads & writes

  • Reads: the config, reference tables, seeds, and the frozen data bag.
  • Writes: the human view to stdout, and a derived plan.json (git-ignored).
  • It is read-only with respect to your committed state — it never touches the registry or page bundles.

Examples

gtmesh plan # review the diff before applying gtmesh plan --out /tmp/p.json gtmesh plan --json | jq '.actions'
Last updated on