Files
sap-architecture/references/nudge-workflow.md
T
2026-07-24 20:47:16 +00:00

9.5 KiB

Nudge workflow — iterative LLM ↔ scripts loop

Audience: Cursor's Agent (Claude Sonnet / GPT) or Claude Code working on a single diagram with a human in the loop.

The goal of this workflow is not to one-shot a perfect diagram. It is to converge on one through small, reviewable edits — guided by the candidate PNG, the SAP target PNG, and a scored breakdown that names what to fix next.

The 3-tool loop

            ┌───────────────────┐
            │ user nudge or     │
            │ initial prompt    │
            └─────────┬─────────┘
                      │
                      ▼
        ┌───────────────────────────┐
        │ LLM picks ONE small edit  │
        │ via the Edit / Write tool │
        └─────────────┬─────────────┘
                      │
                      ▼
        ┌───────────────────────────┐
        │ scripts/autofix.py --write│   ← mechanical clean-up
        └─────────────┬─────────────┘
                      │
                      ▼
        ┌───────────────────────────┐
        │ scripts/iterate.py        │   ← renders PNG, scores,
        │   <candidate>             │     prints next-step list
        │   [--target <ref>]        │
        └─────────────┬─────────────┘
                      │
                      ▼
        ┌───────────────────────────┐
        │ LLM reads:                │
        │   candidate.png           │   ← uses its vision tool
        │   reference.png           │
        │   suggestions list        │
        └─────────────┬─────────────┘
                      │
       score ≥ 90 ────┼──── score < 90
            │         │           │
            ▼         │           ▼
       PASS — done    │     pick next ONE edit
                      │     (loop)
                      ▼
              await user nudge
              ("move Joule to the left",
               "add MCP Gateway in BTP",
               "use teal pills for MCP")

