Revision guide

How to change anything in the Strategic Plan, and what to run afterwards.

Written for someone editing the files rather than maintaining the LaTeX. You do not need to understand the macros — only where each kind of content lives and what shape the line takes.


Two rules

1. Numbers come from Excel; everything else comes from the .tex files. The document never opens the workbook. export_metrics reads the workbook and writes data/metrics.tex, and the document reads that. If you change a number and do not run the export, the PDF keeps the old one and nothing warns you at the time.

2. Never edit a generated file. data/metrics.tex is rewritten on every export, and columns A–C of the workbook are rewritten by sync_metrics --fix. Anything you type there is lost.


Where things live

To change Edit
A metric’s number the workbook on I:
A metric’s wording content/departments/<dept>.tex
A milestone’s wording or date content/departments/<dept>.tex
A strategic detail line content/departments/<dept>.tex
A strategy’s wording or owners content/strategies.tex
A goal’s title or narrative content/pillars-and-goals.tex
A pillar’s wording content/pillars-and-goals.tex
Board priorities config/board-priorities.tex
The plan years config/plan-window.tex
Director, portfolio counts config/agency.tex
Moving content between departments see section P
Adding or renaming a department config/departments.tex
Hiding a metric config/suppressed-metrics.tex
Mission, vision, core values content/about.tex
“The Strategic Plan” narrative content/the-plan.tex
Appendix B content/appendix-b.tex
The cover page — photo, panel, spacing lib/mhplanstyle.sty, “Cover page”
The cover photograph itself assets/cover.jpg
Colours, fonts, margins lib/mhbrand.sty

Department file names are listed in config/departments.tex, fourth argument of each \newdepartment line.


A. Change a metric’s number

  1. Open the workbook: I:\PnR\Special Projects\MaineHousing Strategic Plan\Data Collection - Metrics.xlsx
  2. Find the row by its Key (column A), e.g. AM.G3.1.reinvest.
  3. Edit the yellow columns only:
    • D Line 1 Label, E Line 1 Value — e.g. 3yr Avg / 2.72%
    • F/G and H/I for a second and third line
    • K Owner, L Last Updated
    • Column J Preview shows how the cell will print. It is a formula; do not type over it.
  4. Type values exactly as they should appear — $33,085,573, sub-5%, 25 days or less. Do not add backslashes; the export escapes LaTeX characters for you.
  5. Save and close Excel.
  6. Run the export and rebuild — see Build and verify below.

A blank value prints a red TBD and raises a build warning, so gaps stay visible rather than silently becoming zero.


B. Change a metric’s wording

The description is in the department file, not the workbook.

  1. Open content/departments/<dept>.tex.

  2. Find the line:

    \metric{Subsequent loan proceeds reinvested annually in maintaining
      and improving the physical condition of properties.}{AM.G3.1.reinvest}
  3. Edit the first braces (the wording). Leave the second (the key) alone — the key is what ties the row to the workbook.

  4. Rebuild. make check will notice that the workbook’s copy of the wording is now out of date and report it as STALE; run python scripts/sync_metrics.py --fix to refresh column C.


C. Add a metric

  1. In content/departments/<dept>.tex, add a line inside the right \rstrategy block:

    \metric{Number of new thing counted.}{AM.G3.2.newthing}

    Keys follow DEPT.Gn.m.slug — department, goal, strategy, short name. Metrics appear in the order the lines appear.

  2. Rebuild. The metric prints TBD because the workbook has no row yet.

  3. Add the row to the workbook, either by hand or with python scripts/sync_metrics.py --fix, which appends any key the document asks for and the workbook lacks.

  4. Fill in the value, export, rebuild.


D. Hide a metric but keep collecting it

Use this when a figure is not ready to publish but you still want the data gathered.

  1. Add the key to config/suppressed-metrics.tex:

    \suppressmetric{AM.G3.2.cashflow}   % benchmark still being validated
  2. Rebuild. No row prints; the \metric line and the workbook row both stay put.

