blog: calibration v8 — AI phrasing blacklist, STEP8 6-step rewrite, Flexoptix author identity

- STRICTLY FORBIDDEN section: comprehensive AI phrasing blacklist (leverage, utilize,
  Furthermore, robust, seamless, delve into, in conclusion, etc.)
- STEP8 rewritten into 6 structured steps: hunt AI words, break rhythm, add human element,
  fix label formats, structural cleanup, ensure Flexoptix identity
- Banned sentence structures added (parallel triplets, same-length paragraphs)
- STEP6 author identity: reader should know this came from Flexoptix
- Version bump to 0.3.0
This commit is contained in:
Rene Fichtmueller 2026-04-01 00:43:38 +02:00
parent 52a04129e2
commit 580df8be01
4 changed files with 152 additions and 69 deletions

View File

@ -69,7 +69,7 @@ app.get("/", (_req, res) => {
app.get("/api", (_req, res) => {
res.json({
name: "Transceiver Intelligence Platform",
version: "0.2.6",
version: "0.3.0",
endpoints: [
"GET /api/transceivers?q=&form_factor=&speed=&category=&fiber_type=&wdm_type=&coherent=",
"GET /api/transceivers/:id",

View File

@ -42,9 +42,39 @@ VOICE:
- Occasionally blunt or sarcastic
- Prioritize clarity over completeness
STRICTLY FORBIDDEN:
STRICTLY FORBIDDEN AI PHRASING BLACKLIST (any of these = rewrite):
BANNED WORDS & PHRASES (AI fingerprints never use):
- "leverage", "optimize", "enhance", "plays a key role", "unlock", "empower"
- "In today's fast-paced world", "In the ever-evolving landscape", "it goes without saying"
- "it is worth noting", "it is important to note", "it should be noted"
- "that being said", "with that in mind", "at the end of the day"
- "delve into", "dive into", "explore", "unpack", "shed light on"
- "game-changer", "game-changing", "cutting-edge", "state-of-the-art", "industry-leading"
- "robust", "seamless", "scalable", "holistic", "comprehensive" (as empty adjectives)
- "it is crucial to", "it is essential to", "it is vital to"
- "in conclusion", "to summarize", "in summary", "to wrap up"
- "Furthermore", "Additionally", "Moreover", "Consequently", "Subsequently"
- "This is why X is not optional, but part of the baseline operating model" McKinsey speak
- "X rarely comes from a single obvious source" vague academic hedge
- "The discussion around X is often framed as" consulting opening
- "In practice, things tend to behave differently" too soft, say HOW they behave
- "a testament to", "a reflection of", "underscores the importance of"
- "revolutionary", "industry-leading", "next-generation", "world-class"
- "streamline", "streamlined", "best-in-class", "cutting edge"
- "nuanced", "multifaceted", "ecosystem" (when used vaguely)
- "paradigm", "synergy", "utilize" (say "use")
BANNED SENTENCE STRUCTURES (AI patterns):
- Perfectly parallel sentences: "X does A. Y does B. Z does C." vary the rhythm
- Every paragraph same length break it
- Sentences starting with "This" three times in a row AI hallmark
- Ending a section with a 3-4 word summary sentence that restates what was just said
- "Both X and Y have their place" wishy-washy non-conclusion
- "Ultimately, the decision depends on..." without saying what it depends on specifically
BANNED STRUCTURAL PATTERNS:
- "In today's fast-paced world" or ANY generic intro
- "leverage", "optimize", "enhance", "plays a key role"
- Empty bullet lists without context
- Neutral non-advice ("it depends on your requirements")
- Textbook explanations of basic concepts
@ -332,33 +362,66 @@ Article:
// STEP 8: KILL AI TONE
// ═══════════════════════════════════════════════════════
export const STEP8_KILL_AI_TONE = `Rewrite this article to remove ALL signs of AI-generated text.
export const STEP8_KILL_AI_TONE = `Your task: make this article sound like it was written by a human engineer who has actual opinions — not by a language model trying to be balanced and comprehensive.
REMOVE:
- Overly perfect sentence structures
- Repetitive paragraph patterns (same opening, same length)
- Generic transition phrases ("Furthermore", "Additionally", "It's worth noting")
- Lists that all follow identical format
- Perfect grammar everywhere add occasional conversational shortcuts
- Phrases like "it is important to note", "one should consider"
- Any section that ends with a tidy 4-item bullet list
- Perfectly symmetrical sections (same length = AI fingerprint)
- ALL markdown headers: ##, ###, ####, **Bold Section Title:** strip every single one. Write plain text only.
- Repeated explanations: if cleaning, polarity, or power is in two sections, merge them into the first occurrence and remove the second.
- "Cause:" / "Fix:" / "Example:" labels these are documentation format, not blog format. Integrate into prose.
BAD: "**Cause:** Mismatched firmware versions. **Fix:** Validate compatibility before deployment."
GOOD: "Firmware mismatches are rarely obvious. In one deployment, optics initialized cleanly but started flapping under load — the issue turned out to be a version mismatch between switch and transceiver firmware that only surfaced under realistic traffic."
- Repeated MMFSMF transitions: if the cabling change is explained more than once, merge into one place.
- "fraught with hidden risks" or similar fear-selling language replace with "introduces additional operational considerations"
- "When Not to Use" as a bullet list integrate into prose: "In smaller environments or legacy MMF deployments, the overhead of validation and migration can outweigh the cost advantage."
- "Example:" as a standalone label before a quote weave the example into the surrounding paragraph naturally.
STEP 1 HUNT AND DESTROY AI WORDS (scan every sentence, replace or delete):
These words are AI fingerprints. Any of them = rewrite that sentence.
"leverage" use "use"
"utilize" use "use"
"Furthermore", "Additionally", "Moreover" delete the word, rewrite transition naturally or cut
"It is worth noting", "It is important to note", "it should be noted" delete entirely, just say the thing
"delve into", "dive into", "explore" skip the preamble, start doing it
"robust" as empty adjective name what makes it robust, or delete
"seamless" delete, nothing is seamless
"holistic", "comprehensive" as empty adjectives delete
"that being said", "with that in mind", "at the end of the day" delete
"in conclusion", "to summarize", "in summary" delete, article already said it
"a testament to", "underscores the importance of", "a reflection of" rewrite directly
"nuanced", "multifaceted" say what you actually mean
"streamline", "streamlined" say what changes specifically
"paradigm" delete or say "approach"
"synergy" delete always
"it is crucial to", "it is essential to", "it is vital to" just say the thing without the preamble
"This is why X is not optional, but part of the baseline operating model" say "X is required. Period."
"In practice, things tend to behave differently" say HOW they behave differently, with an example
"The discussion is often framed as X versus Y" skip framing, start with the actual point
"Both X and Y have their place" take a position or cut the sentence
"Ultimately" as sentence opener delete or rephrase
REPLACE WITH:
- Natural, slightly imperfect flow
- Varied sentence lengths (some very short, some longer)
- Conversational asides ("Look, ...", "Here's the thing:", "Don't get me started on...")
- Direct address ("You know this is true if...")
- Specific instead of generic ("the Nexus 93180 in rack 14" not "your network switch")
STEP 2 BREAK PERFECT AI RHYTHM:
AI writes in perfectly even waves. Humans don't. Fix it:
After 3 same-length sentences: add ONE very short one. "It usually doesn't." or "That's the problem."
After a long technical paragraph: one direct opinion sentence. "Most teams don't catch this until it's too late."
Vary paragraph length some 1 sentence, some 4. Never all the same.
If every paragraph starts with "The" or "In" vary the opening words
STEP 3 ADD ONE HUMAN ELEMENT PER ARTICLE:
Choose ONE of these and add it naturally:
A conversational aside: "Look, nobody is going to tell you this in a sales call, but..."
A direct address: "If you've been on a pager call at 2AM for a dirty connector, you know exactly what I mean."
A blunt Flexoptix statement: "We sell compatible optics. We've also seen what happens when teams skip validation. The optics aren't the problem."
An admission: "There's no clean answer here. The right choice depends on whether you've done the work upfront."
STEP 4 FIX LABEL FORMATS:
"Cause:" / "Fix:" / "Example:" as labels integrate into prose narrative
BAD: "Cause: Firmware mismatch. Fix: Validate before deployment."
GOOD: "In one deployment, links came up cleanly but started flapping under load. The root cause was a firmware version gap between switch and transceiver — something that only surfaced under real traffic. Aligning firmware across both platforms fixed it."
"When Not to Use" as bullet list one flowing paragraph
"BUY / WAIT / SKIP" sections delete, say it as one direct sentence instead
STEP 5 STRUCTURAL CLEANUP:
ALL markdown headers: ##, ###, #### remove, plain text only
Repeated topics (cleaning in two sections, MMF/SMF twice) merge into first occurrence, delete second
"fraught with" replace with specific description of what happens
Sentences starting "This" three times in a row vary the opener
ALL markdown headers: ##, ###, ####, **Bold Section Title:** strip every single one
STEP 6 ENSURE FLEXOPTIX IS RECOGNIZABLE AS AUTHOR:
The reader should know this came from Flexoptix not a generic tech blog
If Flexoptix appears 0 times in the article: add it once naturally
Example: "This is something we see regularly at Flexoptix — teams that saved 70% on optics and spent twice that on troubleshooting because they skipped the validation step."
The author sells optics. They have an opinion. They've seen what fails. Show that.
One sentence of Flexoptix perspective is enough don't make it an ad, just make it human
PROSE STYLE OPTION (use when article currently feels too structured/sectioned):
If the article has many headers and bullet points and reads like a slide deck, consider

View File

@ -14,7 +14,7 @@ healthRouter.get("/", async (_req: Request, res: Response) => {
res.json({
success: true,
status: "healthy",
version: "0.2.6",
version: "0.3.0",
uptime: process.uptime(),
database: {
connected: true,

View File

@ -21,10 +21,10 @@
}
blogPipelineRunning = true;
var blogList = document.getElementById('blog-list');
if (blogList) {
blogList.innerHTML =
'<div style="background:linear-gradient(135deg,#1a1a1a,#2a2a2a);color:white;padding:2rem;border-radius:12px;text-align:center">' +
var pipelineEl = document.getElementById('blog-pipeline-status');
if (pipelineEl) {
pipelineEl.innerHTML =
'<div style="background:linear-gradient(135deg,#1a1a1a,#2a2a2a);color:white;padding:2rem;border-radius:12px;text-align:center;margin-bottom:1rem">' +
'<div style="font-size:1.4rem;font-weight:700;margin-bottom:1rem">Generating Blog with AI...</div>' +
'<div id="bp-status" style="font-size:1rem;color:#FF8100;margin-bottom:0.5rem">Starting 10-step Flexoptix Style pipeline...</div>' +
'<div id="bp-step" style="font-size:0.85rem;color:#aaa">Connecting to LLM (qwen2.5:14b)</div>' +
@ -63,15 +63,36 @@
function pollPipeline(id, attempt) {
if (attempt > 80) {
blogPipelineRunning = false;
var pipelineEl = document.getElementById('blog-pipeline-status');
if (pipelineEl) pipelineEl.innerHTML = '';
if (typeof showToast === 'function') showToast('Timeout', 'Pipeline took too long. Check the blog list.');
if (typeof loadBlogDrafts === 'function') loadBlogDrafts();
return;
}
// Poll progress endpoint (fast) + blog status endpoint (to detect completion)
setTimeout(function() {
fetch((API || '') + '/api/blog/' + id).then(function(r) { return r.json(); }).then(function(data) {
// 1) Fetch real-time progress from server
fetch((API || '') + '/api/blog/' + id + '/progress')
.then(function(r) { return r.json(); })
.then(function(prog) {
if (prog.running) {
var bar = document.getElementById('bp-bar');
var pct = document.getElementById('bp-pct');
var status = document.getElementById('bp-status');
var step = document.getElementById('bp-step');
if (bar) bar.style.width = prog.pct + '%';
if (pct) pct.textContent = prog.pct + '%';
if (status) status.textContent = prog.label || ('Step ' + prog.step + '/10');
if (step) step.textContent = 'Running on qwen2.5:14b via Ollama...';
}
}).catch(function() {});
// 2) Fetch blog draft to detect pipeline completion
fetch((API || '') + '/api/blog/' + id)
.then(function(r) { return r.json(); })
.then(function(data) {
var d = data.draft || data;
var gen = d.generated_by || '';
var steps = d.pipeline_steps_completed || 0;
var done = gen && gen !== 'tip-blog-engine-template' && gen.length > 0;
if (done) {
@ -82,29 +103,21 @@
var step = document.getElementById('bp-step');
if (bar) bar.style.width = '100%';
if (pct) pct.textContent = '100%';
if (status) { status.textContent = 'Blog generated! ' + (d.word_count || '?') + ' words'; status.style.color = '#2d6a4f'; }
if (step) step.textContent = 'Generated by: ' + gen;
if (status) { status.textContent = '✓ Blog fertig! ' + (d.word_count || '?') + ' Wörter'; status.style.color = '#2d6a4f'; }
if (step) step.textContent = 'Engine: ' + gen;
blogPipelineRunning = false;
if (typeof showToast === 'function') showToast('Blog Ready!', (d.title || 'Article') + ' — ' + (d.word_count || '?') + ' words');
setTimeout(function() {
var pipelineEl = document.getElementById('blog-pipeline-status');
if (pipelineEl) pipelineEl.innerHTML = '';
if (typeof loadBlogDrafts === 'function') loadBlogDrafts();
if (typeof viewBlogDraft === 'function') viewBlogDraft(id);
}, 2000);
} else {
// Still processing
var pctVal = Math.min(95, steps * 10 + 5);
var bar = document.getElementById('bp-bar');
var pct = document.getElementById('bp-pct');
var status = document.getElementById('bp-status');
var step = document.getElementById('bp-step');
if (bar) bar.style.width = pctVal + '%';
if (pct) pct.textContent = pctVal + '%';
if (status) status.textContent = 'Step ' + steps + '/10';
if (step && steps > 0 && steps <= 10) step.textContent = STEP_NAMES[steps - 1] || 'Processing...';
pollPipeline(id, attempt + 1);
}
}).catch(function() { pollPipeline(id, attempt + 1); });
}, 15000);
}, 8000); // Poll every 8s instead of 15s for snappier UI
}
// Hot topics loader
@ -149,6 +162,13 @@
}
})();
// Called via data attributes to avoid quote-escaping issues in onclick
window.blogDeleteClick = function(el) {
var id = el.getAttribute('data-blog-id');
var title = el.getAttribute('data-blog-title');
if (id) window.deleteBlogDraft(id, title);
};
// Delete a single blog draft
window.deleteBlogDraft = function(id, title) {
if (!confirm('Delete "' + title + '"?')) return;