# Update Guide

> Modify an existing Pathfinder guide based on a change request. Plans the edit, applies it surgically, runs a review pass against critical rules, and validates with the Pathfinder CLI. Preserves all blocks outside the planned change. Use when the user wants to add, edit, or remove blocks in an existing guide, swap a data source, retrofit lazyRender, or otherwise modify a guide's content.json without rewriting it from scratch.

- Skill: `grafana/update-guide` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add grafana/update-guide`
- Raw SKILL.md: https://api.skillmd.com/api/skills/grafana/update-guide/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: grafana (https://skillmd.com/u/grafana)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/grafana/update-guide

---


# Update Existing Guide

Modify an existing `content.json` based on a change request. The skill plans the edit, applies it, reviews it against the critical rules, and validates the result. Blocks outside the planned change are guaranteed unchanged (byte-level diff at the end).

**This skill writes to `content.json`.** It is not read-only — read [safety-invariants.md](safety-invariants.md) before running.

**Do NOT read external reference files upfront.** Each phase's sub-agent loads its own references. Everything the orchestrator needs is inline below.

This skill implements the **skill-memory convention**. See [../skill-memory.md](../skill-memory.md) for the shared `assets/`, manifest, and frontmatter standards.

---

## Workflow Overview

```
Input (guide directory + change request)
  │
  ├─ Phase 0: Check for Prior Run ── orchestrator
  │    Hash = guide content + change request
  │
  ├─ Phase 1: Acquire & Snapshot ── orchestrator (no external reads)
  │    Reads: content.json, manifest.json
  │    Writes: assets/snapshots/content.json.before
  │             assets/guide-structure.json (id → path map)
  │
  ├─ Phase 2: Plan the Change ───── sub-agent loads authoring-guide.mdc
  │    │                              + best-practices.mdc
  │    │                              + ../shared/critical-rules.md
  │    Writes: assets/change-plan.md
  │
  ├─ Checkpoint: User confirms plan ── orchestrator
  │
  ├─ Phase 3: Apply the Change ──── orchestrator + per-section sub-agents
  │    │                              (sub-agents load authoring-guide.mdc + best-practices.mdc)
  │    Writes: updated content.json
  │             assets/change-log.md (before/after per block path)
  │
  ├─ Phase 4: Review & Fix ──────── sub-agent loads review-guide-pr.mdc
  │    │                              + ../shared/critical-rules.md
  │    Writes: fixed content.json + assets/review-report.md
  │
  └─ Phase 5: Validate ──────────── orchestrator
       Byte-level diff vs snapshot for unchanged paths
       JSON validity, ID uniqueness, IDREF resolution
       Pathfinder CLI: validate --package {guide_dir}
       On failure: restore from snapshot, mark run failed
```

---

## Inputs

- **Required**: `guide_dir` — path to a directory containing `content.json`.
- **Required**: `change_request` — free-text description of the change ("add a Loki section after the Prometheus one", "swap data source X for Y", "add `lazyRender: true` to the step at blocks[3].blocks[2]") OR a structured change spec (see [change-request-schema.md](change-request-schema.md)).
- **Optional**: `target_path` — explicit block path (e.g., `blocks[3].blocks[2]`) when the change_request is ambiguous about location. Phase 2 will use this if provided.

If the user gives only `guide_dir`, ask for the `change_request`. Free-text is acceptable.

---

## Critical Rules

Read [../shared/critical-rules.md](../shared/critical-rules.md) for the canonical 21 critical rules. Phase 2, Phase 3, and Phase 4 sub-agents must cite rule numbers when proposing or reviewing changes. The shared file forwards to [../../../AGENTS.md](../../../AGENTS.md) — that is the authoritative list.

---

## Safety Invariants

Read [safety-invariants.md](safety-invariants.md) — five inviolable rules the orchestrator and Phase 5 enforce. Violating any one fails the run and restores from snapshot.

---

## Generated Files

The deliverable is the updated `content.json`. Everything in `assets/` is skill-internal.

```
{guide_dir}/
  content.json                        ← UPDATED (was modified by Phase 3)
  manifest.json                       ← UPDATED only if change_request affects manifest fields
  assets/
    manifest.yaml                     ← skill memory (input hash, change request, last_update_at)
    guide-structure.json              ← id → path map (Phase 1)
    change-plan.md                    ← user-approved plan (Phase 2)
    change-log.md                     ← per-block before/after (Phase 3)
    review-report.md                  ← review findings + fixes (Phase 4)
    snapshots/
      content.json.before             ← pre-write snapshot (Phase 1)