Do this rather than commenting out the \metric line. A commented-out metric leaves its workbook row looking like an orphan on every sync.

Every build reports what is hidden, so nothing stays suppressed by accident:

Metrics suppressed (in the workbook, not printed): 2
 -- DEV.G3.1.age15
 -- AM.G3.2.cashflow

To bring it back, delete the line.


E. Remove a metric permanently

Two places, in this order:

  1. Delete the \metric{...}{KEY} line from content/departments/<dept>.tex. Rebuild — this refreshes the key inventory.

  2. Remove the workbook row:

    python scripts/sync_metrics.py --prune          # dry run, lists them
    python scripts/sync_metrics.py --prune --yes    # actually delete

    Or delete the rows by hand in Excel; make sync names them for you.

Doing step 2 first is the mistake to avoid: the row stays in the PDF and prints TBD, because the \metric line is what puts it on the page. The build summary, make sync and make check will all flag it.


F. Change a milestone’s wording or date

  1. Open content/departments/<dept>.tex and find the line:

    \milestone{Refine and implement a portfolio risk rating tool.}{Dec}{2026}

    Three parts: text, month, year.

  2. Edit whichever you need. Month is free text — Dec, Sept, Mar.

Two variants exist:

\milestonetarget{Establish a cohort of Hub Coordinators.}{Jun}{2026}
\milestoneundated{Report results of audits to the Board of Commissioners.}

\milestonetarget prints “Target:” instead of “Expected:”. \milestoneundated prints no date at all.

Milestone dates do not roll forward with the plan window — by design. When you advance the years, a milestone dated before the new window start is flagged in the build summary so you can retire it, re-date it, or report it complete. See N.


G. Add or remove a milestone

Add or delete the whole \milestone{...}{...}{...} line inside the right \rstrategy block. Nothing else to update — milestones have no workbook rows. make milestones will show the new inventory.


H. Change a strategic detail line

Detail lines are the prose bullets under each strategy.

\detail{Increase inspection frequency for projects deemed high risk due
  to physical plant concerns.}

Edit, add or delete whole \detail{...} lines. They print in order.

Two variants:

\detaillist{Host regular meetings with partner organizations to:}{%
  \item Maintain open dialogue about program requirements.
  \item Address relevant current events and policy concerns.}

\detailseealso{DEV,PNR}

\detaillist is a detail line with a bulleted list beneath it, both in the same cell so no rule separates the bullets from the line that introduces them. Use it wherever a detail ends in a colon. (An older \detailitems, which put the list in a row of its own, still builds but is no longer used.) \detailseealso prints “Additional department details in Development and Planning & Research.” with both linked — give it department codes, and the commas and “and” are handled for any number.

To point at a strategy elsewhere in the plan, inside prose:

\detail{Access, and support advocacy (see strategy
  \backlink{strat:7.5}{7.5}), for sufficient funding.}

I. Change a strategy’s wording or owning departments

Strategy wording is declared once and reused by the pillar table and by every roadmap that carries it. Change it here and it changes everywhere.

  1. Open content/strategies.tex.

  2. Find the line:

    \newstrategy{3.1}{Maintain and improve the condition, accessibility,
      and energy efficiency of multi-family projects.}{AM,DEV}

    Three parts: number, wording, owning departments.

  3. Edit the wording, or the department list. The Departments column of the pillar table regenerates itself.

Department codes come from config/departments.tex. ALL and MULT print “All” and “Multiple” and link nowhere.


J. Add or retire a strategy

Add. Put a new \newstrategy line in content/strategies.tex in the position you want it to appear in the pillar table:

\newstrategy{3.5}{Wording of the new strategy.}{AM}

It appears in the table immediately. To give it departmental detail, add an \rstrategy{3.5} block to each owning department’s file.

Retire. Delete the \newstrategy line, then delete any \rstrategy{3.5} blocks that reference it. If you miss one the build stops with a named error rather than printing a blank:

