"""Writes docs/werkrevisor-review-decisions.svg and its dark variant: where a review ends early or takes a shortcut.""" from html import escape LIGHT = dict(bg="#ffffff", text="#141616", muted="#55615f", soft="#3e4645", lane="#f3f6f5", step="#ffffff", step_line="#c9d3d1", dec="#e7f1f3", dec_line="#0e6b7d", arrow="#6e7c7a", label="#0e6b7d") DARK = dict(bg="#0d1312", text="#e9efed", muted="#9fb0ad", soft="#b7c4c1", lane="#17201f", step="#1e2927", step_line="#3a4a47", dec="#132e35", dec_line="#3aa3b8", arrow="#8a9a97", label="#5cc3d6") OUTCOME = {"exit": "#5f6b75", "reuse": "#0e6b7d", "error": "#58616b", "red": "#c0392b", "green": "#24733e", "yellow": "#d4a514", "orange": "#e07b2e", "hint": "#3b6fb6"} # (kind, text lines, exit label, outcome kind, outcome lines) ROWS = [ ("1 Before the model: the pull request and the rules", [ ("step", ["Werkator starts", "the review"], None, None, None), ("dec", ["Head current,", "PR open?"], "no", "exit", ["Exit 30,", "writes nothing"]), ("dec", ["Marked ready,", "\"WIP: \" removed?"], "no", "error", ["ERROR"]), ("dec", ["Head reviewed", "before?"], "yes", "reuse", ["Reuses that", "verdict"]), ("step", ["Rules on files", "and diff"], None, None, None), ("dec", ["Open question in", "a PR document?"], "yes", "red", ["RED,", "no model call"]), ("dec", ["Possible secret", "in the diff?"], "yes", "yellow", ["YELLOW, nothing", "to Jev or a model"]), ]), ("2 The shortcut, Jev, the context and the model", [ # The rules still apply, e.g. a risky path keeps its YELLOW. ("dec", ["Only mechanical,", "image or approved?"], "yes", "reuse", ["Verdict of the", "rules alone"]), ("step", ["Jev: PR documents,", "changesets, files;", "PR document check"], None, None, None), ("dec", ["Approved before,", "new blocks safe?"], "yes", "green", ["Approval", "carried over"]), ("dec", ["Classifier mode,", "no model?"], "yes", "green", ["GREEN only if", "Jev judged all files"]), ("dec", ["Prompt within", "the input limit?"], "no", "yellow", ["Excerpts, then diff;", "else YELLOW"]), ("dec", ["Budget left", "on the key?"], "no", "error", ["ERROR,", "no model call"]), ("step", ["Model review:", "advises or decides"], None, None, None), ]), ("3 After the model: findings, verdict and output", [ ("dec", ["Model call", "failed?"], "yes", "hint", ["Hint if Jev judged", "all files, else YELLOW"]), ("step", ["Jev judges each", "finding"], "", "orange", ["ORANGE, YELLOW", "or a hint"]), ("step", ["Verdict: the worst", "reason wins; risk and", "finding: RED"], None, None, None), ("dec", ["GREEN without", "full review?"], "yes", "yellow", ["Becomes", "YELLOW"]), ("dec", ["RED for", "max_red_rounds?"], "yes", "red", ["RED, asks the", "human reviewers"]), ("dec", ["Head still", "the same?"], "no", "exit", ["Exit 30,", "writes nothing"]), ("step", ["Comment, status,", "approval, merge;", "usage record"], None, None, None), ]), ] SPINES = [228, 488, 748] NODE_W, NODE_H = 176, 84 def svg(c): out = [] add = out.append add('') add('Decisions in a werkrevisor review') add(f''' ''') add(f'') add('Decisions in a werkrevisor review') add('Each check can end the review early or take a shortcut; ' 'otherwise the review goes on to the right.') for r, (heading, nodes) in enumerate(ROWS): spine = SPINES[r] add(f'') add(f'{escape(heading.upper())}') slot = 1500 / len(nodes) xs = [50 + slot * (i + 0.5) for i in range(len(nodes))] for i, (kind, lines, exit_label, outcome, outcome_lines) in enumerate(nodes): x = xs[i] top = spine - NODE_H / 2 if kind == "dec": w, h, d = NODE_W, NODE_H, 18 pts = (f"{x - w / 2 + d},{top} {x + w / 2 - d},{top} {x + w / 2},{spine} " f"{x + w / 2 - d},{top + h} {x - w / 2 + d},{top + h} {x - w / 2},{spine}") add(f'') else: add(f'') first = spine - (len(lines) - 1) * 10 + 5 for j, line in enumerate(lines): add(f'{escape(line)}') if i + 1 < len(nodes): add(f'') if kind == "dec": opposite = "yes" if exit_label == "no" else "no" add(f'{opposite}') if outcome_lines: ob_top = spine + 64 add(f'') add(f'{escape(exit_label)}') add(f'') # Yellow and orange keep their bright color, so their text is dark for the contrast. cls = "out out-dark" if outcome in ("yellow", "orange") else "out" for j, line in enumerate(outcome_lines): add(f'{escape(line)}') if r + 1 < len(ROWS): last, nxt = xs[-1], SPINES[r + 1] mid = spine + 158 add(f'') add('git.javagil.de/mi/werkrevisor') add('') return "\n".join(out) + "\n" if __name__ == "__main__": import sys target = sys.argv[1] if len(sys.argv) > 1 else "docs" open(f"{target}/werkrevisor-review-decisions.svg", "w").write(svg(LIGHT)) open(f"{target}/werkrevisor-review-decisions-dark.svg", "w").write(svg(DARK))