```

### Frontmatter disclaimer

Every generated markdown file in `assets/` **must** start with:

```markdown
---
disclaimer: Auto-generated by update-guide skill. Do not edit manually.
notice: To regenerate, re-run the skill with the same change request.
input_sha256: {hex digest}
guide_id: {id from content.json}
change_request: "{the change request, truncated to 100 chars}"
---
```

### Manifest file

After Phase 5, write `{guide_dir}/assets/manifest.yaml`:

```yaml
# Auto-generated by update-guide skill. Do not edit manually.
schema_version: 1
skill_name: "update-guide"
generated_at: "{ISO 8601 timestamp}"
input_sha256: "{hex digest — see below}"

guide:
  id: "{guide id from content.json}"

change:
  request: "{the full change request}"
  paths_added: ["blocks[N]", ...]
  paths_edited: ["blocks[M]", ...]
  paths_removed: ["blocks[P]", ...]

validation:
  cli_validate_passed: {true|false}
  byte_level_diff_clean: {true|false}

files:
  change_plan: "assets/change-plan.md"
  change_log: "assets/change-log.md"
  review_report: "assets/review-report.md"
  snapshot: "assets/snapshots/content.json.before"
```

Compute `input_sha256` by hashing the pair `(content.json contents, change_request)`:

```bash
cat {guide_dir}/content.json <(printf "\n---\n%s" "{change_request}") | shasum -a 256 | awk '{print $1}'
```

This means re-running the same change against the same starting content.json matches the prior run and triggers warm-start. If either the content or the request differs, a fresh plan is generated.

---

## Phase 0: Check for Prior Run (Orchestrator)

Before starting the update pipeline, check whether this update has already been applied.

1. Check whether `{guide_dir}/assets/manifest.yaml` exists.
2. If it does: read the manifest, extract `input_sha256` and `change.request`.
3. Re-hash the current pair: `cat content.json <(printf "\n---\n%s" "{change_request}") | shasum -a 256 | awk '{print $1}'`.
4. Compare hashes:
   - **Match** → this exact change was already applied. Tell the user (cite `change.request` and `generated_at`) and offer three options: (a) view the existing `change-log.md`, (b) re-run the change against the *current* `content.json` (treating it as a fresh request — drops the prior manifest), (c) abort.
   - **Mismatch** → this is a different change request or the file has been edited since. Move the prior `manifest.yaml`, `change-plan.md`, `change-log.md`, `review-report.md` to `assets/history/{prior_generated_at}/`. Proceed with the fresh run.
5. If `manifest.yaml` does not exist: fresh run — proceed to Phase 1.

---

## Phase 1: Acquire & Snapshot (Orchestrator)

1. Verify `{guide_dir}/content.json` exists and is valid JSON. If not, report the parse error and stop.
2. Create `{guide_dir}/assets/snapshots/` and copy `content.json` to `assets/snapshots/content.json.before` (raw bytes — no parsing, no re-serialisation).
3. Read `manifest.json` if present (Phase 2 may reference it for context).
4. Walk the block tree and produce `assets/guide-structure.json` — a map from every block id (and section id, input variable name) to its path. Shape:

   ```json
   {
     "ids": {
       "open-dashboards": "blocks[2].blocks[0]",
       "configure-prometheus": "blocks[3]"
     },
     "section_ids": {
       "navigation": "blocks[2]"
     },
     "input_variables": {
       "datasourceName": "blocks[1]"
     },
     "tree_summary": {
       "total_blocks": 42,
       "total_sections": 5,
       "total_interactive_steps": 18
     }
   }
   ```

5. Compute `input_sha256` (see above) and stash it for Phase 5.

---

## Phase 2: Plan the Change (Sub-agent)

Dispatch a sub-agent (Plan subagent type) with the following brief:

````
You are the **Plan the Change** phase of the update-guide skill. Read the following files in order, then produce a change plan.

**Read (in order):**

1. [.cursor/authoring-guide.mdc](../../../.cursor/authoring-guide.mdc) — block types, action types, requirements, best practices
2. [.cursor/best-practices.mdc](../../../.cursor/best-practices.mdc) — decision trees for blocks/actions/requirements/objectives; code smells
3. [../shared/critical-rules.md](../shared/critical-rules.md) — the 21 critical rules (cited by number)
4. [./change-request-schema.md](./change-request-schema.md) — structured change-request shapes (for context, even if the request is free-text)
5. {guide_dir}/assets/guide-structure.json — the id → path map
6. {guide_dir}/content.json — the original guide (for context)

**Resolve the change_request `{change_request}` to a concrete plan.**

For free-text requests, identify:

- **What** is changing (add a block / edit a block / remove a block / replace a section / add a requirement)
- **Where** it goes (use `target_path` if provided; otherwise infer from the request and from `guide-structure.json`)
- **Why** (so Phase 3 can write good prose for any new blocks)

For structured requests, validate against `change-request-schema.md` and surface any malformed fields.

**Output: a structured markdown plan at `{guide_dir}/assets/change-plan.md`** with the standard frontmatter disclaimer and these sections:

```markdown
# Change Plan