! Package mhplan Error: Strategy 3.5 belongs to goal 3, which is not declared.

Renumbering an existing strategy is the risky edit — the number is also the link target used by roadmaps and prose cross-references. If you renumber, search the whole content/ folder for the old number.


K. Change a goal’s title or narrative

  1. Open content/pillars-and-goals.tex.

  2. Find the goal:

    \newgoal{3}{2}
      {Ensure the long-term sustainability of MaineHousing's multifamily
       portfolio.}
      {MaineHousing oversees more than \mfpropertycount{} multifamily
       properties that house \mfhouseholdcount{} Maine households. ...}

    Four parts: goal number, pillar number, title, narrative paragraph.

  3. Edit the title or the narrative. The title appears in the pillar section, in every roadmap that carries the goal, and in the PDF bookmarks — all from this one place.

To add a goal, add a \newgoal block after the pillar it belongs to. The section, heading, narrative, strategy table and bookmark all follow; main.tex needs no change. Declare the pillar before its goals or the build stops with a named error.


L. Change a pillar

Same file, above its goals:

\newpillar{2}{To preserve and improve the quality of housing in Maine.}
             {Preserve and Improve the Quality of Housing in Maine}

Three parts: number, the mission statement used in the Four Pillars summary, and the section heading that follows “Pillar Two —”.


M. Update Board priorities

Set annually, so this is revised on the same cycle as the plan window.

  1. Open config/board-priorities.tex.

  2. Replace the priorities:

    \newboardpriority{Advocacy}{Be proactive in our advocacy for
      legislation and public policies that create efficiencies.}

    They print in the order declared.

  3. Move the previous year’s set into the archive at the foot of the file, commented out, so the sequence of Board direction stays readable.

  4. The heading year comes from \setboardyear in config/plan-window.tex — no change needed here.

Optionally name the strategies a priority bears on:

\newboardpriority[8.3,8.4]{Creativity}{Focus both externally and ...}

which appends “(see strategies 8.3 and 8.4)”, hyperlinked. Leave the bracket off and nothing is added.


N. Roll the plan forward a year

  1. In config/plan-window.tex, change one line:

    \setplanwindow{2027}

    That moves the cover date, the Board priorities heading, and Appendix B’s reference to the next edition.

  2. Update config/board-priorities.tex — see M.

  3. Rebuild and read the summary:

    Milestones dated before 2027: 101

    Then run make milestones for the list by department. For each: retire it, re-date it, or report it complete.

  4. Update the numbers in the workbook and export.

  5. Review strategies and departmental detail.

  6. Run make check, then make sync, then rebuild.

  7. When publishing, set \reviewmodeoff in config/plan-window.tex so review markers disappear.


O. Director, portfolio counts and other agency facts

config/agency.tex:

\newcommand{\directorname}{Daniel Brennan}
\newcommand{\mfpropertycount}{850}
\newcommand{\mfhouseholdcount}{24,000}

These are used in the front matter and in Goal 3’s narrative, so a changed figure updates everywhere it appears.


P. Move content from one department to another

When a strategy and its detail, metrics and milestones transfer between departments, four things need attention. Strategy numbers never change — 9.1 is 9.1 whoever runs it — so only the department changes.

1. The roadmap files

Cut the \rstrategy block and everything under it from the old department’s file in content/departments/ and paste it into the new one, in the right \deptgoal section. Detail lines, \detaillist, \detailseealso and milestones all move with it unchanged and need no further edit.

2. Who owns the strategy

The easiest step to forget. content/strategies.tex lists the owning departments:

\newstrategy{1.1}{Offer a mortgage product that is highly competitive.}{HO,TRE}

Remove the old department, add the new one. Miss this and the Pillar table credits one department while the roadmap shows another — so check.R now tests for it:

[FAIL] roadmap blocks match strategy ownership   HO has a block for 1.1, owned by TRE

3. Metric keys in the workbook