Key rules for the LLM

  1. One edit per iteration. Resist the urge to fix five things at once. The score breakdown ranks dimensions by weighted impact — pick the top suggestion. Always re-run iterate.py after each edit so you can see the score delta.

  2. Always look at the PNGs. The text breakdown will tell you "icons missing", but the PNG tells you where to put them. After every iterate.py run, open both candidate.png and reference.png with your vision/read tool. Reason about them visually, not only by hex value.

  3. Watch the delta. iterate.py reports ↑+3.2 or ↓-1.5 since the previous run. If you went down, your last edit was wrong — undo it (your text editor's history or git diff) before trying something else. Don't pile bad edits on top of bad edits.

  4. Stop at PASS. Once the score is ≥ 90 and the user has given no further nudge, stop. Don't keep editing in pursuit of 100 — you'll start replacing intentional differences (the candidate's scenario labels) with template defaults.

  5. When the user nudges in natural language, treat it as a single edit step. "Make Joule purple" → find the Joule zone cell → change fillColor and strokeColor to #F1ECFF / #5D36FF → autofix → iterate. Don't conflate the nudge with other improvements you also see.

  6. Ask the user before destructive moves. Examples that need confirmation: deleting a zone the user explicitly added, swapping the chosen template for a different one, regenerating the file from scratch. A nudge is small; if your only path to compliance is a rewrite, ask first.

What iterate.py gives you

Every run prints a structured block. Read it carefully — every line is there to direct your next move:

─── SAP DIAGRAM ITERATION ───
candidate    : docs/architecture/foo.drawio
target       : ac_RA0029_AgenticAI_root.drawio  (corpus fingerprint match)
score        : 78.4 / 100   ↑+3.2 since last iteration
pass gate    : 90.0   (BELOW — keep iterating)

📷 Read these images with your vision tool to plan the next edit:
   candidate :  .cache/sap-architecture-iter/foo/foo.candidate.png
   reference :  .cache/sap-architecture-iter/foo/ac_RA0029_AgenticAI_root.reference.png
   side-by-side HTML : .cache/sap-architecture-iter/foo/review.html

⚠ Lowest-scoring dimensions (fix worst first):
   zones        45.0%  ████░░░░░░
   zone_depth   50.0%  █████░░░░░
   icons        55.0%  █████░░░░░
   pill_vocab   60.0%  ██████░░░░
   ...

✏ Next concrete edit (do ONE, then re-run iterate.py):
   1. Add 4 zone container(s). Reference has 8 zones; you have 4. Use rounded
      rect with arcSize=16, strokeWidth=1.5, and a top-left bold inline label.
   2. Add 6 BTP service icon(s). Use scripts/extract_icon.py
      "<service-name>" --x <X> --y <Y> --id <id> to get a ready mxCell.
   3. Replace 2 novelty pill verb(s). Allowed: TRUST, Authenticate, ...
   ...

✓ Score improved +3.2. Keep going.

Translating nudges into edits

User nudge What you should do
"Make Joule purple" Find the Joule zone cell (<mxCell value="Joule"...> or similar). Set fillColor=#F1ECFF;strokeColor=#5D36FF. autofix → iterate.
"Add MCP Gateway in BTP" Look at the reference PNG to see where MCP Gateway goes. Duplicate an existing card (e.g. Custom Agents), change its label to MCP Gateway, use extract_icon.py "Integration Suite" for the icon, and put it inside the BTP zone parent. autofix → iterate.
"Move System Trigger to bottom-left" Find the System Trigger cell, edit its <mxGeometry x="..." y="..."> so x is small and y is high. Keep on 10-px grid. autofix → iterate.
"Use teal pills for the MCP flow" Find the MCP-flow pill cells (likely arcSize=50 near the cards you want connected). Set fillColor=#DAFDF5;strokeColor=#07838F on each. autofix → iterate.
"It looks too crowded" Compare zone counts vs reference. If you have more zones than ref, remove the least-essential one. If geometry density is too high, increase canvas pageWidth/pageHeight (rare). autofix → iterate.
"I don't like this template, try a different one" This is the destructive case — ask the user to confirm. If yes: scaffold_diagram.py --template <other>.drawio --out <same-destination> --force. The file will be replaced.

Common loops

Initial-creation loop (after fresh scaffold)

  1. Run scaffold_diagram.py "<request>" --out foo.drawio — produces a SAP-anchored starting point at ~100% structural similarity to its source template.
  2. Run iterate.py foo.drawio — first iteration; it picks the source template as target automatically and reports near-100 score because edits haven't started.
  3. Make label edits to fit the user's scenario (rename SuccessFactorsARC-1, etc.).
  4. After every 1-3 small edits, run autofix.py --write foo.drawio && iterate.py foo.drawio.
  5. Loop until either the user is satisfied or score is ≥ 90.

User-nudge loop (later refinement)

  1. User says: "Joule should be on the left, not in the middle."
  2. Read candidate.png from the last iterate run to see current Joule placement.
  3. Read reference.png to understand the canonical SAP layout.
  4. Make ONE edit: change Joule zone's <mxGeometry x="..." to a smaller value.
  5. Run autofix.py && iterate.py.
  6. Confirm with the user that the placement now matches their intent — they may want it even further left, or a different zone moved instead.

Recovery loop (you regressed)

  1. Last iterate.py showed ↓-2.5 — your edit broke something.
  2. Use git diff foo.drawio (or your editor's undo) to inspect the exact change that hurt the score.
  3. If the change was off the user's nudge path, undo it and try a smaller, more targeted version.
  4. If the change WAS on the user's nudge path but the structural cost is high, explain the tradeoff to the user and ask whether they want the visual change or the score.

When to stop

The loop terminates when ANY of these are true:

  • iterate.py reports score >= 90 AND the user has given no follow-up nudge.
  • The user explicitly says "good", "stop", "ship it".
  • Five consecutive iterations move the score by less than ±0.5 points (you're at a plateau — better to ask the user what to nudge next than to keep guessing).
  • The user starts asking for changes that aren't SAP-style (custom dark backgrounds, novelty pill verbs the validator rejects). In that case acknowledge the tradeoff once and proceed.

What iterate.py does NOT do

  • It does not edit the diagram for you. You (the LLM) make all edits.
  • It does not run Ollama. The LLM in Cursor / Claude Code IS the model — iterate.py just feeds it visual + scored feedback.
  • It does not roll back automatically. Use git or your editor's undo for that.
  • It does not change the target template mid-loop unless you re-invoke with --target. If you scaffolded from template A and are 30 iterations in, switching to template B will reset the score baseline.