"""HTML for the studio. Every string that came from a person or a model is escaped here. These functions take the plain dicts the engine produces (model_dump output), so the same data shown on screen is what MCP callers and exports receive. """ from __future__ import annotations import base64 import json from html import escape from humantouch.intent import STRENGTH_LABELS STATE_CLASS = { 'original': 'p-original', 'lightly edited': 'p-light', 'substantially rewritten': 'p-heavy', 'moved': 'p-moved', 'AI-added': 'p-added', 'restored by you': 'p-restored', 'kept by guard': 'p-guard', 'edited by you after generation': 'p-user', } STATE_HELP = { 'original': 'exactly as you wrote it', 'lightly edited': 'mostly your wording', 'substantially rewritten': 'reworked from your sentence', 'moved': 'your sentence, in a new place', 'AI-added': 'no counterpart in your text', 'restored by you': 'you put your wording back', 'kept by guard': 'an edit was withheld to protect meaning or protected text', 'edited by you after generation': 'you changed this by hand afterwards', } LEVEL_WIDTH = {'none': 0, 'very low': 12, 'low': 30, 'medium': 60, 'high': 100} HEADER = """

AN EDITOR THAT WORKS UNDERNEATH YOUR VOICE

Edited.
Still yours.

HumanTouch helps AI edit your writing without sanding away the parts that make it yours. Paste something you’ve written. I can tighten it, reshape it, help you continue it, compare versions, or learn the patterns of your voice. I’ll tell you when I think a revision changes more than style.

""" FOOTER = """ """ EMPTY = '

Nothing here yet. This fills in after an edit.

' def _short(text: str, limit: int = 90) -> str: text = ' '.join((text or '').split()) return text if len(text) <= limit else text[:limit - 1] + '…' def change_label(change: dict) -> str: left = f'“{_short(change["original"], 40)}”' if change['original'] else '(nothing)' right = f'“{_short(change["revised"], 40)}”' if change['revised'] else '(removed)' return f'{change["id"]:02d} · {left} → {right} · {change["category"]}' def summary(result: dict | None, fixture: bool = False) -> str: if not result: return '' a = result['analysis'] s = a['stats'] parts = ['
'] if fixture: parts.append('

Development provider: these edits come from a mechanical test double, not a language model.

') mode = 'ghost' if a['assistance_mode'] == 'ghostwriter' else 'mirror' parts.append(f'

{"New language added" if mode == "ghost" else "Edited, not rewritten"}. {escape(a["assistance_note"])}

') active = s['changes'] - s['changes_restored'] parts.append(f'

{int(active)} edit{"s" if active != 1 else ""} in effect · {int(s["sentences_untouched"])} of {int(s["sentences"])} sentences ' f'exactly yours · {int(s["source_words"])} → {int(s["result_words"])} words

') for action in result.get('guard_actions', []): parts.append(f'

{escape(action)}

') high = [w for w in a['meaning_warnings'] if w['severity'] != 'low'] if high: parts.append(f'

{len(high)} thing{"s" if len(high) != 1 else ""} to check below: this revision may change more than style.

') parts.append('
') for name, est in a['confidence'].items(): parts.append(f'
{escape(name.capitalize())}
{escape(est["level"])} ' f'{escape(est["means"])}
') parts.append('
') return ''.join(parts) def warnings(result: dict | None) -> str: if not result: return EMPTY items = result['analysis']['meaning_warnings'] out = ['

Did I change what you meant?

'] if not items: out.append('

No warning from the deterministic checks (numbers, dates, names, quotations, links, negation, scope and ' 'certainty words). They cannot see a subtle paraphrase, so a read-through is still yours to do.

') for w in items: out.append(f'

{escape(w["status"])} {escape(w["what"])}

') if w['original']: out.append(f'

Original {escape(w["original"])}

') if w['revised']: out.append(f'

Revision {escape(w["revised"])}

') if w['change_ids']: out.append(f'

To restore your wording, tick edit{"s" if len(w["change_ids"]) != 1 else ""} ' f'{", ".join(f"{i:02d}" for i in w["change_ids"])} in the ledger.

') out.append('
') audit = result.get('audit') if audit: out.append('

A model’s second reading model judgment

' '