Metric keys carry the department: FIN.G1.6.delinquency becomes HO.G1.6.delinquency. Rename the key in place; do not add and delete.

  1. Filter column A for the old prefix, select the moved keys, and find-and-replace FIN. with HO. within the selection. The row never moves, so values, labels, Owner, Last Updated and Notes all travel with it.
  2. Do the same for column B, Department — --fix only fills that in on rows it appends, so a renamed row keeps the old department until you change it.
  3. source("scripts/sync_metrics.R") — missing, orphaned and stale should all report none.

Why not --fix then --prune: that treats a move as a deletion plus an unrelated addition. The new rows arrive blank and the populated ones are deleted, so every value, owner, date and note is lost:

HO.G1.3.setuptime      L1=None: None     <- new, blank
FIN.G1.3.setuptime     deleted, with its values

4. Cross-references in other departments

Search content/departments/ for \detailseealso{FIN} and for \backlink{strat:...} mentioning the moved strategies. These still compile if left stale — they just point somewhere misleading, and no check will tell you.

Then

source("scripts/export_metrics.R")
source("build.R"); build_plan()
source("scripts/check.R")

Milestones need nothing beyond moving the lines: they live only in the .tex files and have no workbook rows. The department’s roadmap colour also needs nothing — it follows registry position, not content.


Q. Add or rename a department

config/departments.tex:

\newdepartment{AM}  {Asset Mgmt}  {Asset Management} {asset-management}

Four parts: code, short label for the Departments column, full name for the roadmap heading, and the file name in content/departments/.

  • Rename: edit the label or full name. Everything that prints it follows.
  • Add: add a line and create content/departments/<file>.tex. Appendix A is generated from this list, so nothing else changes.
  • Order matters. Declaration order is Appendix A’s order and sets the four-colour rotation of the roadmap tables. Inserting a department reshades everything after it.

R. Front matter and other prose

Mission, vision, core values, the Director quote content/about.tex
“The Strategic Plan” and “The Four Pillars” narrative content/the-plan.tex
Appendix B content/appendix-b.tex

Ordinary prose — edit the words.


S. Bold headings stranded at the foot of a page

Labels like Mission, Vision, Core Values and 2026 Board of Commissioners’ Priorities are bold paragraphs, not sectioning commands. Nothing in LaTeX protects them: one can be left alone at the bottom of a page with its content overleaf. A real \section is safe, because LaTeX pins a heading to the first line that follows it — an ordinary bold paragraph gets no such treatment.

Two commands in lib/mhbrand.sty supply it by hand:

