Skip to main content

max / makenotwork

server: remove completed exorcise plan docs The three exorcise plans (comments, strings, templates) were working docs for the AI-tells cleanup pass; that work has landed and the plans aren't useful as historical artifacts.
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-24 21:06 UTC
Commit: 1dcc23bdf8979005df19b21907b5d976ebd3902c
Parent: d7530d5
3 files changed, +0 insertions, -549 deletions
@@ -1,141 +0,0 @@
1 - # Exorcise Comments — Inventory
2 -
3 - Inventory of Rust comment density across `MNW/server/src/` and shared crates, to size `/exorcise` sub-batches. Inventory only — no edits.
4 -
5 - Counting method:
6 - - doc comments: `rg '^\s*///|^\s*//!'`
7 - - inline comments: `rg '^\s*//[^/!]'` minus TODO/FIXME lines (those stay)
8 -
9 - ## Grand Totals
10 -
11 - | Scope | Files | Doc lines | Inline lines |
12 - |---|---|---|---|
13 - | Server top-level files (9) | 9 | 391 | 196 |
14 - | Server subdirs | 254 | 4,367 | 2,266 |
15 - | Server total | 263 | 4,758 | 2,462 |
16 - | Shared crates | 33 | 1,327 | 635 |
17 - | **Combined** | **296** | **6,085** | **3,097** |
18 -
19 - Total comment lines surveyed: ~9,182.
20 -
21 - Notes:
22 - - `git_issues/` does not exist in this tree — listed as N/A.
23 - - `templates.rs` does not exist; there is a `templates/` directory (6 files) — inventoried under that name.
24 - - `tauri-updater-ui` has no `src/` (JS-only shipping asset) — listed as N/A.
25 -
26 - ## Server Modules
27 -
28 - ### `payments/`
29 -
30 - High AI-tell risk per task brief (past LLM-assisted edits).
31 -
32 - - Files: 5 (`mod.rs`, `checkout.rs`, `checkout_metadata.rs`, `connect.rs`, `webhooks.rs`)
33 - - Doc lines: 131
34 - - Inline: 30
35 - - Judgment: **small batch** (single pass). Low raw count but flagged for scrutiny — read carefully even though counts are modest.
36 -
37 - ### `routes/`
38 -
39 - - Files: 140
40 - - Doc lines: 1,592
41 - - Inline: 1,582
42 - - Judgment: **split into 3–4 sub-batches**. Largest surface in the codebase by file count and inline density.
43 -
44 - ### `db/`
45 -
46 - - Files: 91
47 - - Doc lines: 2,075
48 - - Inline: 337
49 - - Judgment: **split into 2–3**. Doc-comment heavy (highest absolute doc count anywhere); inline is lighter than routes.
50 -
51 - ### Top-level files
52 -
53 - | File | Lines | Doc | Inline |
54 - |---|---|---|---|
55 - | `lib.rs` | 288 | 23 | 6 |
56 - | `config.rs` | 899 | 91 | 52 |
57 - | `error.rs` | 459 | 20 | 16 |
58 - | `auth.rs` | 666 | 65 | 16 |
59 - | `storage.rs` | 860 | 65 | 14 |
60 - | `templates/` (dir, 6 files) | — | 405 | 138 |
61 - | `synckit_auth.rs` | 311 | 15 | 9 |
62 - | `build_runner.rs` | 700 | 34 | 27 |
63 - | `license_templates.rs` | 489 | 13 | 8 |
64 -
65 - - Judgment: **one batch for all top-level `.rs` files** (~330 doc + 117 inline), then **`templates/` as its own small batch** (405 doc + 138 inline — surprisingly dense for a 6-file dir).
66 -
67 - ### `git/`
68 -
69 - - Files: 4 (`mod.rs`, `history.rs`, `objects.rs`, `refs.rs`)
70 - - Doc lines: 47
71 - - Inline: 46
72 - - Judgment: **small batch**.
73 -
74 - ### `git_issues/`
75 -
76 - - N/A — directory does not exist under `MNW/server/src/`.
77 -
78 - ### `validation/`
79 -
80 - - Files: 5
81 - - Doc lines: 73
82 - - Inline: 80
83 - - Judgment: **small batch**.
84 -
85 - ### `import/`
86 -
87 - - Files: 3
88 - - Doc lines: 44
89 - - Inline: 53
90 - - Judgment: **small batch**.
91 -
92 - ## Shared Crates
93 -
94 - ### `docengine`
95 -
96 - - Files: 15
97 - - Doc lines: 261
98 - - Inline: 190
99 - - Judgment: **medium batch** (single pass).
100 -
101 - ### `tagtree`
102 -
103 - - Files: 1
104 - - Doc lines: 378
105 - - Inline: 148
106 - - Judgment: **medium batch**. Single file but very doc-heavy — likely deliberate library prose; review with care.
107 -
108 - ### `synckit-client`
109 -
110 - - Files: 15
111 - - Doc lines: 602
112 - - Inline: 285
113 - - Judgment: **split into 2**. Highest doc-line total of any shared crate.
114 -
115 - ### `theme-common`
116 -
117 - - Files: 1
118 - - Doc lines: 54
119 - - Inline: 11
120 - - Judgment: **tiny batch**.
121 -
122 - ### `s3-storage`
123 -
124 - - Files: 1
125 - - Doc lines: 32
126 - - Inline: 1
127 - - Judgment: **tiny batch**.
128 -
129 - ### `tauri-updater-ui`
130 -
131 - - N/A — no Rust `src/` (JS asset crate: `updater.js` + `docs/`).
132 -
133 - ## Recommended Batch Ordering
134 -
135 - 1. `payments/` — small but high AI-tell risk, do first.
136 - 2. `routes/` — split into 3–4 (e.g., by sub-area).
137 - 3. `db/` — split into 2–3.
138 - 4. `synckit-client` — split into 2.
139 - 5. Server top-level files (one batch) + `templates/` (one batch).
140 - 6. `docengine`, `tagtree` — one batch each.
141 - 7. Mop-up: `git/`, `validation/`, `import/`, `theme-common`, `s3-storage`.
@@ -1,207 +0,0 @@
1 - # Inventory: User-Facing Prose String Literals (Rust)
2 -
3 - ## Methodology
4 -
5 - Ripgrep sweep over `MNW/server/src/` and `MNW/shared/*/src/`, excluding `tests/` directories and any line falling inside a `#[cfg(test)]` module (filter: Python script that pre-computes brace-balanced ranges per file). Goal: surface runtime user-facing prose where AI-tell tone (em-dashes, hedge openers, false contrasts, padding adverbs, "seamless/robust/leverage", checkmark/emoji, etc.) may have leaked in. This is an inventory only; no strings were edited.
6 -
7 - Four categories (plus two derived sub-cuts: `write!(f,...)` for Display body prose, and `impl Display for ...` block headers as a navigation index):
8 -
9 - 1. Flash / toast helpers (`hx_toast` is the canonical helper; no `flash!` macro exists)
10 - 2. `thiserror` `#[error("...")]` annotations
11 - 3. Email / notification builders (file path filtered to `email/` and `notification` files; raw match contained ~183 hits dominated by URL-format helpers in `synckit-client` and `docengine` which were excluded as non-prose)
12 - 4. Hardcoded prose: capital-leading, 40+ chars, ending in period
13 -
14 - ## Grand Totals (post-filter, non-test only)
15 -
16 - | Category | Total hits | Shown |
17 - |---|---:|---:|
18 - | 1. Flash/Toast (`hx_toast`) | 22 | 22 |
19 - | 2. `#[error("...")]` (thiserror) | 40 | 30 |
20 - | 3. Email/notification `format!` builders (email/notification paths only) | 72 | 30 |
21 - | 4. Long prose literals (≥40 chars, sentence-shaped) | 118 | 30 |
22 - | (Aux A) `write!(f, "...")` Display prose (≥20 chars) | 9 | 9 |
23 - | (Aux B) `impl Display for ...` blocks (index) | 15 | 15 |
24 -
25 - **Top 3 files by combined user-facing prose density:**
26 - 1. `server/src/email/templates/notifications.rs` — 29 hits (every email body)
27 - 2. `server/src/error.rs` — 18 hits (central `#[error]` catalog)
28 - 3. `server/src/email/tokens.rs` — 17 hits (unsubscribe action copy)
29 -
30 - Other notable hotspots:
31 - - `server/src/routes/pages/email_actions/account.rs` — 10 prose unsubscribe confirmations
32 - - `server/src/db/creator_tiers.rs` — 11 quota/tier-upsell prose strings
33 - - `server/src/routes/storage/{images,uploads,versions,media}.rs` — repeated copy-paste of "Upload not found. Please try uploading again." and "Could not determine file size. Please try uploading again." (consolidation candidate)
34 - - `shared/synckit-client/src/error.rs` — em-dash usage in error variants ("Encryption not initialized — call setup_encryption first", "Token expired — re-authenticate to continue syncing") — classic AI tell
35 -
36 - ## 1. Flash / Toast (22 hits)
37 -
38 - - `server/src/helpers.rs:142` — `([("HX-Trigger", hx_toast(message, toast_type))], axum::response::Html(String::new()))`
39 - - `server/src/helpers.rs:145` — `pub fn hx_toast(message: &str, toast_type: &str) -> HeaderValue {`
40 - - `server/src/helpers.rs:154` — `tracing::warn!(message, error = %e, "hx_toast produced invalid header value");`
41 - - `server/src/routes/api/license_keys.rs:18` — `helpers::{self, hx_toast, is_htmx_request},`
42 - - `server/src/routes/api/license_keys.rs:461` — `[("HX-Trigger", hx_toast("License key revoked", "success"))],`
43 - - `server/src/routes/api/ssh_keys.rs:12` — `use crate::helpers::{hx_toast, is_htmx_request};`
44 - - `server/src/routes/api/ssh_keys.rs:109` — `[("HX-Trigger", hx_toast("SSH key added", "success"))],`
45 - - `server/src/routes/api/ssh_keys.rs:149` — `[("HX-Trigger", hx_toast("SSH key removed", "success"))],`
46 - - `server/src/routes/api/passkeys.rs:16` — `helpers::hx_toast,`
47 - - `server/src/routes/api/passkeys.rs:128` — `[("HX-Trigger", hx_toast("Passkey registered", "success"))],`
48 - - `server/src/routes/api/passkeys.rs:182` — `[("HX-Trigger", hx_toast("Passkey renamed", "success"))],`
49 - - `server/src/routes/api/passkeys.rs:216` — `[("HX-Trigger", hx_toast("Passkey deleted", "success"))],`
50 - - `server/src/routes/api/totp.rs:15` — `helpers::hx_toast,`
51 - - `server/src/routes/api/totp.rs:106` — `[("HX-Trigger", hx_toast("Two-factor authentication enabled", "success"))],`
52 - - `server/src/routes/api/totp.rs:140` — `[("HX-Trigger", hx_toast("Two-factor authentication disabled", "success"))],`
53 - - `server/src/routes/api/totp.rs:187` — `[("HX-Trigger", hx_toast("Backup codes regenerated", "success"))],`
54 - - `server/src/routes/api/promo_codes.rs:15` — `helpers::{self, hx_toast, is_htmx_request}, `
55 - - `server/src/routes/api/promo_codes.rs:289` — `[("HX-Trigger", hx_toast("Promo code created", "success"))], `
56 - - `server/src/routes/api/promo_codes.rs:372` — `[("HX-Trigger", hx_toast("Promo code deleted", "success"))], `
57 - - `server/src/routes/api/promo_codes.rs:472` — `[("HX-Trigger", hx_toast("Promo code updated", "success"))], `
58 - - `server/src/routes/api/promo_codes.rs:497` — `[("HX-Trigger", hx_toast(&format!("{count} expired code(s) deleted"), "success"))], `
59 - - `server/src/routes/api/promo_codes.rs:611` — `[("HX-Trigger", hx_toast("Item added to your library", "success"))], `
60 -
61 - > Note: no `flash!` macro, `set_flash`, or `add_flash` exists in the codebase. All transient user feedback flows through `hx_toast(message, type)` in `server/src/helpers.rs`, which emits an `HX-Trigger` header consumed by htmx.
62 -
63 - ## 2. `#[error("...")]` (thiserror) — top 30 of 40
64 -
65 - - `server/src/git/mod.rs:304` — `#[error("Invalid repository or owner name")]`
66 - - `server/src/git/mod.rs:306` — `#[error("Repository not found")]`
67 - - `server/src/git/mod.rs:308` — `#[error("Ref not found")]`
68 - - `server/src/git/mod.rs:310` — `#[error("Tree not found")]`
69 - - `server/src/git/mod.rs:312` — `#[error("Path not found")]`
70 - - `server/src/git/mod.rs:314` — `#[error("Git error: {0}")]`
71 - - `shared/synckit-client/src/error.rs:9` — `#[error("HTTP request failed: {0}")]`
72 - - `shared/synckit-client/src/error.rs:14` — `#[error("Server returned {status}: {message}")]`
73 - - `shared/synckit-client/src/error.rs:25` — `#[error("JSON serialization error: {0}")]`
74 - - `shared/synckit-client/src/error.rs:30` — `#[error("Encryption not initialized — call setup_encryption first")]`
75 - - `shared/synckit-client/src/error.rs:35` — `#[error("Wrong password or corrupted key envelope")]`
76 - - `shared/synckit-client/src/error.rs:39` — `#[error("Invalid key envelope: {0}")]`
77 - - `shared/synckit-client/src/error.rs:44` — `#[error("Encryption error: {0}")]`
78 - - `shared/synckit-client/src/error.rs:48` — `#[error("Base64 decode error: {0}")]`
79 - - `shared/synckit-client/src/error.rs:52` — `#[error("Not authenticated — call authenticate first")]`
80 - - `shared/synckit-client/src/error.rs:57` — `#[error("Token expired — re-authenticate to continue syncing")]`
81 - - `shared/synckit-client/src/error.rs:61` — `#[error("Internal error: {0}")]`
82 - - `shared/synckit-client/src/error.rs:66` — `#[error("Keychain error: {0}")]`
83 - - `server/src/mt_client.rs:15` — `#[error("MT unreachable: {0}")]`
84 - - `server/src/mt_client.rs:17` — `#[error("MT returned error status {status}: {body}")]`
85 - - `server/src/mt_client.rs:19` — `#[error("failed to deserialize MT response: {0}")]`
86 - - `server/src/config.rs:490` — `#[error("Invalid HOST address")]`
87 - - `server/src/config.rs:492` — `#[error("Invalid PORT number")]`
88 - - `server/src/config.rs:494` — `#[error("DATABASE_URL environment variable is required")]`
89 - - `server/src/config.rs:496` — `#[error("SIGNING_SECRET is required in production (HOST=0.0.0.0 or HTTPS HOST_URL detected). Set SIGNING_SECRET to a stable random string.")]`
90 - - `server/src/config.rs:498` — `#[error("SIGNING_SECRET must be at least 32 characters long")]`
91 - - `server/src/error.rs:18` — `#[error("Not found")]`
92 - - `server/src/error.rs:21` — `#[error("Unauthorized")]`
93 - - `server/src/error.rs:24` — `#[error("Forbidden")]`
94 - - `server/src/error.rs:27` — `#[error("Bad request: {0}")]`
95 -
96 - > Many of these (especially in `server/src/error.rs` and `shared/synckit-client/src/error.rs`) surface directly to end users via response bodies or sync-client toasts. The synckit em-dashes (lines 30, 52, 57) are the highest-priority AI-tell candidates.
97 -
98 - ## 3. Email / Notification `format!` builders — top 30 of 72
99 -
100 - - `server/src/email/templates/notifications.rs:19` — `let subject = format!("New sale: {}", item_title);`
101 - - `server/src/email/templates/notifications.rs:20` — `let body = format!(`
102 - - `server/src/email/templates/notifications.rs:47` — `let body = format!(`
103 - - `server/src/email/templates/notifications.rs:71` — `let subject = format!("{} -- from {}", subject, creator_name);`
104 - - `server/src/email/templates/notifications.rs:72` — `let body = format!(`
105 - - `server/src/email/templates/notifications.rs:99` — `let subject = format!("New release: {} by {}", item_title, creator_name);`
106 - - `server/src/email/templates/notifications.rs:100` — `let body = format!(`
107 - - `server/src/email/templates/notifications.rs:127` — `let subject = format!("New post: {} by {}", post_title, creator_name);`
108 - - `server/src/email/templates/notifications.rs:128` — `let body = format!(`
109 - - `server/src/email/templates/notifications.rs:153` — `let body = format!(`
110 - - `server/src/email/templates/notifications.rs:176` — `let body = format!(`
111 - - `server/src/email/templates/notifications.rs:203` — `let body = format!(`
112 - - `server/src/email/templates/notifications.rs:237` — `let body = format!(`
113 - - `server/src/email/templates/notifications.rs:265` — `let subject = format!("Content removed: {}", item_title);`
114 - - `server/src/email/templates/notifications.rs:266` — `let body = format!(`
115 - - `server/src/email/templates/notifications.rs:291` — `let subject = format!("Content restored: {}", item_title);`
116 - - `server/src/email/templates/notifications.rs:292` — `let body = format!(`
117 - - `server/src/email/templates/notifications.rs:312` — `let body = format!(`
118 - - `server/src/email/templates/notifications.rs:342` — `let body = format!(`
119 - - `server/src/email/templates/notifications.rs:379` — `let subject = format!("New issue on {}/{}: {}", repo_owner, repo_name, issue_title);`
120 - - `server/src/email/templates/notifications.rs:380` — `let body = format!(`
121 - - `server/src/email/templates/notifications.rs:430` — `let subject = format!("Re: New issue on {}/{}: {}", repo_owner, repo_name, issue_title);`
122 - - `server/src/email/templates/notifications.rs:431` — `let body = format!(`
123 - - `server/src/email/templates/notifications.rs:478` — `let subject = format!("{} tipped you {}", tipper_name, price);`
124 - - `server/src/email/templates/notifications.rs:480` — `Some(msg) => format!(`
125 - - `server/src/email/templates/notifications.rs:495` — `None => format!(`
126 - - `server/src/email/templates/notifications.rs:520` — `let subject = format!("{} is leaving Makenot.work — download your purchases", creator_name);`
127 - - `server/src/email/templates/notifications.rs:521` — `let body = format!(`
128 - - `server/src/email/templates/notifications.rs:557` — `let body = format!(`
129 - - `server/src/email/templates/auth.rs:15` — `let body = format!(`
130 -
131 - > Continuation lines for each `let body = format!(` invocation contain the actual prose; this index points at the call sites. `server/src/email/templates/notifications.rs` is the single biggest concentration of runtime-built prose in the codebase and should be the first exorcise target.
132 -
133 - ## 4. Hardcoded prose literals (capital-led, ≥40 chars, sentence-ending) — top 30 of 118
134 -
135 - - `server/src/email/templates/auth.rs:77` — `.map(|url| format!("Use this link to log in securely:\n\n{}\n\nThis link expires in 15 minutes.", url))`
136 - - `server/src/email/templates/auth.rs:78` — `.unwrap_or_else(|| "Your account will unlock automatically in 15 minutes.".to_string())`
137 - - `server/src/email/templates/monetization.rs:202` — `.map(|d| format!("You will retain your Fan+ benefits until {}.", d.format("%B %-d, %Y")))`
138 - - `server/src/main.rs:137` — `tracing::info!("S3 storage not configured. File uploads will be unavailable.");`
139 - - `server/src/main.rs:164` — `tracing::info!("Stripe not configured. Payments will be unavailable.");`
140 - - `server/src/routes/pages/sandbox.rs:133` — `Some("A sample project to explore the creator dashboard."),`
141 - - `server/src/routes/pages/sandbox.rs:154` — `Some("Edit this item to see how content management works."),`
142 - - `server/src/routes/pages/email_actions/password.rs:47` — `"If an account exists with that email, we've sent a password reset link.",`
143 - - `server/src/routes/pages/email_actions/password.rs:250` — `"This password has appeared in {} known data breach(es). Consider changing it.",`
144 - - `server/src/routes/auth.rs:126` — `"Account is locked. Try again in {} minute(s), or use the login link sent to your email.",`
145 - - `server/src/routes/auth.rs:164` — `"Too many failed attempts. Account locked for {} minutes. A login link has been sent to your email.",`
146 - - `server/src/routes/pages/email_actions/account.rs:80` — `message: "This deletion link has expired. Please request a new one from your account settings.".to_string(),`
147 - - `server/src/routes/pages/email_actions/account.rs:331` — `Ok("You have unfollowed this creator and will no longer receive their broadcasts."`
148 - - `server/src/routes/pages/email_actions/account.rs:336` — `Ok("You will no longer receive emails about new releases from creators you follow."`
149 - - `server/src/routes/pages/email_actions/account.rs:341` — `Ok("You will no longer receive email notifications when someone buys your content."`
150 - - `server/src/routes/pages/email_actions/account.rs:347` — `"You will no longer receive email notifications for new followers."`
151 - - `server/src/routes/pages/email_actions/account.rs:354` — `Ok("You will no longer receive email notifications for new device sign-ins."`
152 - - `server/src/routes/pages/email_actions/account.rs:359` — `Ok("You will no longer receive email notifications for issues on your repositories."`
153 - - `server/src/routes/pages/email_actions/account.rs:364` — `Ok("You will no longer receive platform status notifications.".to_string())`
154 - - `server/src/routes/pages/email_actions/account.rs:371` — `Ok("You have been unsubscribed from this mailing list.".to_string())`
155 - - `server/src/routes/pages/email_actions/account.rs:375` — `Ok("You will no longer receive email notifications for tips.".to_string())`
156 - - `server/src/db/custom_domains.rs:30` — `"You already have a custom domain configured. Remove it first to add a new one.".to_string(),`
157 - - `server/src/routes/git_issues/push_refs.rs:196` — `"Closed via commit ['{}'](/git/{}/{}/commit/{}) on '{}'.",`
158 - - `server/src/routes/git_issues/push_refs.rs:213` — `"Reopened via commit ['{}'](/git/{}/{}/commit/{}) on '{}'.",`
159 - - `server/src/routes/git_issues/push_refs.rs:225` — `"Referenced in commit ['{}'](/git/{}/{}/commit/{}) on '{}'.",`
160 - - `server/src/routes/api/reports.rs:81` — `return Err(AppError::Validation("Report limit reached. Please try again later.".to_string()));`
161 - - `server/src/db/items/bulk.rs:235` — `"Too many copies with similar names. Rename an existing copy first.".to_string(),`
162 - - `server/src/routes/storage/images.rs:140` — `"Upload not found. Please try uploading again.".to_string(),`
163 - - `server/src/routes/storage/images.rs:146` — `AppError::BadRequest("Could not determine file size. Please try uploading again.".to_string())`
164 - - `server/src/routes/storage/images.rs:310` — `"Upload not found. Please try uploading again.".to_string(),`
165 -
166 - > The `email_actions/account.rs` cluster (lines 331–375) is 11 near-identical unsubscribe confirmations — strong candidate for a shared helper. The four `storage/*.rs` files repeat "Upload not found. Please try uploading again." and "Could not determine file size. Please try uploading again." verbatim — consolidation opportunity.
167 -
168 - ## Aux A. `write!(f, "...")` Display body prose (9 hits, all shown)
169 -
170 - - `shared/docengine/src/filters.rs:93` — `Self::TypeError { filter, message } => write!(f, "filter '{filter}': {message}"),`
171 - - `shared/docengine/src/filters.rs:95` — `write!(f, "filter '{filter}' expects {expected} arg(s), got {got}")`
172 - - `shared/docengine/src/filters.rs:98` — `write!(f, "filter '{filter}' arg {position}: expected {expected}")`
173 - - `shared/docengine/src/filters.rs:100` — `Self::DomainError { filter, message } => write!(f, "filter '{filter}': {message}"),`
174 - - `shared/docengine/src/filters.rs:326` — `Self::EmptyExpression => write!(f, "empty expression inside {{{{ }}}}"),`
175 - - `shared/docengine/src/filters.rs:328` — `Self::MissingFilterName => write!(f, "missing filter name after '|'"),`
176 - - `shared/docengine/src/filters.rs:329` — `Self::InvalidArg(s) => write!(f, "invalid filter argument: {s:?}"),`
177 - - `shared/docengine/src/assumptions.rs:41` — `Self::Parse(e) => write!(f, "TOML parse error: {e}"),`
178 - - `shared/docengine/src/assumptions.rs:50` — `write!(f, "unresolved placeholders: {}", unresolved.join(", "))`
179 -
180 - ## Aux B. `impl Display for ...` headers (index, 15 hits)
181 -
182 - - `server/src/email/tokens.rs:21` — `impl std::fmt::Display for UnsubscribeAction {`
183 - - `shared/synckit-client/src/types.rs:23` — `impl fmt::Display for ChangeOp {`
184 - - `shared/docengine/src/filters.rs:90` — `impl fmt::Display for FilterError {`
185 - - `shared/docengine/src/filters.rs:323` — `impl fmt::Display for ParseError {`
186 - - `shared/docengine/src/assumptions.rs:37` — `impl fmt::Display for AssumptionsError {`
187 - - `shared/docengine/src/assumptions.rs:78` — `impl fmt::Display for LookupValue {`
188 - - `shared/tagtree/src/lib.rs:67` — `impl fmt::Display for TagError {`
189 - - `server/src/license_templates.rs:22` — `impl fmt::Display for LicensePreset {`
190 - - `server/src/db/analytics.rs:31` — `impl std::fmt::Display for TimeRange {`
191 - - `server/src/db/enums.rs:14` — `impl std::fmt::Display for $enum_name {`
192 - - `server/src/db/id_types.rs:50` — `impl fmt::Display for $name {`
193 - - `server/src/db/validated_types.rs:63` — `impl std::fmt::Display for $name {`
194 - - `server/src/db/validated_types.rs:184` — `impl std::fmt::Display for Email {`
195 - - `server/src/db/validated_types.rs:283` — `impl std::fmt::Display for Cents {`
196 - - `server/src/db/validated_types.rs:421` — `impl std::fmt::Display for PriceCents {`
197 -
198 - > Read the immediately-following `match` arms in each of these to audit Display body text.
199 -
200 - ## Recommended Exorcise Priority
201 -
202 - 1. `server/src/email/templates/notifications.rs` — highest reader exposure, most prose per file
203 - 2. `server/src/email/templates/auth.rs` and `monetization.rs` — auth/billing copy is high-stakes
204 - 3. `server/src/routes/pages/email_actions/account.rs` — duplicated unsubscribe prose, consolidate then exorcise
205 - 4. `shared/synckit-client/src/error.rs` — em-dashes in error messages
206 - 5. `server/src/db/creator_tiers.rs` — tier-upsell prose, business-critical tone
207 - 6. Storage upload error duplication across `routes/storage/{images,uploads,versions,media}.rs` and `routes/api/internal/uploads.rs` — consolidate before exorcising
@@ -1,201 +0,0 @@
1 - # Exorcise Templates Inventory
2 -
3 - This file inventories every `.html` template under `MNW/server/templates/` and tags each one for the upcoming `/exorcise` campaign. Categories are picked by a quick read plus grep of paragraph tags and natural-language sentences. **prose-heavy** files carry enough human-readable copy (paragraphs, descriptions, empty states, help text, flash text) that an exorcise pass has surface area to find LLM tells (em-dashes, hedge openers, false contrasts, padding adverbs, decorative emoji, overused vocab). **chrome-only** files are structural HTML/CSS/JS with only short button labels and form chrome — skippable. **mixed** files are mostly structural with a meaningful chunk of prose embedded (a settings page with one explanatory paragraph, an upload widget with help text).
4 -
5 - **Total: 181 files. 73 prose-heavy / 47 mixed / 61 chrome-only.**
6 -
7 - ## templates/ (root)
8 -
9 - - `_head_assets.html` — chrome-only: head assets, link/script tags.
10 - - `base.html` — chrome-only: layout skeleton with header/footer blocks.
11 - - `index.html` — chrome-only: trivial redirect/landing stub.
12 -
13 - ## dashboards/
14 -
15 - - `dashboards/admin-appeals.html` — chrome-only: admin table with appeal entries partial.
16 - - `dashboards/admin-metrics.html` — mixed: admin metrics tables with section descriptions and threshold notes.
17 - - `dashboards/admin-reports.html` — chrome-only: admin reports table.
18 - - `dashboards/admin-signups.html` — mixed: signup queue with reviewer guidance copy.
19 - - `dashboards/admin-uploads.html` — chrome-only: upload moderation table.
20 - - `dashboards/admin-users.html` — chrome-only: user admin table.
21 - - `dashboards/admin-waitlist.html` — chrome-only: waitlist table chrome.
22 - - `dashboards/dashboard-blog-editor.html` — chrome-only: markdown editor scaffold.
23 - - `dashboards/dashboard-delete-account.html` — prose-heavy: deletion warning copy, recovery window explainer.
24 - - `dashboards/dashboard-export.html` — prose-heavy: export descriptions for each data type.
25 - - `dashboards/dashboard-import.html` — prose-heavy: import guide, per-platform notes, coming-soon list.
26 - - `dashboards/dashboard-item.html` — chrome-only: tab shell for item dashboard.
27 - - `dashboards/dashboard-project.html` — chrome-only: tab shell for project dashboard.
28 - - `dashboards/dashboard-user.html` — prose-heavy: account-state banners (deactivated/paused/suspended) with explanatory copy.
29 -
30 - ## pages/
31 -
32 - - `pages/account-deleted.html` — prose-heavy: farewell copy.
33 - - `pages/audio_player.html` — mixed: player chrome with description and metadata blocks.
34 - - `pages/blog_post.html` — prose-heavy: blog post body rendered as long-form markdown.
35 - - `pages/buy.html` — mixed: checkout chrome with terms and disclosure copy.
36 - - `pages/cart.html` — prose-heavy: cart empty states, wishlist prompts, checkout copy.
37 - - `pages/changelog.html` — prose-heavy: changelog entries are pure prose.
38 - - `pages/collection.html` — mixed: collection page with description block.
39 - - `pages/confirm_delete.html` — prose-heavy: deletion confirmation warning copy.
40 - - `pages/creators.html` — prose-heavy: creator-pitch landing page, multiple paragraphs.
41 - - `pages/discover.html` — mixed: long template, mostly card chrome but with empty-state and section intro copy.
42 - - `pages/doc_index.html` — mixed: doc index page with intro paragraph.
43 - - `pages/doc.html` — prose-heavy: rendered documentation body.
44 - - `pages/email_result.html` — prose-heavy: short result message page.
45 - - `pages/error.html` — prose-heavy: error message body.
46 - - `pages/fan_plus.html` — prose-heavy: Fan Plus tier pitch and benefits.
47 - - `pages/feed.html` — mixed: feed listing with empty-state and intro copy.
48 - - `pages/forgot_password.html` — prose-heavy: password reset instructions.
49 - - `pages/git/blame.html` — chrome-only: blame table.
50 - - `pages/git/commit.html` — chrome-only: commit diff view.
51 - - `pages/git/commits.html` — chrome-only: commit list.
52 - - `pages/git/explore.html` — chrome-only: repo browse grid.
53 - - `pages/git/file_log.html` — chrome-only: file history table.
54 - - `pages/git/file.html` — chrome-only: file viewer chrome.
55 - - `pages/git/issue.html` — mixed: issue thread with reply-by-email instructions.
56 - - `pages/git/issues.html` — chrome-only: issue list table.
57 - - `pages/git/repo.html` — mixed: repo header with README placeholder and empty-state copy.
58 - - `pages/git/repos.html` — chrome-only: repo list.
59 - - `pages/git/settings.html` — mixed: settings form with field help text.
60 - - `pages/git/tree.html` — chrome-only: tree browser.
61 - - `pages/health.html` — mixed: probe results with summaries; mostly tabular but some explanatory text.
62 - - `pages/index.html` — prose-heavy: marketing landing page.
63 - - `pages/item.html` — prose-heavy: public item page with description and bundle/section copy.
64 - - `pages/library_audio.html` — mixed: audio library player with item metadata.
65 - - `pages/library_downloads.html` — mixed: downloads list with per-file help copy.
66 - - `pages/library_locked.html` — prose-heavy: locked-library explainer.
67 - - `pages/library_text.html` — mixed: text library viewer chrome with description.
68 - - `pages/library_video.html` — mixed: video library viewer.
69 - - `pages/library.html` — chrome-only: library tab shell.
70 - - `pages/login.html` — chrome-only: login form.
71 - - `pages/oauth_authorize.html` — mixed: OAuth consent screen with scope descriptions.
72 - - `pages/policy.html` — prose-heavy: content policy long-form text.
73 - - `pages/pricing.html` — prose-heavy: pricing page with tier descriptions and FAQ.
74 - - `pages/project_blog.html` — mixed: project blog index with intro copy.
75 - - `pages/project_paywall.html` — prose-heavy: paywall explainer with tier options.
76 - - `pages/project.html` — prose-heavy: public project page with description and section copy.
77 - - `pages/purchase.html` — prose-heavy: purchase flow with tier explainers and disclosures.
78 - - `pages/receipt.html` — mixed: receipt template with thank-you copy.
79 - - `pages/reset_password.html` — prose-heavy: reset password instructions and expiry messages.
80 - - `pages/sandbox.html` — chrome-only: developer sandbox.
81 - - `pages/stripe_disclaimer.html` — prose-heavy: Stripe flow explainer, paragraphs of policy.
82 - - `pages/tag_tree.html` — chrome-only: tag tree visualization.
83 - - `pages/team.html` — prose-heavy: team bios and founder narrative.
84 - - `pages/text_reader.html` — mixed: reader chrome with content body.
85 - - `pages/two_factor.html` — prose-heavy: 2FA instruction copy.
86 - - `pages/use_cases.html` — prose-heavy: use-case landing page, multiple pitches per medium.
87 - - `pages/user.html` — mixed: public profile with bio and item lists.
88 - - `pages/video_player.html` — mixed: video page with description blocks.
89 -
90 - ## partials/
91 -
92 - - `partials/_ui.html` — chrome-only: UI helper macros.
93 - - `partials/admin_appeal_entries.html` — chrome-only: admin table rows.
94 - - `partials/admin_nav.html` — chrome-only: admin nav links.
95 - - `partials/admin_report_entries.html` — chrome-only: admin table rows.
96 - - `partials/admin_upload_entries.html` — chrome-only: admin table rows.
97 - - `partials/admin_user_entries.html` — chrome-only: admin table rows.
98 - - `partials/admin_waitlist_entries.html` — chrome-only: admin table rows.
99 - - `partials/alert.html` — chrome-only: one-line alert macro.
100 - - `partials/discover_results.html` — mixed: card grid with empty-state and sort-label copy.
101 - - `partials/discussion_section.html` — chrome-only: discussion block scaffold.
102 - - `partials/error_fragment.html` — chrome-only: tiny error fragment.
103 - - `partials/export_content_ready.html` — chrome-only: HTMX swap fragment.
104 - - `partials/export_download.html` — chrome-only: download link fragment.
105 - - `partials/follow_button.html` — chrome-only: follow toggle.
106 - - `partials/form_status.html` — chrome-only: form status indicator.
107 - - `partials/git_nav.html` — chrome-only: git nav tabs.
108 - - `partials/insertion_list.html` — chrome-only: list builder UI.
109 - - `partials/item_analytics.html` — chrome-only: analytics charts and stat cards.
110 - - `partials/item_audio_upload.html` — chrome-only: audio upload widget.
111 - - `partials/item_edit_row.html` — chrome-only: editable row.
112 - - `partials/item_license_keys.html` — chrome-only: license key table.
113 - - `partials/item_text_editor.html` — mixed: markdown editor with help-text panel.
114 - - `partials/item_version_upload.html` — chrome-only: version upload widget.
115 - - `partials/library_status.html` — chrome-only: status one-liner.
116 - - `partials/link_row.html` — chrome-only: link row macro.
117 - - `partials/login_error.html` — chrome-only: tiny error swap.
118 - - `partials/onboarding_checklist.html` — mixed: checklist with per-step help text.
119 - - `partials/passkey_list.html` — mixed: passkey list with explanation paragraph.
120 - - `partials/paywall.html` — prose-heavy: paywall message with tier prompts (small but dense).
121 - - `partials/placement_list.html` — chrome-only: placement table.
122 - - `partials/promo_codes_list.html` — chrome-only: promo code table.
123 - - `partials/report_modal.html` — chrome-only: report modal form.
124 - - `partials/save_status.html` — chrome-only: save indicator.
125 - - `partials/share_link.html` — chrome-only: empty/trivial file.
126 - - `partials/site_header.html` — chrome-only: header nav.
127 - - `partials/slug_status.html` — chrome-only: slug availability indicator.
128 - - `partials/ssh_keys_list.html` — mixed: SSH key list with help text.
129 - - `partials/suspension_banner.html` — prose-heavy: suspension banner copy with appeal instructions.
130 - - `partials/tabs/buyer_contacts.html` — chrome-only: contacts table.
131 - - `partials/tabs/item_details.html` — prose-heavy: extensive form help text and section explainers.
132 - - `partials/tabs/item_embed.html` — prose-heavy: per-embed-format description copy.
133 - - `partials/tabs/item_files.html` — chrome-only: file row macro.
134 - - `partials/tabs/item_overview.html` — mixed: item overview with status copy.
135 - - `partials/tabs/item_pricing.html` — prose-heavy: pricing model explainers, license terms text.
136 - - `partials/tabs/item_sales.html` — mixed: sales table with refund-policy notes.
137 - - `partials/tabs/item_settings.html` — mixed: settings form with help text.
138 - - `partials/tabs/library_collections.html` — mixed: collections UI with empty-state copy.
139 - - `partials/tabs/library_communities.html` — mixed: community tab with intro copy.
140 - - `partials/tabs/library_contacts.html` — mixed: contacts tab with help text.
141 - - `partials/tabs/library_feed.html` — mixed: feed tab with empty-state copy.
142 - - `partials/tabs/library_purchases.html` — mixed: purchase history with note copy.
143 - - `partials/tabs/library_subscriptions.html` — chrome-only: subscriptions table.
144 - - `partials/tabs/library_wishlists.html` — mixed: wishlist with empty-state copy.
145 - - `partials/tabs/project_analytics.html` — chrome-only: analytics charts.
146 - - `partials/tabs/project_blog.html` — mixed: blog tab with intro copy.
147 - - `partials/tabs/project_code.html` — mixed: git/code panel with help text.
148 - - `partials/tabs/project_content.html` — prose-heavy: content tab with several empty-state and explainer paragraphs.
149 - - `partials/tabs/project_members.html` — mixed: member management with role descriptions.
150 - - `partials/tabs/project_monetization.html` — chrome-only: stub tab.
151 - - `partials/tabs/project_overview.html` — prose-heavy: onboarding-style overview with multiple help paragraphs.
152 - - `partials/tabs/project_promotions.html` — prose-heavy: promo code creation with rule explainers.
153 - - `partials/tabs/project_settings.html` — prose-heavy: settings form with extensive per-field help copy.
154 - - `partials/tabs/project_subscriptions.html` — mixed: subscription tab with explainer.
155 - - `partials/tabs/project_synckit.html` — prose-heavy: SyncKit explainer paragraphs.
156 - - `partials/tabs/user_account.html` — prose-heavy: account settings with help text per option.
157 - - `partials/tabs/user_analytics.html` — chrome-only: analytics charts.
158 - - `partials/tabs/user_creator.html` — prose-heavy: creator tier copy, trial guidance, founder pricing notes.
159 - - `partials/tabs/user_forums.html` — mixed: forum tab with intro copy.
160 - - `partials/tabs/user_media.html` — prose-heavy: media library with help text and empty states.
161 - - `partials/tabs/user_payments.html` — prose-heavy: payments tab with Stripe Connect onboarding copy and status messages.
162 - - `partials/tabs/user_profile.html` — prose-heavy: profile fields with per-field help text and RSS explainer.
163 - - `partials/tabs/user_projects.html` — mixed: projects tab with empty-state.
164 - - `partials/tabs/user_sessions.html` — mixed: session list with security note.
165 - - `partials/tabs/user_settings.html` — chrome-only: settings shell.
166 - - `partials/tabs/user_ssh_keys_tab.html` — mixed: SSH keys tab with help text.
167 - - `partials/tabs/user_ssh_keys.html` — mixed: SSH keys panel with help text.
168 - - `partials/tabs/user_support.html` — prose-heavy: support tab with contact and policy copy.
169 - - `partials/tabs/user_synckit.html` — prose-heavy: SyncKit explainer for users.
170 - - `partials/tag_follow_toggle.html` — chrome-only: toggle button.
171 - - `partials/tag_suggestions.html` — chrome-only: suggestion list.
172 - - `partials/tag.html` — chrome-only: tag macro.
173 - - `partials/tip_button.html` — chrome-only: tip button.
174 - - `partials/toast.html` — chrome-only: toast macro.
175 - - `partials/totp_setup.html` — prose-heavy: TOTP setup instructions.
176 - - `partials/totp_status.html` — prose-heavy: TOTP status messages with backup-code guidance.
177 - - `partials/transactions_table.html` — chrome-only: transaction table.
178 - - `partials/username_status.html` — chrome-only: username availability indicator.
179 -
180 - ## wizards/
181 -
182 - - `wizards/partials/step_nav.html` — chrome-only: prev/next buttons.
183 - - `wizards/steps/item/basics.html` — mixed: form fields with per-field help text.
184 - - `wizards/steps/item/content.html` — prose-heavy: upload step with extensive drop-zone and per-type instructions.
185 - - `wizards/steps/item/preview.html` — mixed: preview step with summary copy.
186 - - `wizards/steps/item/pricing.html` — mixed: pricing form with help text.
187 - - `wizards/steps/item/sections.html` — mixed: tabbed sections builder with help text.
188 - - `wizards/steps/item/type.html` — mixed: type chooser with descriptions.
189 - - `wizards/steps/join/account.html` — mixed: account form with intro copy.
190 - - `wizards/steps/join/complete.html` — prose-heavy: completion screen with branching welcome copy.
191 - - `wizards/steps/join/pitch.html` — prose-heavy: creator-application pitch instructions.
192 - - `wizards/steps/join/profile.html` — mixed: profile form with help text.
193 - - `wizards/steps/join/stripe.html` — prose-heavy: Stripe Connect onboarding explainer.
194 - - `wizards/steps/project/appearance.html` — mixed: appearance form with per-field help text.
195 - - `wizards/steps/project/basics.html` — mixed: basics form with help text.
196 - - `wizards/steps/project/first_content.html` — prose-heavy: first-content prompt with explainer.
197 - - `wizards/steps/project/monetization.html` — mixed: monetization form with tier descriptions.
198 - - `wizards/steps/project/preview.html` — mixed: preview step with summary copy.
199 - - `wizards/wizard_item.html` — chrome-only: wizard shell.
200 - - `wizards/wizard_join.html` — mixed: join wizard shell with intro copy.
201 - - `wizards/wizard_project.html` — mixed: project wizard shell with summary copy.