This is another model call’s opinion, kept separate from the checks above. Each line quotes both texts exactly; ' f'{audit["unverified_dropped"]} line(s) that did not were dropped.

') for item in audit['items']: out.append(f'

{escape(item["status"])} “{escape(_short(item["original"], 140))}” → ' f'“{escape(_short(item["revised"], 140))}” {escape(item["note"])}

') elif result.get('audit_error'): out.append(f'

{escape(result["audit_error"])}

') out.append('
') return ''.join(out) def ledger(result: dict | None) -> str: if not result: return EMPTY changes = result['analysis']['changes'] if not changes: return '

No edits. The text came back exactly as you wrote it.

' out = ['

Categories describe the kind of difference each edit makes. They are read from the edit itself, ' 'not from the model’s account of why.

'] for c in changes: cls = 'restored' if c['restored'] else 'active' who = {'you': 'restored by you', 'guard': 'withheld by the meaning guard', 'protected text': 'withheld: protected text'}.get(c.get('restored_by') or '', '') out.append( f'
CHANGE {c["id"]:02d}{escape(c["category"])}' + (f'{escape(who)}' if who else '') + '
' f'

{escape(c["original"]) or "(nothing)"}' f'{escape(c["revised"]) or "(removed)"}

' f'

{escape(c["reason"])} · Voice impact: {c["voice_impact"]} · Meaning impact: {c["meaning_impact"]}

') out.append('
') return ''.join(out) def _legend(states: list[str]) -> str: seen = [s for s in STATE_CLASS if s in states] return '

' + ''.join(f'{escape(s)}{escape(STATE_HELP[s])}' for s in seen) + '

' def authorship(result: dict | None) -> str: if not result: return EMPTY prov = result['analysis']['provenance'] counts: dict[str, int] = {} for p in prov: counts[p['state']] = counts.get(p['state'], 0) + 1 tally = ', '.join(f'{n} {s}' for s, n in counts.items()) body = ' '.join(f'' f'{escape(p["text"])}{escape(p["state"])}' for p in prov) return (f'

Where did these words come from? {len(prov)} sentences: {escape(tally)}. ' 'This is about awareness, not contamination: added words are not worse words.

' f'{_legend(list(counts))}
{body}
') def voice(result: dict | None) -> str: if not result: return EMPTY a = result['analysis'] drift = a['voice_drift'] out = [f'

Voice drift against {escape(drift["reference"])}

' f'

{escape(drift["summary"])}

'] if drift['shifts']: out.append('') for s in drift['shifts']: out.append(f'') out.append('
HabitBeforeNowChange
{escape(s["label"])}{s["before"]:g}{s["after"]:g}{escape(s["change"])}
') out.append('

Authorial distance

How far this revision moved from your text, axis by axis. A navigational aid, not a verdict.

') for name, axis in a['authorial_distance'].items(): out.append(f'
{escape(name.capitalize())}
' f'{escape(axis["level"])}{escape(axis["how"])}
') out.append('
') if a['preserved_features']: out.append('

What I kept

') out.append('
') return ''.join(out) def plan_text(intent: dict | None) -> str: if not intent: return '' return ('

I think you want (' + escape(intent['basis']) + '; untick anything I got wrong):

') def notice_list(items: list[dict]) -> str: if not items: return '' return '' def data_link(obj: dict, filename: str, label: str) -> str: payload = base64.b64encode(json.dumps(obj, ensure_ascii=False, indent=2).encode('utf-8')).decode() return f'{escape(label)}' def voiceprint(vp: dict | None) -> str: if not vp: return ('

No Voiceprint yet. Add some of your own writing above and build one. Without it, HumanTouch protects the voice ' 'of whatever text you paste; with it, it can also notice drift from how you usually write.

') q = vp['sample_quality'] out = [f'

Your Voiceprint

Sample: {escape(q["rating"])}. {escape(q["advice"])}

'] if vp['tendencies']: out.append('

Your writing tends to

') out.append('

Dimensions

Descriptions, not grades. Observed is measured from your samples; inferred is a proxy built on ' 'those measurements; model judgment is a model’s reading that quoted your samples.