\mhminorheading{2026 Board of Commissioners' Priorities}   % own paragraph
\mhminorheadingrunon{Mission}                              % text on the next line

Each refuses to start unless enough of the page remains, and keeps the label attached to whatever follows. Use them for any new bold label rather than a bare \textbf{...}.

A goal and its table

A goal heading, its narrative and the opening of its strategy table are bound into one unit, so the whole thing moves to the next page rather than leaving a heading stranded. Three things make that hold, and all three are needed:

  • \nopagebreak after the heading, binding it to the narrative;
  • \interlinepenalty inside the narrative, so TeX cannot break within it — without this the break simply moves one line up;
  • a penalty after the table header and \mhstrategykeeprows (default 2) rows held with it, so the table cannot open with a bare header.

This replaced a fixed \needspace, which could only ever be right for one combination of narrative length and first-row height. Stress-tested by inflating every narrative until the page count rose from 8 to 12: no heading was separated from its table at any length.

Goal headings

Strategic Goal n: in the pillar sections and Goal #n: in the department roadmaps carry the same protection, with a larger reserve — each is followed by a narrative paragraph and the head of a table:

\renewcommand{\mhgoalheadinglines}{8}     % default 8

These stay \subsections rather than becoming bold paragraphs, because that is what generates their PDF bookmarks and the goal:n targets the roadmaps link back to. Converting them to \mhminorheading would look identical and silently lose both.

If a label is still stranded

It is followed by something taller than the guard allows for. Raise the relevant reserve:

\renewcommand{\mhminorheadinglines}{8}    % default 5
\renewcommand{\mhgoalheadinglines}{10}    % default 8

\mhminorheadinglines at 5 is enough for a label plus the first few lines of a paragraph or list. Raising either too far just pushes headings onto the next page unnecessarily, so go up in ones and twos and rebuild.


T. Core values list

The Mission / Vision / Core Values block is in content/about.tex:

\begin{corevalues}
  \corevalue{integrity}{Integrity and Accountability}
\end{corevalues}

The first argument names the icon file, assets/value-integrity.png; the second is the label. With no icon file present a plain outlined square stands in, so the page still builds.

The icon sits in a fixed-width box, which is what keeps every label starting at the same place no matter how wide the individual icons are. Four lengths in lib/mhbrand.sty control the row:

\setlength{\mhcorevalueindent}{28pt}    % left indent of the whole row
\setlength{\mhcorevalueiconbox}{28pt}   % width reserved for the icon
\setlength{\mhcorevalueiconsize}{22pt}  % icon height
\setlength{\mhcorevaluegap}{12pt}       % icon to label

If the labels look ragged down the left, the icon box is doing its job but something else moved; if an icon looks squashed, it is wider than the box and has been scaled down to fit. Raise \mhcorevalueiconbox — the labels stay aligned, they just move right together. Icons narrower than the box are untouched and keep their full height.


U. How appendix tables break across pages

A strategy block splits across a page break freely, provided enough of its rows land on each side. Two numbers in lib/mhtables.sty define “enough”, near the top of the section headed Pagination of strategy blocks:

\newcommand{\mhblockminfirst}{2}   % rows required on the page it starts on
\newcommand{\mhblockminlast}{2}    % rows required on the page it continues onto

If neither side can be satisfied, the whole block moves to the next page.

Measured over the 124 blocks in the current plan:

Setting Rows stranded alone Appendix pages with >150pt unused
2 / 2 0 18
2 / 1 7 17
1 / 1 11 16

Stricter settings cost whitespace; looser ones pack pages tighter and leave single rows adrift. 2/2 is set.

Two things to know if you change them:

  • The row counts come from the .aux file, written on one pass and read on the next, because TeX cannot know how many rows a block has until it has set them. A first run from clean therefore applies only the minfirst half; the second pass settles it. make runs enough passes, but a single bare latexmk on a cleaned tree may not — use make force if a break looks wrong.
  • Raising either number much above 2 will start pushing whole blocks onto fresh pages and cost pages rather than tidying them.

Not every large gap in the appendix is caused by this rule. Some blocks sit on a page with room to spare and still move over whole for reasons outside these two numbers.


V. Cover page

Everything on the cover is a named length set at the top of the cover section in lib/mhbrand.sty, under the comment “Cover page”. Change the numbers there; do not go hunting inside the picture itself.

Replacing the photograph

  1. Save the photo as assets/cover.jpg.
  2. Rebuild with make force — see the warning below.

If the file is absent the cover still builds, with a plain MH Blue block where the photo would be. Nothing breaks; it just looks unfinished.

The photo is never distorted. It is scaled to cover the photo band and the surplus is cropped, the way a web banner behaves — so any proportions work. A wide panorama is scaled to the band’s height and cropped left and right; a tall portrait is scaled to the page width and cropped top and bottom.

For a photo that fills the band with no cropping at all, supply it at the band’s proportions: 8.5 × 5.45 inches, i.e. 2550 × 1635 px at 300 dpi. Anything at least that large is fine; smaller will look soft in print.

Choosing which part of the photo shows

When a photo is cropped, by default you see its top-left. Two lengths pan the crop:

\setlength{\mhcoverphotoshiftx}{2in}     % pan right
\setlength{\mhcoverphotoshifty}{1.2in}   % pan down

Positive values move right and down through the picture, towards its far corner. 0pt on both is the top-left. Work in small steps and rebuild; a tenth of an inch is visible.

Only the axis that is actually cropped can be panned, and which one that is depends on the photo:

  • a wide photo — proportionally wider than the band — is scaled to the band’s height and cropped left and right, so shiftx pans it and shifty has nothing to move;
  • a tall or normally proportioned photo is scaled to the page width and cropped top and bottom, so shifty pans it and shiftx has nothing to move.

Panning an axis with no surplus slides the photo off its band and leaves a white gap down one edge. If you see one, you are using the wrong axis for that photo — set it back to 0pt.

The photo, the white stripe and the slate band

Three lengths interact down the page: the photo is clipped at \mhcoverphotoheight, the slate band starts at \mhcoverbandtop, and anything between them shows as a white stripe.

The band is painted over the photo, so it always wins. The shipped composition uses that deliberately: the photo is clipped at 6.0in but the band starts at 5.5in, so the photo runs behind the band and there is no white stripe — the two meet flush at 5.5in. Measured on the built cover, photo 0–5.50in, slate 5.50–11.00in.

  • photoheight below bandtop leaves a white stripe between them.
  • photoheight at or above bandtop closes it. The photo stops where the band starts.
  • Raising photoheight further changes nothing visible; it only adds headroom for panning (below).

So to make the photo cover more of the page, move \mhcoverbandtop down, not \mhcoverphotoheight up.

Panning needs surplus photo

\mhcoverphotoshifty slides the image up behind the clip. For the photo still to reach the band, the image — scaled to the full page width — must be at least bandtop + shifty tall. At the shipped 5.5in and 55pt that is 6.26in, i.e. about 1880px at 300dpi for an 8.5in-wide photo.

If it is shorter, its bottom edge rises above the band and a white stripe appears across the page. That is also what happens when assets/cover.jpg is missing entirely: the stand-in block is exactly photoheight tall, so any downward pan exposes a gap under it. A white stripe on a cover with no photo in it is this, not a misconfiguration.

The composition### The composition

Length Default Controls
\mhcoverphotoheight 6.0in how far down the page the photo reaches, up to \mhcoverbandtop
\mhcoverphotoshiftx 0pt pans a cropped photo right
\mhcoverphotoshifty 55pt pans a cropped photo down
\mhcoverbandtop 5.5in where the slate band begins, measured from the top of the page; also the hard ceiling for the photo
\mhcoverpanelx 0.52in white panel, distance from the left edge
\mhcoverpanely 2.7in white panel, distance from the top edge
\mhcoverpanelwidth 5.15in white panel width
\mhcoverpanelheight 6.50in white panel height

Inside the panel, top to bottom:

Length Default Controls
\mhcovertextwidth 4.55in text column width; the difference from the panel width is the left inset
\mhcovergaptop 0.35in space above the logo
\mhcoverlogoheight 0.42in logo height
\mhcovergaptitle 0.42in logo to title
\mhcovergaprule 0.85in title to green rule
\mhcoverrulewidth 4.2in length of the green rule
\mhcoverrulethick 3pt thickness of the green rule
\mhcovergapdate 0.30in rule to the date line

Two more, not lengths:

\newcommand{\mhcovertitlesize}{\fontsize{40}{48}\selectfont}
\newcommand{\mhcovertitle}{MaineHousing\\ Strategic Plan}

\mhcovertitlesize takes a size and a baseline separation — keep the second roughly 1.25 times the first. \mhcovertitle is the wording; \\ is the line break. The date line underneath comes from \planwindow and follows \setplanwindow, so it needs no editing.

The logo is assets/logo.png, sized by \mhcoverlogoheight. Absent, the cover falls back to a typeset wordmark.

Working on the composition

Rebuilding all 57 pages to look at one page is slow. Comment out everything after the cover in main.tex temporarily, or build the external edition (make external, 8 pages) — the cover is identical in both.

Always use make force while adjusting the cover. Adding or replacing a file in assets/ does not change any file latexmk tracks, so an ordinary make will report everything up to date and leave you looking at the old cover. This will waste your time at least once otherwise.


Build and verify

Whatever you changed, this is the loop.

With make:

make            export the workbook, then build      -> build/main.pdf
make check      verify everything

RStudio:

source("build.R")
build_plan()                 # export metrics, then build
source("scripts/check.R")    # verify -- the same fourteen checks as `make check`

Only changed .tex files, no workbook edits? make pdf skips the export and is quicker. When in doubt run make — the export is cheap.

Other commands:

make sync workbook vs document: missing, orphaned, stale, unrefreshed
make milestones milestone inventory: overdue, due this year, beyond
make extracts a review PDF per department, into build/extracts/ (see below)
make external the external edition, into build/external.pdf
make force rebuild ignoring the cache
make clean remove build artefacts

R equivalents, all runnable from the RStudio console: source("scripts/sync_metrics.R"), source("scripts/milestones.R"), source("scripts/check.R"), build_extracts(), build_plan_external(). Nothing routine requires leaving RStudio.

Always read the end-of-build summary

=== MaineHousing Strategic Plan: review summary ===
Plan window ....... January 2026 to December 2028
Metric values as of 31 July 2026
Metrics with no workbook value: 1
Metrics suppressed (in the workbook, not printed): 0
Milestones dated before 2026: 0

“Metric values as of” is the date the export last ran. If it is older than your workbook edit, the export did not run and the PDF has stale numbers.


Department extracts

A review packet for one department: the same source, the same numbers, the same styling, restricted to that department’s roadmap. Four to six pages instead of fifty-seven, for sending a director their own section.

make extracts                       all fourteen
python scripts/extracts.py AM DEV   just these
python scripts/extracts.py --list   show the department codes

From RStudio, needing no Python at all:

source("build.R")
build_extracts()                 # or build_extracts(c("AM", "DEV"))

Output lands in build/extracts/, named for the department — Asset Management roadmap 2026.pdf. The year follows \setplanwindow.


The external edition

make external builds an outward-facing copy — no appendices, no Departments column — from the same source. You do not maintain it separately: edit the plan as usual and rebuild both.

The only thing to keep in mind is that anything you put in a department roadmap (strategic detail, metrics, milestones) appears only in the internal edition. Content that must reach an external reader belongs in a strategy, a goal narrative, or the front matter.


Special characters

In .tex files these need a backslash:

Type Write
% \%
& \&
$ \$
# \#
_ \_

So: Maintain costs at a maximum of 5\%. and Energy \& Housing Services.

In the Excel workbook, do not escape anything. Type 2.72% and $33,085,573 as you would normally; the export handles it.

Quotation marks: use `single' and ``double'' — LaTeX turns them into proper curly quotes. A straight " gives the wrong glyph.


When the build complains

Message Meaning
Strategy 3.5 belongs to goal 3, which is not declared Strategy number points at a goal that does not exist — check content/pillars-and-goals.tex
Goal 11 is assigned to pillar 7, which has not been declared Same, one level up
No workbook value for metric key 'X' The document asks for a metric the workbook lacks — add the row, or you forgot to export
\suppressmetric{X} refers to a key no \metric{} uses A suppression outlived its metric; delete the line
Undefined control sequence Usually a mistyped command, or an unescaped %/&/$
Misplaced \omit / Misplaced \noalign A table row macro was used outside a roadmap environment, or a new one was written incorrectly — see the warning at the head of the row-macro section in lib/mhtables.sty
metrics export up to date FAIL The workbook was saved after the last export; run the export
no missing characters FAIL The font lacks a character being used and is dropping it silently; the check names the character and the face
roadmap blocks match strategy ownership FAIL A department has a roadmap block for a strategy it is not listed as owning in content/strategies.tex — usually a move with step 2 forgotten

make check runs fourteen tests and exits non-zero if any fail, so it can gate a commit. Run it before you publish anything.