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 e1877672c0
commit 8b187a5dac
4 changed files with 152 additions and 69 deletions

View File

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

View File

@ -42,9 +42,39 @@ VOICE:
- Occasionally blunt or sarcastic - Occasionally blunt or sarcastic
- Prioritize clarity over completeness - 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 - "In today's fast-paced world" or ANY generic intro
- "leverage", "optimize", "enhance", "plays a key role"
- Empty bullet lists without context - Empty bullet lists without context
- Neutral non-advice ("it depends on your requirements") - Neutral non-advice ("it depends on your requirements")
- Textbook explanations of basic concepts - Textbook explanations of basic concepts
@ -332,33 +362,66 @@ Article:
// STEP 8: KILL AI TONE // 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: STEP 1 HUNT AND DESTROY AI WORDS (scan every sentence, replace or delete):
- Overly perfect sentence structures These words are AI fingerprints. Any of them = rewrite that sentence.
- Repetitive paragraph patterns (same opening, same length) "leverage" use "use"
- Generic transition phrases ("Furthermore", "Additionally", "It's worth noting") "utilize" use "use"
- Lists that all follow identical format "Furthermore", "Additionally", "Moreover" delete the word, rewrite transition naturally or cut
- Perfect grammar everywhere add occasional conversational shortcuts "It is worth noting", "It is important to note", "it should be noted" delete entirely, just say the thing
- Phrases like "it is important to note", "one should consider" "delve into", "dive into", "explore" skip the preamble, start doing it
- Any section that ends with a tidy 4-item bullet list "robust" as empty adjective name what makes it robust, or delete
- Perfectly symmetrical sections (same length = AI fingerprint) "seamless" delete, nothing is seamless
- ALL markdown headers: ##, ###, ####, **Bold Section Title:** strip every single one. Write plain text only. "holistic", "comprehensive" as empty adjectives delete
- Repeated explanations: if cleaning, polarity, or power is in two sections, merge them into the first occurrence and remove the second. "that being said", "with that in mind", "at the end of the day" delete
- "Cause:" / "Fix:" / "Example:" labels these are documentation format, not blog format. Integrate into prose. "in conclusion", "to summarize", "in summary" delete, article already said it
BAD: "**Cause:** Mismatched firmware versions. **Fix:** Validate compatibility before deployment." "a testament to", "underscores the importance of", "a reflection of" rewrite directly
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." "nuanced", "multifaceted" say what you actually mean
- Repeated MMFSMF transitions: if the cabling change is explained more than once, merge into one place. "streamline", "streamlined" say what changes specifically
- "fraught with hidden risks" or similar fear-selling language replace with "introduces additional operational considerations" "paradigm" delete or say "approach"
- "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." "synergy" delete always
- "Example:" as a standalone label before a quote weave the example into the surrounding paragraph naturally. "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: STEP 2 BREAK PERFECT AI RHYTHM:
- Natural, slightly imperfect flow AI writes in perfectly even waves. Humans don't. Fix it:
- Varied sentence lengths (some very short, some longer) After 3 same-length sentences: add ONE very short one. "It usually doesn't." or "That's the problem."
- Conversational asides ("Look, ...", "Here's the thing:", "Don't get me started on...") After a long technical paragraph: one direct opinion sentence. "Most teams don't catch this until it's too late."
- Direct address ("You know this is true if...") Vary paragraph length some 1 sentence, some 4. Never all the same.
- Specific instead of generic ("the Nexus 93180 in rack 14" not "your network switch") 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): 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 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({ res.json({
success: true, success: true,
status: "healthy", status: "healthy",
version: "0.2.6", version: "0.3.0",
uptime: process.uptime(), uptime: process.uptime(),
database: { database: {
connected: true, connected: true,

View File

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