') labels = {'keep': 'you said: keep this', 'not_me': 'you said: that isn’t me', 'more': 'you said: more of this', 'less': 'you said: less of this', 'never_imitate': 'you said: never imitate this'} for d in vp['dimensions']: corrected = f'{escape(labels[d["correction"]])}' if d.get('correction') else '' evidence = ''.join(f'{escape(e)}' for e in d['evidence']) out.append(f'
{escape(d["name"].capitalize())}' f'{escape(d["basis"])}confidence: {escape(d["confidence"])}{corrected}
' f'

{escape(d["summary"])} {evidence}

') out.append('
') if vp['signature_patterns']: out.append('

Signature patterns

' + ''.join( f'{escape(p["text"])} ×{p["count"]}' for p in vp['signature_patterns']) + '

') if vp['stable_traits'] or vp['contextual_traits']: out.append(f'

Across contexts ({escape(", ".join(vp["contexts"]))})

Stable: {escape(", ".join(vp["stable_traits"]) or "none measured")}.
' f'Changes with context: {escape(", ".join(vp["contextual_traits"]) or "none measured")}.

') if vp['voice_notes']: out.append('

Your voice notes

') model = {'included': f'A model reading is included; {vp["unverified_dropped"]} claim(s) it could not tie to an exact quotation were dropped.', 'not requested': 'No model was used. Everything above is measured on this server.', 'failed': 'The model reading failed, so humor, abstraction and imagery are marked “not assessed” rather than guessed.'}[vp['model_read']] out.append(f'

{escape(model)}

Limitations and every measurement
{escape(json.dumps(vp["observed"], indent=2))}
') out.append(data_link(vp, 'humantouch-voiceprint.json', 'Download this Voiceprint (JSON)')) out.append('

The file holds derived measurements, your notes, and short quoted phrases from your samples. It does not hold the samples.

') return ''.join(out) def voice_indicator(vp: dict | None) -> str: if not vp: return '

No Voiceprint loaded. I’ll protect the voice of the text itself.

' q = vp['sample_quality'] return f'

Voiceprint active · {q["words"]:,} words sampled · {escape(q["rating"])}

' def comparison(cmp: dict | None) -> str: if not cmp: return '' out = ['
'] for title, items in (('Certainty differences', cmp['certainty']), ('Factual and content differences', cmp['facts'])): if items: out.append(f'

{title}

' + ''.join( f'

{escape(w["status"])} {escape(w["what"])}' + (f'
A: {escape(w["original"])}' if w['original'] else '') + (f'
B: {escape(w["revised"])}' if w['revised'] else '') + '

' for w in items)) out.append(f'

{escape(cmp["note"])}

') return ''.join(out) def demo(generic: dict, touched: dict, source: str) -> str: def column(title: str, r: dict) -> str: a = r['analysis'] s = a['stats'] medium_up = sum(w['severity'] != 'low' for w in a['meaning_warnings']) rows = [('Sentences left exactly as written', f'{int(s["sentences_untouched"])} of {int(s["sentences"])}'), ('Share of the original’s words edited', f'{s["edit_ratio"]:.0%}'), ('Meaning warnings to check', str(medium_up)), ('Habits that drifted', str(len(a['voice_drift']['shifts']))), ('Sentences with no counterpart', str(int(s['ai_added_sentences']))), ('Length', f'{int(s["source_words"])} → {int(s["result_words"])} words')] body = ' '.join(f'{escape(p["text"])}' for p in a['provenance']) table = ''.join(f'{escape(k)}{escape(v)}' for k, v in rows) return (f'

{escape(title)}

{body}
{table}
' f'

{escape(a["voice_drift"]["summary"])}

') states = [p['state'] for r in (generic, touched) for p in r['analysis']['provenance']] return ('

Both columns were produced just now by the same model from the same text and the same request. ' 'Only the instructions around the model differ. The numbers are measurements of these two outputs, so they will vary from run to run.

' f'{_legend(states)}
{column("A conventional rewrite prompt", generic)}{column("HumanTouch", touched)}
') def cowrite_map(sentences: list[dict]) -> str: if not sentences: return '' body = ' '.join(f'{escape(text)}{escape(label)}' for text, label, c in ((s['text'], s['state'], 'p-added' if s['state'] == 'AI-added' else 'p-light' if 'edited' in s['state'] else 'p-original') for s in sentences)) return f'
{body}
' __all__ = ['HEADER', 'FOOTER', 'STRENGTH_LABELS']