## Request

{verbatim change_request}

## Edits

For each edit:
- **Action**: add | edit | remove | replace
- **Path**: blocks[N].blocks[M] (existing path for edit/remove/replace; insertion target + position for add)
- **Block type**: markdown | interactive | section | ...
- **What it does**: one-sentence description
- **Why this location**: one-sentence rationale citing existing structure

## New Selectors To Verify

Any new `reftarget` selectors the user needs to confirm against the live Grafana UI before the change is applied. List one per line with the action context.

## New Requirements / Objectives

If the plan adds requirements or objectives, list them with their rationale. Cite the relevant requirement type from `docs/requirements-reference.md` (mentally — don't open it).

## IDREFs Affected

If any change touches:
- A section that other sections depend on via `section-completed:<id>`
- An `input` block whose variable is referenced by `var-<name>` or `{{<name>}}`

…list every referrer so Phase 3 knows what to revalidate.

## Risks

Anything the plan author is uncertain about. Examples:
- Selector stability ("this `data-testid` may have changed in recent Grafana")
- Section placement ("the new Loki section may be better after step 5 rather than at the end")
- Rule conflicts ("this addition may double the section's step count past 8")
```

**Do not modify content.json.** Stop after writing the plan. The orchestrator will present it to the user for confirmation.
````

After the sub-agent writes the plan, **the orchestrator presents the plan to the user and asks for confirmation** before proceeding to Phase 3. If the user requests revisions, re-dispatch Phase 2 with the same brief plus the user's feedback as additional context.

This is a hard checkpoint. Do not run Phase 3 until the user explicitly approves the plan.

---

## Phase 3: Apply the Change (Orchestrator + Sub-agents)

After plan approval:

1. Re-read `content.json` (in case the user has tweaked since Phase 1 — if so, re-snapshot and warn).
2. For each edit in the plan:
   - **Add**: insert the block at the specified path.
     - If the block is a simple structural insertion (`markdown`, `noop`), the orchestrator generates the JSON directly using the plan's "What it does" / "Why this location" prose.
     - If the block is interactive content that requires authoring expertise (a full `section`, a `guided` block with multiple steps, a `quiz`), dispatch a per-section sub-agent (Plan subagent type) with the brief below.
   - **Edit**: apply the field-level changes from the plan.
   - **Remove**: delete the block.
   - **Replace**: do a paired remove + add at the same path.
3. After every edit, write `content.json` with the same indentation style as the original (detect from `assets/snapshots/content.json.before` — usually 2-space).
4. Write `assets/change-log.md` with per-block before/after blocks. Frontmatter as above. Shape:

   ```markdown
   ## Edit 1 — add at `blocks[5]`

   **Before**: (none — new block)

   **After**:
   ```json
   { "type": "markdown", "content": "..." }
   ```

   ## Edit 2 — edit `blocks[3].blocks[2]`

   **Before**:
   ```json
   { "type": "interactive", "action": "highlight", "reftarget": "..." }
   ```

   **After**:
   ```json
   { "type": "interactive", "action": "highlight", "reftarget": "...", "lazyRender": true }
   ```
   ```

5. If `manifest.json` is affected by the change request (title, description, targeting, tier, dependencies, milestones), update it. Otherwise leave it untouched.

### Per-section sub-agent brief

````
You are generating one section block for an in-flight update to an existing Pathfinder guide. Read these files, then produce ONE section JSON object.

**Read (in order):**

1. [.cursor/authoring-guide.mdc](../../../.cursor/authoring-guide.mdc)
2. [.cursor/best-practices.mdc](../../../.cursor/best-practices.mdc)
3. [../shared/critical-rules.md](../shared/critical-rules.md)
4. {guide_dir}/assets/change-plan.md — the approved plan (find your section's entry under Edits)
5. {guide_dir}/assets/guide-structure.json — for ID uniqueness checks

**Section brief**: {paste the plan's "Action / Path / Block type / What it does / Why this location" for this section}

**Constraints:**
- Section id MUST be unique (check against `guide-structure.json` `ids` and `section_ids`)
- Follow all 21 critical rules
- Step budget: 3-8 interactive steps for a typical section
- Include section bookends (intro markdown immediately before the section, summary immediately after) unless the section has only 1-2 blocks. Do not put “You'll …” intros inside the section.
- Cite the rule numbers you considered in a comment block above the JSON if helpful (the orchestrator will strip the comment)

**Output**: ONE valid JSON object for the section block. No prose. No markdown fences. Just the JSON.
````

(This sub-agent pattern mirrors `autogen-guide/SKILL.md` Phase 3.)

---

## Phase 4: Review & Fix (Sub-agent)

Dispatch a sub-agent (Plan subagent type) with the following brief:

````
You are the **Review & Fix** phase of the update-guide skill. Read these files, then review the changed blocks AND their immediate neighbours.

**Read (in order):**

1. [.cursor/review-guide-pr.mdc](../../../.cursor/review-guide-pr.mdc) — the review protocol
2. [../shared/critical-rules.md](../shared/critical-rules.md) — the 21 critical rules
3. {guide_dir}/assets/change-log.md — what was changed
4. {guide_dir}/content.json — the current state of the guide (post-edit)

**Scope**: every block path listed in `change-log.md` AND its siblings + parent section.

**Apply** every blocking check from review-guide-pr.mdc §1, every structural check from §2.4-2.5, and the §4.6 legacy `?doc=` check. Auto-fix findings in-place (write the updated `content.json`) unless the fix would change the user-facing intent of the change.

**Output**: `{guide_dir}/assets/review-report.md` with the standard frontmatter disclaimer and these sections:

```markdown
# Review Report

## Summary

- Findings: N (auto-fixed: N, requires user attention: N)
- Scope: {list of block paths reviewed}

## Auto-fixed

For each: path, rule number, what changed.

## Requires user attention

For each: path, rule number, why it can't be auto-fixed.
```

**Do not touch blocks outside the scope. Do not regenerate prose — only fix concrete rule violations.**
````

---

## Phase 5: Validate (Orchestrator)

After Phase 4:

1. **Byte-level diff vs snapshot**. Parse both `content.json` and `assets/snapshots/content.json.before`. For every block path NOT in `change-log.md`, the block must be byte-identical between the two. If any unchanged path differs, this is a safety invariant violation — restore from snapshot, write `assets/review-report.md` with a `## CRITICAL: safety invariant violated` section, and stop.
2. **JSON validity**. Parse `content.json` with strict JSON. On parse error, restore from snapshot and stop.
3. **ID uniqueness**. Walk the updated tree and confirm every block id is unique. On collision, restore and stop.
4. **IDREF resolution**. For every `section-completed:<id>` requirement and every `var-<name>` requirement, confirm the target still exists. For every `{{<name>}}` in markdown content, confirm an `input` block with that variable name exists earlier in the guide. On unresolved reference, restore and stop.
5. **Pathfinder CLI validate**. Run:

   ```bash
   node {pathfinder-app}/dist/cli/cli/index.js validate --package {guide_dir}
   ```

   If the CLI is not available, surface this as an incomplete-validation warning rather than a failure (skills cannot assume the user has the CLI built). If the CLI returns non-zero, restore from snapshot and stop.

6. If all checks pass: write/update `{guide_dir}/assets/manifest.yaml` with the schema documented above. Surface a one-paragraph summary to the user with: paths added/edited/removed, validation results, and the path to `audit-report.md` if the user wants a deeper review afterwards.

If any check fails, the orchestrator MUST:

- Restore `content.json` from `assets/snapshots/content.json.before` (byte-level copy).
- Restore `manifest.json` if it was modified.
- Write `assets/review-report.md` with a `## CRITICAL: validation failed` section explaining which check failed and which snapshot was restored.
- Mark the run as failed in `assets/manifest.yaml` (`validation.cli_validate_passed: false`) and STOP.

---

## When to use vs. skip

Use update-guide when:

- An existing guide needs a non-trivial change that touches multiple blocks or requirements.
- A change request must be reviewed and validated before merging (e.g., adding `lazyRender` retrofits).
- You want a paper trail of what changed (`change-plan.md`, `change-log.md`).

Skip update-guide and hand-edit when:

- The change is a 1-line content tweak (typo, prose clarification, tooltip rewording).
- The guide doesn't yet exist — use `autogen-guide` instead.
- The change is a full rewrite — re-run `autogen-guide` from the latest source.

---

## See Also

- [autogen-guide/SKILL.md](../autogen-guide/SKILL.md) — generate a guide from source code (for *new* guides)
- [audit-guide/SKILL.md](../audit-guide/SKILL.md) — audit an existing guide (run before/after this skill for a paper trail)
- [migrate-guide/SKILL.md](../migrate-guide/SKILL.md) — migrate to the package format
- [../skill-memory.md](../skill-memory.md) — shared skill memory convention

