How Hallmark's Project Memory Uses `.hallmark/log.json` to Track Diversification

Hallmark stores a lightweight JSON array at .hallmark/log.json and prepends each run's macrostructure, theme axes, and enrichment choices to enforce diversification rules across consecutive builds.

Hallmark's project memory system ensures no two consecutive page generations repeat the same macrostructure or theme combination. This article explains how the .hallmark/log.json file works, what data it captures, and how Hallmark uses it to guarantee visual variety—even when re-running identical briefs.


What .hallmark/log.json Stores

Hallmark creates .hallmark/log.json at the project root after its first successful run. Each entry is a JSON object appended to the front of the array (newest first), following the structure defined in skills/hallmark/SKILL.md §2.5.

Standard Fields (All Runs)

  • date: ISO date string (YYYY-MM-DD)
  • macrostructure: Selected layout pattern (e.g., "Bento Grid", "Long Document", "Stat-Led")
  • theme: Catalog theme name ("Coral", "Bloom") or "custom" for user-defined runs
  • enrichment: Hero enrichment archetype ("E1 clipped-edge", "none", etc.)
  • brief: One-line summary of the source brief

Custom-Run Additional Fields

When theme: "custom", Hallmark records two extra fields per custom-theme.md §F:

  • theme_axes: The three diversification axes as a slash-separated string—"paper band / display style / accent hue" (e.g., "light / italic-serif / chromatic-terracotta")
  • vibe: The user's shorthand vibe phrase (e.g., "archival warmth, hand-set, no varnish")
[
  {
    "date": "2026-05-01",
    "macrostructure": "Stat-Led",
    "theme": "custom",
    "theme_axes": "light / italic-serif / chromatic-terracotta",
    "vibe": "archival warmth, hand-set, no varnish",
    "enrichment": "none",
    "brief": "Coffeebox · subscription"
  }
]

How Hallmark Reads Project Memory

Before selecting any macrostructure or theme, Hallmark checks for .hallmark/log.json existence. The logic is implemented in skills/hallmark/SKILL.md §2.5.

If the File Exists

Hallmark loads the last 3–5 entries and applies two guardrails:

  1. Macrostructure diversification: The candidate macrostructure must not match any of the last three entries. If it does, Hallmark rejects it and selects an alternative.

  2. Theme diversification: The new theme must differ on at least one axis (paper band, display style, or accent hue) from the most recent entry.

If the File Does Not Exist

Hallmark treats the run as a first run with no constraints, then creates .hallmark/log.json after the build completes with the initial entry.


Diversification Logic in Practice

The diversification system follows a strict read-evaluate-record loop:

Step 1: Load Recent History

Hallmark slices the first 5 entries from log.json to establish the exclusion window.

Step 2: Enforce Macrostructure Variety

// Pseudocode reflecting SKILL.md §2.5 logic
const recentMacros = recent.slice(0, 3).map(e => e.macrostructure);
let candidateMacro = pickMacrostructure();

while (recentMacros.includes(candidateMacro)) {
  candidateMacro = pickAlternativeMacrostructure();
}

Step 3: Enforce Theme Variety

For catalog themes, Hallmark reads axis values from site/css/tokens.css:

const prevAxes = getAxesFromTokensCss(recent[0].theme);
const candidateAxes = getAxesFromTokensCss(candidateTheme);

// Must differ on at least one axis
if (axesMatch(prevAxes, candidateAxes)) {
  candidateTheme = pickAlternativeTheme();
}

For custom themes, axes are parsed directly from the previous entry's theme_axes string:

// From custom-theme.md §F implementation
const prevAxes = recent[0].theme_axes?.split(' / ');
const candidateAxes = computeCustomAxes(); // e.g., ["light", "italic-serif", "chromatic-terracotta"]

if (prevAxes && candidateAxes.every((a, i) => a === prevAxes[i])) {
  // Reject—at least one axis must change
  candidateAxes = perturbAxes(candidateAxes);
}

Step 4: Record the Decision

Hallmark prepends the finalized entry:

log.unshift({
  date: new Date().toISOString().split('T')[0],
  macrostructure: candidateMacro,
  theme: candidateTheme,
  ...(candidateTheme === 'custom' && {
    theme_axes: candidateAxes.join(' / '),
    vibe: userVibe
  }),
  enrichment: chosenEnrichment,
  brief: briefSummary
});
fs.writeFileSync('.hallmark/log.json', JSON.stringify(log, null, 2));

Multi-Page and Redesign Scenarios

For app-level redesigns, Hallmark writes a single combined entry rather than per-page records. Per skills/hallmark/references/verbs/redesign.md, these entries use "scope": "app" and capture the full macrostructure stamp including nav and footer archetype selections.


Key Source Files

File Purpose
skills/hallmark/SKILL.md Core diversification workflow, log read/write logic, and guardrail rules
skills/hallmark/references/custom-theme.md Log entry schema for custom runs, theme_axes and vibe field definitions
skills/hallmark/references/verbs/redesign.md Combined log entry format for multi-page redesigns
site/css/tokens.css Axis value storage for catalog theme diversification checks
.hallmark/log.json Generated project memory file (created after first run)

Summary

  • Hallmark's .hallmark/log.json acts as persistent project memory, storing the most recent 3–5 runs in a front-appended JSON array.
  • Macrostructure diversification blocks repetition within the last three entries.
  • Theme diversification requires at least one axis change (paper band, display style, or accent hue) from the immediate previous entry.
  • Custom themes record theme_axes and vibe directly; catalog themes resolve axes via site/css/tokens.css.
  • The system is route-blind: a custom run following a catalog run (or vice versa) must still satisfy the same axis-difference rule.

Frequently Asked Questions

What happens on the very first Hallmark run?

If .hallmark/log.json does not exist, Hallmark generates without constraints and creates the file afterward with the first entry. The second run then begins enforcing diversification rules.

Can I manually edit .hallmark/log.json?

Yes—the file is standard JSON. Removing entries or changing macrostructure values adjusts what Hallmark considers "recent." However, malformed JSON will cause Hallmark to treat the next run as a fresh start.

How does Hallmark handle theme axes for catalog versus custom themes?

Catalog themes store axis values in site/css/tokens.css; Hallmark looks up the previous theme's axes there. Custom themes embed theme_axes directly in the log entry, so Hallmark parses that string without external lookup.

Does the diversification apply across different project directories?

No—.hallmark/log.json is project-scoped. Each directory maintains independent memory. Running Hallmark in /project-a does not affect diversification rules in /project-b.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →