Changelog
What we shipped
Build status in plain English. New features, fixes, and infrastructure shipped to production.
fmtMin utility, no_body_published trigger, max pub gap chip (TASK-1021→1023)
2026-05-07
- ›lib/format.ts: fmtMin returns Math.min(a, b) — symmetric pair with fmtMax, same two-input guard
- ›Smart board: no_body_published fires warn when any published item is missing body content (3+ published gate)
- ›Analytics: Max pub gap chip shows longest gap between consecutive published items — pairs with avg pub gap
fmtMax utility, voice_stale_majority trigger, prev-year pubs chip (TASK-1018→1020)
2026-05-07
- ›lib/format.ts: fmtMax returns Math.max(a, b) with independent finite guards on both inputs
- ›Smart board: voice_stale_majority fires warn when majority of active items have stale voice card (5+ gate)
- ›Analytics: Pubs prev-year chip shows published count for previous calendar year — pairs with this-year chip
fmtLog1p utility, hook_without_body trigger, avg RTR words chip (TASK-1015→1017)
2026-05-07
- ›lib/format.ts: fmtLog1p wraps Math.log1p with domain guard n <= -1 (numerically stable log(1+n))
- ›Smart board: hook_without_body fires info when 3+ active items have hook_type set but body not yet written
- ›Analytics: Avg RTR words chip shows mean body word count for ready-to-record items (completes published/draft/rtr trilogy)
fmtMod utility, body_without_hook trigger, RTR-captions chip (TASK-1012→1014)
2026-05-07
- ›lib/format.ts: fmtMod computes a % b with guards for null, non-finite inputs, and b === 0
- ›Smart board: body_without_hook fires warn when 3+ active items have body written but no hook_type classified
- ›Analytics: RTR with captions chip surfaces ready-to-record items where captions are already pre-written
fmtFrac utility, fully_scripted trigger, pubs-this-year chip (TASK-1009→1011)
2026-05-07
- ›lib/format.ts: fmtFrac returns fractional part of a number (n - trunc(n)), 4dp default
- ›Smart board: fully_scripted fires info when every active item has both hook and body written (5+ active gate)
- ›Analytics: Pubs this year chip counts published items in the current calendar year with dynamic year label
fmtTrunc utility, high_desc_coverage trigger, ideas-with-body chip (TASK-1006→1008)
2026-05-07
- ›lib/format.ts: fmtTrunc wraps Math.trunc — returns integer part as string, no fractional rounding
- ›Smart board: high_desc_coverage fires info when >75% of published items have description filled (5+ gate)
- ›Analytics: Ideas with body chip surfaces idea items that already have body content written (early-writing signal)
fmtTan utility, many_hook_types trigger, avg draft words chip (TASK-1003→1005)
2026-05-07
- ›lib/format.ts: fmtTan computes Math.tan with Infinity guard on result (±π/2 singularities return empty string)
- ›Smart board: many_hook_types fires info when 4+ distinct hook frameworks used across published items (5+ gate)
- ›Analytics: Avg draft words chip shows mean body word count across drafts with content (3+ draft gate)
fmtCos utility, caption_complete trigger, caption rate chip (TASK-1000→1002)
2026-05-07
- ›lib/format.ts: fmtCos computes Math.cos (radians input) — TASK-1000 milestone
- ›Smart board: caption_complete fires info when >80% of published items have captions (accessibility signal, 5+ gate)
- ›Analytics: Caption rate chip shows % of published items with captions set (3+ published gate)
fmtSin utility, outlier_heavy trigger, outlier count chip (TASK-997→999)
2026-05-07
- ›lib/format.ts: fmtSin computes Math.sin (radians input, output in [-1,1])
- ›Smart board: outlier_heavy fires info when >50% of active items reference a viral outlier source (5+ active gate)
- ›Analytics: Outlier-backed chip shows total items linked to a source outlier (shows only when count > 0) — TASK-999 milestone
fmtRadToDeg utility, high_source_coverage trigger, ideas 21d chip (TASK-994→996)
2026-05-07
- ›lib/format.ts: fmtRadToDeg converts radians to degrees (n * 180 / π) — inverse of fmtDegToRad
- ›Smart board: high_source_coverage fires info when >75% of active items have a source URL (5+ active gate)
- ›Analytics: Ideas last 21d chip fills the 14d-to-30d gap in the idea-window ladder
fmtDegToRad utility, third_pub trigger, ideas 45d chip (TASK-991→993)
2026-05-07
- ›lib/format.ts: fmtDegToRad converts degrees to radians (n * π / 180) with 4dp default precision
- ›Smart board: third_pub fires info at exactly 3 published items — completes early milestone ladder (1→2→3→5→10)
- ›Analytics: Ideas last 45d chip fills the 30d-to-60d gap in the idea-window ladder
fmtAtan2 utility, second_pub trigger, pubs 21d chip (TASK-988→990)
2026-05-07
- ›lib/format.ts: fmtAtan2 computes two-argument arctangent matching Math.atan2(y, x) parameter order
- ›Smart board: second_pub fires info at exactly 2 published items — bridges the gap between first_content and pub_milestone
- ›Analytics: Pubs last 21d chip fills the 14d-to-30d gap in the publish-window ladder
fmtAtan utility, erratic_pub trigger, pubs 45d chip (TASK-985→987)
2026-05-07
- ›lib/format.ts: fmtAtan computes arctangent (no domain restriction, output in (-π/2, π/2))
- ›Smart board: erratic_pub warns when publish gap std deviation exceeds 14 days (complement to consistent_pub)
- ›Analytics: Pubs last 45d chip fills the 30d-to-60d gap in the publish-window ladder
fmtAcos utility, consistent_pub trigger, pubs 14d chip (TASK-982→984)
2026-05-07
- ›lib/format.ts: fmtAcos computes arccosine with [-1,1] domain guard (returns radians in [0,π])
- ›Smart board: consistent_pub fires info when publish gap std deviation is under 3 days (population variance, 5+ gate)
- ›Analytics: Pubs last 14d chip fills the gap between 7d and 30d in the publish-window ladder
fmtAsin utility, pub_weekday trigger, drafts 90d chip (TASK-979→981)
2026-05-07
- ›lib/format.ts: fmtAsin computes arcsine with [-1,1] domain guard (returns radians)
- ›Smart board: pub_weekday fires info when majority of publishes occur Mon-Fri (complement to pub_weekend)
- ›Analytics: Drafts last 90d chip caps the draft-window ladder (7d / 14d / 30d / 60d / 90d)
fmtTanh utility, pub_weekend trigger, drafts 60d chip (TASK-976→978)
2026-05-07
- ›lib/format.ts: fmtTanh computes hyperbolic tangent (output always in (-1,1))
- ›Smart board: pub_weekend fires info when majority of published items went out on Sat/Sun (5+ published gate)
- ›Analytics: Drafts last 60d chip completes the draft-window ladder alongside 7d, 14d, and 30d chips
fmtCosh utility, idea_backlog trigger, ideas 60d chip (TASK-973→975)
2026-05-07
- ›lib/format.ts: fmtCosh computes hyperbolic cosine with Infinity guard for large inputs
- ›Smart board: idea_backlog fires info when 10+ ideas exist but fewer than 3 items are published
- ›Analytics: Ideas last 60d chip fills the 60d gap in the idea-window ladder (3+ total ideas gate)
fmtSinh utility, no_drafts trigger, drafts 30d chip (TASK-970→972)
2026-05-07
- ›lib/format.ts: fmtSinh computes hyperbolic sine with Infinity guard for large inputs
- ›Smart board: no_drafts warns when 5+ ideas exist but zero drafts (nudges idea-to-draft conversion)
- ›Analytics: Drafts last 30d chip shows drafts created in the rolling 30-day window (3+ total drafts gate)
fmtHypot utility, draft_momentum trigger, ideas 90d chip (TASK-967→969)
2026-05-07
- ›lib/format.ts: fmtHypot computes Euclidean distance via Math.hypot with finite guards on both inputs
- ›Smart board: draft_momentum fires info when 3+ drafts are created within 7 days (positive reinforcement)
- ›Analytics: Ideas last 90d chip shows ideas added in the rolling 90-day window (3+ total ideas gate)
fmtExpm1 utility, idea_slowdown trigger, pubs 60d chip (TASK-964→966)
2026-05-07
- ›lib/format.ts: fmtExpm1 computes Math.expm1 (numerically stable exp(n)-1 for small n)
- ›Smart board: idea_slowdown fires info when no new ideas arrive in 14 days — earlier warning than idea_drought (30d)
- ›Analytics: Pubs last 60d chip fills the gap between 30d and 90d windows (3+ published gate)
fmtLog10 utility, all_published trigger, pubs 90d chip (TASK-961→963)
2026-05-07
- ›lib/format.ts: fmtLog10 computes base-10 logarithm using Math.log10 with domain guard
- ›Smart board: all_published fires a celebratory info trigger when every queue item is published (5+ gate)
- ›Analytics: Pubs last 90d chip shows published items in the rolling 90-day window (3+ published gate)
fmtLog2 utility, no_ideas_in_queue trigger, cancelled 90d chip (TASK-958→960)
2026-05-07
- ›lib/format.ts: fmtLog2 computes base-2 logarithm using Math.log2 with domain guard
- ›Smart board: no_ideas_in_queue warns when queue has 5+ items but zero idea-status entries (top-of-funnel nudge)
- ›Analytics: Cancelled 90d chip shows cancellations in the rolling 90-day window (distinct from all-time cancelled rate)
fmtExp utility, long_wip trigger, draft % chip (TASK-955→957)
2026-05-07
- ›lib/format.ts: fmtExp computes Math.exp with Infinity guard and integer-clean output
- ›Smart board: long_wip fires a warning when any draft or idea item has been stuck for 60+ days (5+ WIP gate)
- ›Analytics: Draft % chip shows drafts as a percentage of total queue depth (3+ gate)
fmtCbrt utility, pub_milestone trigger, idea % chip (TASK-952→954)
2026-05-07
- ›lib/format.ts: fmtCbrt computes cube root with integer-clean output; Math.cbrt handles negative inputs natively
- ›Smart board: pub_milestone fires an info trigger when published count hits exact milestones (5, 10, 25, 50, 100)
- ›Analytics: Idea % chip shows ideas as a percentage of total queue depth (3+ gate)
fmtSqrt utility, first_content trigger, published % chip (TASK-949→951)
2026-05-07
- ›lib/format.ts: fmtSqrt computes square root with negative guard and integer-clean output
- ›Smart board: first_content fires a celebratory info trigger when exactly 1 item has been published
- ›Analytics: Published % chip shows published items as a percentage of the total queue (3+ gate)
fmtLog utility, high_wip_ratio trigger, WIP:pub ratio chip (TASK-946→948)
2026-05-07
- ›lib/format.ts: fmtLog computes logarithm for any base with guards for invalid inputs
- ›Smart board: high_wip_ratio warns when WIP count exceeds 4x published count (3+ published gate)
- ›Analytics: WIP:pub ratio chip shows the ratio of work-in-progress to published items (3+ each gate)
fmtPow utility, wip_all_stale trigger, pubs/month chip (TASK-943→945)
2026-05-07
- ›lib/format.ts: fmtPow computes base^exp with Infinity guard and integer-clean output
- ›Smart board: wip_all_stale warns when every draft+idea item is 21+ days old (5+ WIP gate)
- ›Analytics: Pubs/month chip shows average monthly publish rate over account lifetime (3+ gate)
fmtQuantize utility, all_drafts_stale trigger, pubs/week chip (TASK-940→942)
2026-05-07
- ›lib/format.ts: fmtQuantize maps a 0-1 value to N discrete levels (useful for progress indicators)
- ›Smart board: all_drafts_stale warns when every draft item is 14+ days old without any recent activity
- ›Analytics: Pubs/week chip shows average weekly publish rate over account lifetime (3+ gate)
fmtSnap utility, pub_drought trigger, drafts last 7d chip (TASK-937→939)
2026-05-07
- ›lib/format.ts: fmtSnap rounds n to the nearest step boundary (completes floor/ceil/snap trilogy)
- ›Smart board: pub_drought warns when no items have been published in 45+ days (3+ published gate)
- ›Analytics: Drafts last 7d chip counts drafts created in the trailing 7-day window (3+ gate)
fmtCeil utility, draft_drought trigger, drafts last 14d chip (TASK-934→936)
2026-05-07
- ›lib/format.ts: fmtCeil quantizes n up to the nearest step boundary (mirrors fmtFloor)
- ›Smart board: draft_drought warns when no new drafts have been created in 21+ days (3+ drafts gate)
- ›Analytics: Drafts last 14d chip counts drafts created in the trailing 14-day window (3+ gate)
fmtFloor utility, draft_spike trigger, idea trend delta chip (TASK-931→933)
2026-05-07
- ›lib/format.ts: fmtFloor quantizes n down to the nearest step boundary (default step=1)
- ›Smart board: draft_spike fires when 3+ draft items are created within 48 hours
- ›Analytics: Idea trend chip shows signed delta between last-7d and prior-7d idea counts (3+ gate)
fmtNegate utility, idea_deceleration trigger, ideas last 14d chip (TASK-928→930)
2026-05-07
- ›lib/format.ts: fmtNegate returns the arithmetic negation of a number, integer-safe
- ›Smart board: idea_deceleration fires when last-7d idea count drops 2+ vs prior-7d (2+ prior gate)
- ›Analytics: Ideas last 14d chip counts ideas created in the trailing 14-day window (3+ gate)
fmtMix utility, idea_acceleration trigger, ideas last 7d chip (TASK-925→927)
2026-05-07
- ›lib/format.ts: fmtMix clamps t to [0,1] and blends two values (GLSL mix semantics)
- ›Smart board: idea_acceleration fires when last-7d idea count exceeds prior-7d by 2+ (2+ recent gate)
- ›Analytics: Ideas last 7d chip counts ideas created in the trailing 7-day window (3+ gate)
fmtStep utility, pub_decline trigger, pub trend delta chip (TASK-922→924)
2026-05-07
- ›lib/format.ts: fmtStep returns '0' or '1' based on whether n is below the edge threshold (GLSL step)
- ›Smart board: pub_decline warns when publish count drops 2+ items vs the prior 30-day window
- ›Analytics: Pub trend chip shows signed delta between last-30d and prior-30d publish counts (3+ gate)
fmtSmoothStep utility, pub_momentum trigger, pubs last 30d chip (TASK-919→921)
2026-05-07
- ›lib/format.ts: fmtSmoothStep applies GLSL smoothstep interpolation between two edge values
- ›Smart board: pub_momentum fires when last-30d publish count exceeds prior-30d count (2+ recent gate)
- ›Analytics: Pubs last 30d chip counts items published in the trailing 30-day window (3+ gate)
fmtNormalize utility, slow_pub trigger, pub days chip (TASK-916→918)
2026-05-07
- ›lib/format.ts: fmtNormalize maps a value to 0–1 range with clamping and division-by-zero guard
- ›Smart board: slow_pub warns when publish rate drops below once per 30 days (3+ published gate)
- ›Analytics: Pub days chip shows distinct calendar days on which items were published (3+ gate)
fmtLerp utility, idea_drought trigger, median title chip (TASK-913→915)
2026-05-07
- ›lib/format.ts: fmtLerp computes linear interpolation between two values at position t
- ›Smart board: idea_drought warns when no new ideas have been added in 30+ days (5+ ideas gate)
- ›Analytics: Median title chip shows median title character length across queue items (3+ gate)
fmtRadix utility, low_draft_to_pub trigger, title spread chip (TASK-910→912)
2026-05-07
- ›lib/format.ts: fmtRadix converts integer to any base 2-36 string with optional prefix
- ›Smart board: low_draft_to_pub warns when fewer than 25% of drafts reach published (5+ gate)
- ›Analytics: Title spread chip shows the character range between shortest and longest title (3+ gate)
fmtNth utility, rapid_idea trigger, shortest title chip (TASK-907→909)
2026-05-07
- ›lib/format.ts: fmtNth appends correct ordinal suffix (1st/2nd/3rd/4th) with 11-13 teens guard
- ›Smart board: rapid_idea fires when 3+ idea items were created within the last 24 hours
- ›Analytics: Shortest title chip shows min title char count across all queue items (3+ gate)
fmtOctal utility, pub_streak trigger, longest title chip (TASK-904→906)
2026-05-07
- ›lib/format.ts: fmtOctal converts integer to octal string with optional prefix
- ›Smart board: pub_streak fires when longest consecutive-day publishing streak reaches 3+
- ›Analytics: Longest title chip shows max title char count across all queue items (3+ gate)
fmtBinary utility, burst_publish trigger, peak pub day chip (TASK-901→903)
2026-05-07
- ›lib/format.ts: fmtBinary converts integer to binary string with optional prefix (e.g. '0b')
- ›Smart board: burst_publish fires when 3+ items were published on the same calendar day
- ›Analytics: Peak pub day chip shows the maximum items published on a single day (3+ gate)
fmtChecksum utility, no_active_items trigger, cancelled rate chip (TASK-898→900)
2026-05-07
- ›lib/format.ts: fmtChecksum returns djb2-style 8-char hex hash for any string
- ›Smart board: no_active_items fires when 5+ total items but none are active
- ›Analytics: Cancelled rate chip shows % of all queue items that are cancelled (3+ gate)
fmtAtob utility, high_queue_depth trigger, active items chip (TASK-895→897)
2026-05-07
- ›lib/format.ts: fmtAtob decodes base64 strings with UTF-8 safety (inverse of fmtBase64)
- ›Smart board: high_queue_depth fires when total active items exceed 20
- ›Analytics: Active items chip shows total non-published non-cancelled item count (3+ gate)
fmtBase64 utility, no_scheduled_future trigger, future scheduled chip (TASK-892→894)
2026-05-07
- ›lib/format.ts: fmtBase64 encodes strings to base64 with UTF-8 safety via encodeURIComponent
- ›Smart board: no_scheduled_future fires when scheduled items exist but none have a future date
- ›Analytics: Future scheduled chip counts scheduled items with a publish date in the future (3+ gate)
fmtEngineering utility, oldest_draft_alert trigger, oldest draft age chip (TASK-889→891)
2026-05-07
- ›lib/format.ts: fmtEngineering formats numbers in engineering notation with exponents as multiples of 3
- ›Smart board: oldest_draft_alert fires when the oldest draft item is over 60 days old
- ›Analytics: Oldest draft chip shows the age in days of the most-stale draft item (3+ drafts gate)
fmtSigFig utility, all_ideas_stale trigger, oldest idea age chip (TASK-886→888)
2026-05-07
- ›lib/format.ts: fmtSigFig formats a number to N significant figures stripping trailing zeros
- ›Smart board: all_ideas_stale fires when every idea item is over 30 days old (3+ gate)
- ›Analytics: Oldest idea chip shows the age in days of the most-stale idea item (3+ ideas gate)
fmtIBSize utility, single_hook_type_queue trigger, active hook types chip (TASK-883→885)
2026-05-07
- ›lib/format.ts: fmtIBSize formats byte counts using IEC binary prefixes (KiB, MiB, GiB)
- ›Smart board: single_hook_type_queue fires when all 5+ hook-assigned active items share one hook type
- ›Analytics: Active hook types chip shows distinct hook frameworks across all active items (3+ gate)
fmtBps utility, low_idea_intake trigger, new ideas 14d chip (TASK-880→882)
2026-05-07
- ›lib/format.ts: fmtBps formats a decimal rate as basis points (e.g. 0.03 → 300 bps)
- ›Smart board: low_idea_intake fires when no new ideas have been added in 14 days (3+ total gate)
- ›Analytics: New ideas (14d) chip shows idea items created in the last 14 days (3+ ideas gate)
fmtMoney utility, all_scheduled_past trigger, published MTD chip (TASK-877→879)
2026-05-07
- ›lib/format.ts: fmtMoney formats a number as a currency string with configurable symbol and decimals
- ›Smart board: all_scheduled_past fires when every scheduled item is past its publish date (2+ gate)
- ›Analytics: Published (MTD) chip shows items published in the current calendar month (3+ gate)
fmtHumanize utility, high_pub_gap trigger, avg pub gap chip (TASK-874→876)
2026-05-07
- ›lib/format.ts: fmtHumanize converts identifiers to a capitalised readable label
- ›Smart board: high_pub_gap fires when average days between consecutive publishes exceeds 14
- ›Analytics: Avg pub gap chip shows average days between consecutive published items (3+ gate)
fmtSpaceCase utility, no_outlier_ideas trigger, outlier ideas chip (TASK-871→873)
2026-05-07
- ›lib/format.ts: fmtSpaceCase converts kebab/snake/camel strings to space separated lowercase words
- ›Smart board: no_outlier_ideas fires when 5+ ideas exist but none are seeded from outliers
- ›Analytics: Outlier ideas chip counts idea items seeded from an outlier source (3+ ideas gate)
fmtColonCase utility, idea_to_pub_ratio trigger, idea:pub ratio chip (TASK-868→870)
2026-05-07
- ›lib/format.ts: fmtColonCase converts strings to colon:separated:case
- ›Smart board: idea_to_pub_ratio fires when ideas outnumber published items 5:1 or more
- ›Analytics: Idea:pub ratio chip shows the ratio of idea items to published items (3+ of each gate)
fmtPathCase utility, high_short_title_rate trigger, short titles chip (TASK-865→867)
2026-05-07
- ›lib/format.ts: fmtPathCase converts strings to path/case using forward slash separators
- ›Smart board: high_short_title_rate fires when >50% of published items have titles under 20 chars
- ›Analytics: Short titles chip counts published items with titles under 20 characters (3+ gate)
fmtDotCase utility, zero_pub_last7 trigger, published 7d chip (TASK-862→864)
2026-05-07
- ›lib/format.ts: fmtDotCase converts camelCase/kebab/snake/space strings to dot.case
- ›Smart board: zero_pub_last7 fires when nothing has been published in 7 days (3+ historical gate)
- ›Analytics: Published (7d) chip shows items published in the last 7 days (3+ total published gate)
fmtSwapCase utility, high_recording_ratio trigger, in-recording chip (TASK-859→861)
2026-05-07
- ›lib/format.ts: fmtSwapCase swaps the case of every character in a string
- ›Smart board: high_recording_ratio fires when more than 50% of active items are in recording
- ›Analytics: In recording chip shows % of active items currently at the recording stage (3+ gate)
fmtScream utility, single_platform_only trigger, source platforms chip (TASK-856→858)
2026-05-07
- ›lib/format.ts: fmtScream converts strings to SCREAMING_SNAKE_CASE
- ›Smart board: single_platform_only fires when all sourced published items share one domain
- ›Analytics: Source platforms chip shows distinct source domains across published items (3+ gate)
fmtPascal utility, missing_title trigger, untitled items chip (TASK-853→855)
2026-05-07
- ›lib/format.ts: fmtPascal converts space/kebab/snake strings to PascalCase
- ›Smart board: missing_title fires when 2+ active items have no title set
- ›Analytics: Untitled items chip counts all queue items with no title (renders only when > 0)
fmtSentenceCount utility, cancel_streak trigger, cancel streak chip (TASK-850→852)
2026-05-07
- ›lib/format.ts: fmtSentenceCount counts terminated sentences in a string using .!? punctuation
- ›Smart board: cancel_streak fires when the 3 most-recently created items are all cancelled
- ›Analytics: Cancel streak chip shows length of trailing cancel run from most-recent items
fmtMiddle utility, low_draft_completion trigger, draft completion chip (TASK-847→849)
2026-05-07
- ›lib/format.ts: fmtMiddle truncates the middle of long strings keeping both ends visible
- ›Smart board: low_draft_completion fires when fewer than 25% of drafted items have been published
- ›Analytics: Draft completion chip shows % of draft-stage items that reached published (5+ gate)
fmtBlank utility, high_idea_age trigger, avg idea age chip (TASK-844→846)
2026-05-07
- ›lib/format.ts: fmtBlank returns a fallback when a string is null, empty, or whitespace-only
- ›Smart board: high_idea_age fires when average age of idea items exceeds 21 days
- ›Analytics: Avg idea age chip shows average age of idea-status items in days (3+ gate)
fmtSqueeze utility, ideas_no_description trigger, ideas w/o desc chip (TASK-841→843)
2026-05-07
- ›lib/format.ts: fmtSqueeze collapses multiple consecutive newlines into a single newline
- ›Smart board: ideas_no_description fires when 3+ idea items have no description set
- ›Analytics: Ideas w/o desc chip shows % of idea items missing a description (3+ gate)
fmtLineJoin utility, stale_scheduled trigger, stale scheduled chip (TASK-838→840)
2026-05-07
- ›lib/format.ts: fmtLineJoin joins a string array filtering nulls, defaulting to newline separator
- ›Smart board: stale_scheduled fires when 2+ scheduled items have a publish date 14+ days in the past
- ›Analytics: Stale scheduled chip counts scheduled items overdue by 14+ days (3+ scheduled gate)
fmtLastWord utility, low_hook_diversity trigger, draft hook types chip (TASK-835→837)
2026-05-07
- ›lib/format.ts: fmtLastWord returns the last whitespace-delimited word of a string
- ›Smart board: low_hook_diversity fires when all 5+ published items share the same hook type
- ›Analytics: Draft hook types chip shows distinct hook frameworks used across draft items (3+ gate)
fmtFirstWord utility, high_wip_age trigger, avg WIP age chip (TASK-832→834)
2026-05-07
- ›lib/format.ts: fmtFirstWord returns the first whitespace-delimited word of a string
- ›Smart board: high_wip_age fires when average age of draft+idea items exceeds 30 days
- ›Analytics: Avg WIP age chip shows average age of all draft and idea items in days (3+ gate)
fmtNumWords utility, missing_source_url trigger, published w/o URL chip (TASK-829→831)
2026-05-07
- ›lib/format.ts: fmtNumWords returns the word count of a string as a formatted string
- ›Smart board: missing_source_url fires when 3+ published items have no source URL recorded
- ›Analytics: Published w/o URL chip shows % of published items missing a source URL (3+ gate)
fmtNumeric utility, no_hook_type_drafts trigger, drafts w/o hook chip (TASK-826→828)
2026-05-07
- ›lib/format.ts: fmtNumeric strips all non-digit characters from a string (complement to fmtAlpha)
- ›Smart board: no_hook_type_drafts fires when 3+ draft items are missing a hook_type
- ›Analytics: Drafts w/o hook chip shows % of drafts missing a hook type (3+ gate)
fmtAlpha utility, low_schedule_coverage trigger, scheduled % chip (TASK-823→825)
2026-05-07
- ›lib/format.ts: fmtAlpha strips all non-letter characters from a string
- ›Smart board: low_schedule_coverage fires when fewer than 20% of active items have a scheduled publish date
- ›Analytics: Scheduled % chip shows what share of active items are scheduled (3+ gate)
fmtFraction utility, burst_creation trigger, fastest publish chip (TASK-820→822)
2026-05-07
- ›lib/format.ts: fmtFraction formats two numbers as an integer fraction string (n/d)
- ›Smart board: burst_creation fires when 5+ items are added to the queue within 24 hours
- ›Analytics: fastest publish chip completes the min/avg/max pipeline speed trio
fmtRoman utility, recording_backlog trigger, slowest publish chip (TASK-817→819)
2026-05-07
- ›lib/format.ts: fmtRoman converts integers 1-3999 to Roman numerals using subtraction pairs
- ›Smart board: recording_backlog fires (warn) when 3+ items have been stuck in recording for over 7 days
- ›Analytics: slowest publish chip shows the longest creation-to-published duration — outlier detection for pipeline
fmtOct utility, low_source_outlier_rate trigger, avg time to publish chip (TASK-814→816)
2026-05-07
- ›lib/format.ts: fmtOct completes the base-conversion trio (hex/bin/oct) with optional 0o prefix
- ›Smart board: low_source_outlier_rate fires when fewer than 10% of active items are research-seeded
- ›Analytics: avg time to publish chip shows end-to-end pipeline speed in days
fmtBin utility, low_item_intake trigger, new items 14d chip (TASK-811→813)
2026-05-07
- ›lib/format.ts: fmtBin converts a number to binary string with optional prefix (0b notation)
- ›Smart board: low_item_intake fires when no new queue items have been added in 14 days
- ›Analytics: new items (14d) chip shows queue intake velocity at a glance
fmtHex utility, high_cancel_ratio trigger, published/total ratio chip (TASK-808→810)
2026-05-07
- ›lib/format.ts: fmtHex converts a number to hexadecimal string with optional prefix (# for CSS, 0x for code)
- ›Smart board: high_cancel_ratio fires (warn) when cancelled items exceed 30% of all queue items
- ›Analytics: published / total chip shows lifetime queue completion as a raw X / Y count
fmtPair utility, high idea-to-draft ratio trigger, ratio chip (TASK-805→807)
2026-05-07
- ›lib/format.ts: fmtPair formats two values with a configurable separator (default " / ")
- ›Smart board: high_idea_to_draft_ratio fires when ideas outnumber drafts by 3x or more in active queue
- ›Analytics: idea:draft ratio chip shows the balance between ideation and active drafting
fmtMap utility, idea_dominates trigger, active ideas % chip (TASK-802→804)
2026-05-07
- ›lib/format.ts: fmtMap translates a string through a lookup map with a configurable fallback
- ›Smart board: idea_dominates fires when >70% of 5+ active items are stuck in idea stage
- ›Analytics: active ideas % chip completes the three-way early-stage breakdown (early / draft / idea)
fmtGrade utility, draft_dominates trigger, active drafts % chip (TASK-799→801)
2026-05-07
- ›lib/format.ts: fmtGrade maps a number to a grade label via configurable thresholds (A/B/C or Good/Fair/Poor etc.)
- ›Smart board: draft_dominates fires when >70% of 5+ active items are stuck in draft stage
- ›Analytics: active drafts % chip isolates the draft bottleneck separately from the combined early-stage metric
fmtTail utility, queue_too_small trigger, in-recording count chip (TASK-796→798)
2026-05-07
- ›lib/format.ts: fmtTail returns the last N lines of a multi-line string (companion to fmtHead)
- ›Smart board: queue_too_small fires when the queue has 1-2 items total to prompt content planning
- ›Analytics: in-recording chip shows how many items are currently in active production
fmtHead utility, published_no_hook_type trigger, avg items/week chip (TASK-793→795)
2026-05-07
- ›lib/format.ts: fmtHead returns the first N lines of a multi-line string
- ›Smart board: published_no_hook_type fires when fewer than 25% of 5+ published items have a hook type logged
- ›Analytics: avg items/week chip shows queue creation rate over the last 90 days
fmtChunk utility, stale_outliers trigger, outlier utilization % chip (TASK-790→792)
2026-05-07
- ›lib/format.ts: fmtChunk splits a string into fixed-size character chunks joined by a configurable separator
- ›Smart board: stale_outliers fires when all 5+ outliers are older than 14 days with no fresh detections
- ›Analytics: outlier utilization % chip shows what fraction of research outliers have been turned into queue items
fmtReverse utility, low_pub_velocity trigger, published last 30d chip (TASK-787→789)
2026-05-07
- ›lib/format.ts: fmtReverse reverses a string character by character (null-safe)
- ›Smart board: low_pub_velocity fires (warn) when nothing has been published in 30 days despite 5+ total published items
- ›Analytics: published last 30d chip fills the gap between the existing 7-day and 90-day windows
fmtDeindent utility, stuck_in_draft trigger, old drafts count chip (TASK-784→786)
2026-05-06
- ›lib/format.ts: fmtDeindent strips common leading indentation from multi-line strings
- ›Smart board: stuck_in_draft fires when 3+ draft items have been open for over 21 days
- ›Analytics: drafts > 21d old chip shows count of long-lived drafts needing resolution
fmtIndent utility, stuck_in_idea trigger, avg idea age chip (TASK-781→783)
2026-05-06
- ›lib/format.ts: fmtIndent prefixes each non-blank line with configurable indentation
- ›Smart board: stuck_in_idea fires when 2+ idea-status items haven't been drafted in over 14 days
- ›Analytics: avg idea age chip shows how long ideas sit before progressing
fmtNormSpaces utility, high_wip_count trigger, early-stage active % chip (TASK-778→780)
2026-05-06
- ›lib/format.ts: fmtNormSpaces collapses all whitespace runs (tabs, newlines, spaces) into single spaces
- ›Smart board: high_wip_count fires when >50% of 5+ active items are still in draft or idea stage
- ›Analytics: early-stage active % chip shows what fraction of active items are still in draft/idea
fmtExcerpt utility, all_active_no_source trigger, active no-source % chip (TASK-775→777)
2026-05-06
- ›lib/format.ts: fmtExcerpt truncates a string to N characters with a configurable ellipsis
- ›Smart board: all_active_no_source fires when none of 5+ active items have a source URL
- ›Analytics: active no-source % chip shows what fraction of active items lack a source URL
fmtTitle utility, recent cancellations trigger, cancelled last 30d chip (TASK-772→774)
2026-05-06
- ›lib/format.ts: fmtTitle title-cases each word of a string (null-safe)
- ›Smart board: many_recent_cancellations fires (warn) when 3+ items were cancelled in the last 30 days
- ›Analytics: cancelled last 30d chip shows rolling count of recently cancelled queue items
fmtPadStart utility, all_queue_stale trigger, outlier seed conversion chip (TASK-769→771)
2026-05-06
- ›lib/format.ts: fmtPadStart left-pads a string to a fixed length with a configurable fill character
- ›Smart board: all_queue_stale fires (warn) when all 5+ active items are older than 30 days
- ›Analytics: outlier seed conversion chip shows % of outlier-seeded queue items that reached published
fmtPadEnd utility, no_new_outliers trigger, published this year chip (TASK-766→768)
2026-05-06
- ›lib/format.ts: fmtPadEnd right-pads a string to a fixed length with a configurable fill character
- ›Smart board: no_new_outliers fires when no outliers were detected in 7 days and 5+ exist total
- ›Analytics: Published this year chip shows items published since Jan 1 of the current year
fmtLower utility, recording_no_hook trigger, published last 90d chip (TASK-763→765)
2026-05-06
- ›lib/format.ts: fmtLower returns a trimmed, lowercased string (null-safe complement to fmtUpper)
- ›Smart board: recording_no_hook fires when 2+ recorded items are missing a hook type
- ›Analytics: Published last 90d chip shows items published in the rolling last-90-day window
fmtUpper utility, high_recorded_age trigger, top hook type chip (TASK-760→762)
2026-05-06
- ›lib/format.ts: fmtUpper returns a trimmed, uppercased string (null-safe)
- ›Smart board: high_recorded_age fires when recorded items average more than 14 days old (3+ gate)
- ›Analytics: Top hook type chip shows the most-used hook framework in published items
fmtTrimWords utility, no_source_ready trigger, min body words chip (TASK-757→759)
2026-05-06
- ›lib/format.ts: fmtTrimWords truncates a string to N words and appends a configurable ellipsis
- ›Smart board: no_source_ready fires when 2+ ready-to-record items are missing a source URL
- ›Analytics: Min body words chip shows the shortest published body word count
fmtAbs utility, short_avg_body_pub trigger, max body words chip (TASK-754→756)
2026-05-06
- ›lib/format.ts: fmtAbs returns the absolute value of a number as a string (null-safe)
- ›Smart board: short_avg_body_pub fires when avg published body word count is below 150 words
- ›Analytics: Max body words chip shows the longest published body across all published items
fmtNorm utility, scheduled_no_title trigger, long title % chip (TASK-751→753)
2026-05-06
- ›lib/format.ts: fmtNorm normalizes a number to a 0–100% scale given a min/max range
- ›Smart board: scheduled_no_title warns when any scheduled item is missing a title (1+ gate)
- ›Analytics: Long title % chip shows the share of published items with a title over 80 chars
fmtClamp utility, low_hook_active trigger, avg pub title length chip (TASK-748→750)
2026-05-06
- ›lib/format.ts: fmtClamp clamps a number to [min, max] range and returns it as a string
- ›Smart board: low_hook_active fires when <20% of active items have a hook type set (5+ gate)
- ›Analytics: Avg pub title length chip shows avg title char length across published items
fmtFixed utility, long_lead_time trigger, voice stale % chip (TASK-745→747)
2026-05-06
- ›lib/format.ts: fmtFixed formats a number with a fixed number of decimal places (null-safe)
- ›Smart board: long_lead_time fires when avg days from creation to scheduled publish exceeds 21 days
- ›Analytics: Voice stale % chip shows the percentage of active items with a stale voice profile
fmtSpan utility, single hook type trigger, avg schedule lead chip (TASK-742→744)
2026-05-06
- ›lib/format.ts: fmtSpan formats a range between two values with a configurable separator
- ›Smart board: single_hook_type_published fires when all tagged published items share one hook type
- ›Analytics: Avg schedule lead chip shows avg days between item creation and scheduled publish date
fmtWrap utility, scheduled_far_future trigger, published hook types chip (TASK-739→741)
2026-05-06
- ›lib/format.ts: fmtWrap wraps a string with configurable open/close delimiters (null-safe)
- ›Smart board: scheduled_far_future fires when 2+ items are scheduled more than 30 days out
- ›Analytics: Published hook types chip shows distinct hook_type values across published items
fmtPrefix utility, high_cancel_rate trigger, scheduled next 7d chip (TASK-736→738)
2026-05-06
- ›lib/format.ts: fmtPrefix prepends a prefix string to a non-empty value (null-safe complement to fmtSuffix)
- ›Smart board: high_cancel_rate fires when cancelled items exceed 20% of total (5+ gate, warn level)
- ›Analytics: Scheduled next 7d chip shows items due to publish in the rolling next-7-day window
fmtNum utility, voice_stale_active trigger, published last 7d chip (TASK-733→735)
2026-05-06
- ›lib/format.ts: fmtNum formats an integer with locale comma separators (1234567 → "1,234,567")
- ›Smart board: voice_stale_active fires when 1+ active items still carry a stale voice profile
- ›Analytics: Published last 7d chip shows items published in the rolling last-7-day window
fmtFallback utility, many_items_no_captions trigger, outliers last 30d chip (TASK-730→732)
2026-05-06
- ›lib/format.ts: fmtFallback returns a fallback string when input is null or empty
- ›Smart board: many_items_no_captions fires when >60% of active items have no captions (5+ gate)
- ›Analytics: Outliers last 30d chip shows outliers detected in the rolling last-30-day window
fmtJoin utility, all_drafts_no_description trigger, drafts last 7d chip (TASK-727→729)
2026-05-06
- ›lib/format.ts: fmtJoin joins an array with configurable separator and last-item separator
- ›Smart board: all_drafts_no_description fires when all 5+ drafts are missing descriptions
- ›Analytics: Drafts last 7d chip shows draft items created in the rolling last-7-day window
fmtRepeat utility, many_drafts_no_body trigger, max overdue days chip (TASK-724→726)
2026-05-06
- ›lib/format.ts: fmtRepeat repeats a string n times with optional separator — fmtRepeat('★', 5) → '★★★★★'
- ›Smart board: many_drafts_no_body fires when 3+ draft items have no body content written
- ›Analytics: Max overdue days chip shows the worst-case single item days past its scheduled date
fmtQuote utility, low_source_url_active trigger, avg overdue days chip (TASK-721→723)
2026-05-06
- ›lib/format.ts: fmtQuote wraps a string in configurable quotes — fmtQuote('hello') → '"hello"'
- ›Smart board: low_source_url_active fires when 1–19% of active items have a source URL (5+ gate)
- ›Analytics: Avg overdue days chip shows mean days past scheduled date for overdue items
fmtBracket utility, high_ready_age trigger, scheduled source % chip (TASK-718→720)
2026-05-06
- ›lib/format.ts: fmtBracket wraps a string in square brackets — fmtBracket('v2') → '[v2]'
- ›Smart board: high_ready_age warns when ready-to-record items average more than 14 days old
- ›Analytics: Scheduled source % chip shows what fraction of scheduled items have a source URL
fmtParens utility, long_ready_queue trigger, scheduled outlier rate chip (TASK-715→717)
2026-05-06
- ›lib/format.ts: fmtParens wraps a string in parentheses — fmtParens('draft') → '(draft)'
- ›Smart board: long_ready_queue fires when 4+ items are piled up in ready-to-record status
- ›Analytics: Scheduled outlier rate chip shows how research-backed the upcoming schedule is
fmtSuffix utility, low_captions_coverage trigger, avg ready age chip (TASK-712→714)
2026-05-06
- ›lib/format.ts: fmtSuffix appends a caller-supplied suffix — fmtSuffix('42', 'px') → '42px'
- ›Smart board: low_captions_coverage fires when 1–24% of published items have captions (5+ gate)
- ›Analytics: Avg ready age chip shows mean days ready-to-record items have been sitting unrecorded
fmtBullet utility, no_captions_recording trigger, published outlier rate chip (TASK-709→711)
2026-05-06
- ›lib/format.ts: fmtBullet prepends a bullet prefix — fmtBullet('Item') → '• Item'
- ›Smart board: no_captions_recording fires when any recording-status item has no captions set
- ›Analytics: Published outlier rate chip shows % of published items that were seeded from outliers
fmtKebab utility, low_desc_coverage trigger, avg caption words chip (TASK-706→708)
2026-05-06
- ›lib/format.ts: fmtKebab converts camelCase/snake_case/spaces to kebab-case — 'myFieldName' → 'my-field-name'
- ›Smart board: low_desc_coverage fires when 1–24% of published items have descriptions (5+ gate)
- ›Analytics: Avg caption words chip shows mean word count per published item with captions
fmtSnake utility, no_source_scheduled trigger, avg description words chip (TASK-703→705)
2026-05-06
- ›lib/format.ts: fmtSnake converts camelCase/spaces/hyphens to snake_case — 'myFieldName' → 'my_field_name'
- ›Smart board: no_source_scheduled fires when 2+ scheduled items have no source URL before publishing
- ›Analytics: Avg description words chip shows mean word count per published item with description
fmtCamel utility, description_only trigger, body coverage chip (TASK-700→702)
2026-05-06
- ›lib/format.ts: fmtCamel converts snake_case/kebab-case to camelCase — 'my_field_name' → 'myFieldName'
- ›Smart board: description_only fires when 2+ active items have description but no hook type classified
- ›Analytics: Body coverage chip shows % of published items with body content filled
fmtBar utility, all_scheduled_same_week trigger, avg gap between posts chip (TASK-697→699)
2026-05-06
- ›lib/format.ts: fmtBar renders an ASCII progress bar — fmtBar(3, 5) → '▓▓▓░░'
- ›Smart board: all_scheduled_same_week fires when 3+ scheduled items all land within a 7-day window
- ›Analytics: Avg gap between posts chip shows mean days between consecutive publishes (complements median)
fmtPad utility, captions_missing_ready trigger, median body words chip (TASK-694→696)
2026-05-06
- ›lib/format.ts: fmtPad zero-pads a number to a fixed width — fmtPad(7, 3) → '007'
- ›Smart board: captions_missing_ready fires when 2+ ready-to-record items have no captions set
- ›Analytics: Median body words chip shows median word count across published items with body content
fmtAbbrev utility, long_title_avg trigger, avg title words chip (TASK-691→693)
2026-05-06
- ›lib/format.ts: fmtAbbrev converts multi-word strings to initials — 'Marketing Agency' → 'MA'
- ›Smart board: long_title_avg fires when avg title length across 5+ active items exceeds 80 chars
- ›Analytics: Avg title words chip shows mean word count per queue item title (complements char-length chip)
fmtCapitalize utility, hook_missing_scheduled trigger, published YTD chip (TASK-688→690)
2026-05-06
- ›lib/format.ts: fmtCapitalize title-cases each word — 'content creator' → 'Content Creator'
- ›Smart board: hook_missing_scheduled fires when scheduled items lack hook_type classification
- ›Analytics: Published [year] chip shows all items published since Jan 1 of current year
fmtCents utility, all_drafts_no_hook trigger, best streak ever chip (TASK-685→687)
2026-05-06
- ›lib/format.ts: fmtCents renders sub-cent amounts as '0.30¢' and larger amounts as '$1.20'
- ›Smart board: all_drafts_no_hook fires when every draft (5+) has no hook_type classified
- ›Analytics: Best streak ever chip shows all-time longest consecutive publish streak (personal best)
fmtDelta utility, voice_stale_ready trigger, published this quarter chip (TASK-682→684)
2026-05-06
- ›lib/format.ts: fmtDelta formats signed integer delta — '+3' / '-2' / '0', rounds before format
- ›Smart board: voice_stale_ready fires when ready_to_record items have stale voice card (1+ gate)
- ›Analytics: Published Qx chip shows items published in current calendar quarter with year label
fmtTimeHHMM utility, low_publish_rate_active trigger, avg outlier title words chip (TASK-679→681)
2026-05-06
- ›lib/format.ts: fmtTimeHHMM extracts HH:MM from ISO string or Date using toLocaleTimeString 24h
- ›Smart board: low_publish_rate_active fires when 5+ items created last 30 days but none published
- ›Analytics: Avg outlier title words chip shows mean word count across saved outlier titles (5+ gate)
fmtMonth utility, nothing_scheduled_2_weeks trigger, created/month chip (TASK-676→678)
2026-05-06
- ›lib/format.ts: fmtMonth formats month count as '6mo' — rounds, null-safe
- ›Smart board: nothing_scheduled_2_weeks fires when calendar is empty for next 14 days (5+ items gate)
- ›Analytics: Created / month chip shows avg queue items created per calendar month across full history
fmtPrecision utility, body_only_drafts trigger, no-hook drafts chip (TASK-673→675)
2026-05-06
- ›lib/format.ts: fmtPrecision strips trailing zeros via parseFloat(toFixed()) — '2.50' → '2.5'
- ›Smart board: body_only_drafts fires when 2+ drafts have body written but no hook section (2+ gate)
- ›Analytics: No-hook drafts chip counts active items with body but no hook — complements Unfinished hooks
fmtWeeks utility, large_recording_queue trigger, first published chip (TASK-670→672)
2026-05-06
- ›lib/format.ts: fmtWeeks formats week count as '3w' — rounds, null-safe, complements fmtDays
- ›Smart board: large_recording_queue fires when 4+ items simultaneously in recording status
- ›Analytics: First published chip shows earliest published_at date with total published count hint
fmtDays utility, high_template_ratio trigger, unfinished hooks chip (TASK-667→669)
2026-05-06
- ›lib/format.ts: fmtDays formats integer day count as '14d' — rounds, null-safe
- ›Smart board: high_template_ratio fires when >30% of active items are templates (5+ gate)
- ›Analytics: Unfinished hooks chip counts active items with hook written but no body (zero-hidden)
fmtElapsed utility, published_no_source trigger, research-backed published chip (TASK-664→666)
2026-05-06
- ›lib/format.ts: fmtElapsed formats milliseconds as '3h 22m' / '45m 12s' / '9s'
- ›Smart board: published_no_source fires when >50% of published items (5+) have no source URL
- ›Analytics: Research-backed published chip shows % of published items with a source URL (3+ gate)
fmtSignedPct utility, many_orphan_items trigger, avg shipped multiple chip (TASK-661→663)
2026-05-06
- ›lib/format.ts: fmtSignedPct prefixes positive values with + and formats as percent
- ›Smart board: many_orphan_items fires when 3+ drafts have no hook type, captions, or description
- ›Analytics: Avg multiple (shipped) chip shows mean outlier multiple for published inspired items (3+ gate)
fmtHashtag utility, no_template_items trigger, avg body words chip (TASK-658→660)
2026-05-06
- ›lib/format.ts: fmtHashtag normalizes any string to #hashtag form — lowercases, strips spaces, adds # prefix
- ›Smart board: no_template_items fires when queue has 5+ items but zero saved as reusable templates
- ›Analytics: Avg body words chip shows mean body word count per published item (gated 3+ with body filled)
fmtCelsius utility, short_hook_words trigger, avg hook word count chip (TASK-655→657)
2026-05-06
- ›lib/format.ts: fmtCelsius formats '22.5°C' / '0°C' — strips trailing decimal zero, consistent with fmtDecibel pattern
- ›Smart board: short_hook_words fires when published hooks average <8 words — context-setting signal
- ›Analytics: Avg hook words chip shows mean word count of hook section across published items (gated 5+ with hooks)
fmtDecibel utility, long_queue_no_publish trigger, avg queue age chip (TASK-652→654)
2026-05-06
- ›lib/format.ts: fmtDecibel formats '-6.2 dB' / '0 dB' — strips trailing decimal zero
- ›Smart board: long_queue_no_publish fires when 20+ active items exist but nothing published in 30 days — blocked pipeline signal
- ›Analytics: Avg queue age chip shows mean days since created_at across active items (gated 5+)
fmtAngle utility, low_brain_diversity trigger, brain kinds chip (TASK-649→651)
2026-05-06
- ›lib/format.ts: fmtAngle converts 'question_hook' / 'CONTRARIAN' to 'Question Hook' — title-cases after underscore split
- ›Smart board: low_brain_diversity fires when 5+ brain entries all share one kind — voice model depth signal
- ›Analytics: Brain kinds chip shows distinct entry type count from existing knowledgeKindCounts map (zero extra queries)
fmtFrequency utility, publish_day_conflict trigger, schedule conflicts chip (TASK-646→648)
2026-05-06
- ›lib/format.ts: fmtFrequency(published, daySpan) returns '2/week' or '1.5/month' — switches unit at 0.9/week threshold
- ›Smart board: publish_day_conflict fires when 2+ scheduled items share a calendar date — audience-splitting signal
- ›Analytics: Schedule conflicts chip shows count of dates with stacked items (gated count > 0)
fmtLatency utility, recording_age_warn trigger, avg recorded age chip (TASK-643→645)
2026-05-06
- ›lib/format.ts: fmtLatency formats ms/s/m+s — '45ms', '1.2s', '1m 30s' — strips trailing .0 on seconds
- ›Smart board: recording_age_warn fires when recorded items sit >7 days without publishing (gated 1+ recorded)
- ›Analytics: Avg recorded age chip shows mean days since update for recorded items — uses Record cast for updated_at
fmtByteSize utility, draft_to_ready_rate trigger, funnel conversion chip (TASK-640→642)
2026-05-06
- ›lib/format.ts: fmtByteSize formats B/KB/MB/GB using 1024-based units with one decimal place
- ›Smart board: draft_to_ready_rate fires when <30% of funnel items have passed draft stage (gated 10+ total, 3+ drafts)
- ›Analytics: Funnel conversion chip shows % of items past draft stage — pipeline health at a glance
fmtLineCount utility, overdue_ratio trigger, overdue rate chip (TASK-637→639)
2026-05-06
- ›lib/format.ts: fmtLineCount formats '42 lines' / '1 line' with proper singular — consistent with fmtWords and fmtCount patterns
- ›Smart board: overdue_ratio fires when >30% of scheduled items are past their date — warn level, links to scheduled queue filter
- ›Analytics: Overdue rate chip shows % of scheduled items past due with count hint (gated 3+ scheduled, count > 0)
fmtTokenCount utility, high_scheduled_count trigger, scheduled chip (TASK-634→636)
2026-05-06
- ›lib/format.ts: fmtTokenCount formats '1.2k tokens' / '800 tokens' — strips trailing .0 on k suffix
- ›Smart board: high_scheduled_count fires at 10+ scheduled items — overfull pipeline warning with calendar link
- ›Analytics: Scheduled chip shows total items with a publish date set — distinct from time-windowed next-7d stat
fmtConfidence utility, low_inspiration_rate trigger, templates chip (TASK-631→633)
2026-05-06
- ›lib/format.ts: fmtConfidence normalises 0-1 and 0-100 score ranges to percent — clamps to [0,100]
- ›Smart board: low_inspiration_rate fires when <20% of active queue items sourced from outliers (gated 10+ items)
- ›Analytics: Templates chip shows reusable script framework count in queue — gated on count > 0
fmtGrowthRate utility, high_draft_word_count trigger, recorded chip (TASK-628→630)
2026-05-06
- ›lib/format.ts: fmtGrowthRate formats '+23% MoM' / '-5% WoW' — accepts decimal fraction or whole percent, configurable suffix
- ›Smart board: high_draft_word_count fires when drafts average >1500 words — over-writing signal with link to draft queue
- ›Analytics: Recorded chip shows items filmed but not yet published — gated on count > 0
fmtVersionString utility, no_scheduled_next_week trigger, ready-to-record chip (TASK-625→627)
2026-05-06
- ›lib/format.ts: fmtVersionString prefixes 'v' — passes through existing 'v' prefix, handles number input
- ›Smart board: no_scheduled_next_week fires when nothing is scheduled 7-14 days out and user has published before
- ›Analytics: Ready to record chip surfaces scripts approved and waiting for camera — gated on count > 0
fmtSlug utility, stale_outlier_ratio trigger, published-last-14d chip (TASK-622→624)
2026-05-06
- ›lib/format.ts: fmtSlug converts any string to URL-safe slug — lowercases, collapses non-alphanumeric runs to '-', strips leading/trailing dashes
- ›Smart board: stale_outlier_ratio fires when 50%+ of outliers are 90+ days old — refresh swipe file signal
- ›Analytics: Published last 14d chip shows rolling 2-week publish count distinct from the UTC-week 'this week' stat
fmtTagList utility, no_recent_brain trigger, avg draft age chip (TASK-619→621)
2026-05-06
- ›lib/format.ts: fmtTagList(tags) formats string arrays as '#hook #value #story' — strips duplicate # prefix, lowercases, filters empty
- ›Smart board: no_recent_brain fires when brain has 3+ entries but none added in 14 days — keeps voice model fresh
- ›Analytics: Avg draft age chip shows mean days since created_at across draft-status items (gated 3+ drafts)
fmtStepProgress utility, no_source_any trigger, median publish hour chip (TASK-616→618)
2026-05-06
- ›lib/format.ts: fmtStepProgress(step, total) formats 'Step 3 of 7' with clamping
- ›Smart board: no_source_any fires when ≥3 active items have zero source URLs — distinct from no_source_url threshold
- ›Analytics: Median publish hour chip shows UTC hour at median published item (gated ≥5 published)
fmtCapped utility, high_outlier_age trigger, best publish month chip (TASK-613→615)
2026-05-06
- ›lib/format.ts: fmtCapped(n, cap) returns '50+' when at limit — useful for display truncation signals
- ›Smart board: high_outlier_age fires when avg outlier age >60 days — stale swipe file warning
- ›Analytics: Best publish month chip shows all-time peak monthly publish count with month key hint
fmtURLDomain utility, hook_type_imbalance trigger, source domains chip (TASK-610→612)
2026-05-06
- ›lib/format.ts: fmtURLDomain(url) extracts 'youtube.com' from full URLs, strips www prefix
- ›Smart board: hook_type_imbalance fires when one hook type ≥70% of typed active queue (with ≥2 types)
- ›Analytics: Source domains chip shows distinct URL domains across active queue items (gated ≥2 domains)
fmtLabelCase utility, long_title_items trigger, avg title length chip (TASK-607→609)
2026-05-06
- ›lib/format.ts: fmtLabelCase(s) converts snake_case/camelCase to 'Title Case' — useful for hook_type display
- ›Smart board: long_title_items fires when ≥3 active items have titles >80 chars — unfocused topic signal
- ›Analytics: Avg title length chip shows mean char count of active queue titles with focus-threshold hint
fmtHandle utility, high_ai_no_publish trigger, created-last-week chip (TASK-604→606)
2026-05-06
- ›lib/format.ts: fmtHandle(s) ensures '@' prefix — '@nabila' passes through, 'nabila' → '@nabila'
- ›Smart board: high_ai_no_publish fires when ≥10 AI calls MTD but 0 items published this month
- ›Analytics: Created last week chip promotes queueLastWeek raw count to its own StatStrip slot
fmtSentenceCase utility, no_hook_variety_queue trigger, MTD AI efficiency chip (TASK-601→603)
2026-05-06
- ›lib/format.ts: fmtSentenceCase(s) normalises hook_type labels — 'QUESTION_HOOK' → 'Question_hook'
- ›Smart board: no_hook_variety_queue fires when ≥5 active typed items all share one hook type
- ›Analytics: MTD AI efficiency chip shows published-per-AI-call ratio for the month (gated ≥3 calls + ≥1 publish)
fmtYear utility, many_drafts_no_hooks trigger, queue hook types chip (TASK-598→600)
2026-05-06
- ›lib/format.ts: fmtYear(d) returns 4-digit UTC year string — '2026'
- ›Smart board: many_drafts_no_hooks fires when ≥5 draft items have no hook framework assigned
- ›Analytics: Queue hook types chip shows distinct hook type count in active queue (gated ≥2 types)
fmtWords utility, queue_size_warning trigger, queue outlier rate chip (TASK-595→597)
2026-05-06
- ›lib/format.ts: fmtWords(n) formats '1,234 words' with auto-plural — convenience wrapper over fmtCount
- ›Smart board: queue_size_warning fires when ≥40 active items accumulate — WIP overload signal
- ›Analytics: Queue outlier rate chip shows % of active queue items seeded from outliers (gated ≥5 active)
fmtHours utility, no_recent_ai_calls trigger, AI cost-per-publish chip (TASK-592→594)
2026-05-06
- ›lib/format.ts: fmtHours(h) formats hours as '1h' / '2.5h' — distinct from fmtMinutes and fmtDuration
- ›Smart board: no_recent_ai_calls fires when ≥5 all-time AI calls exist but none in last 14 days
- ›Analytics: AI cost per publish chip shows all-time spend divided by published count (gated ≥3 published)
fmtDaysDiff utility, recent_high_outlier trigger, outliers-this-week chip (TASK-589→591)
2026-05-06
- ›lib/format.ts: fmtDaysDiff(from, to) returns compact day diff — '3d' or '2w', negative = '—'
- ›Smart board: recent_high_outlier fires when a ≥5× outlier from the last 14 days hasn't seeded any queue item
- ›Analytics: Outliers this week chip shows fresh outlier additions in the rolling 7-day window
fmtPercentChange utility, consecutive_publish trigger, published-this-week chip (TASK-586→588)
2026-05-06
- ›lib/format.ts: fmtPercentChange(from, to) returns signed '±N%' — returns '—' when baseline is zero
- ›Smart board: consecutive_publish fires when ≥3 items published in 7 days — positive momentum reinforcement
- ›Analytics: Published this week chip shows raw UTC Mon-Sun publish count alongside MTD
fmtMinutes utility, low_knowledge trigger, pipeline words chip (TASK-583→585)
2026-05-06
- ›lib/format.ts: fmtMinutes(m) formats minutes as '45m' or '1h 30m' — distinct from fmtMs/fmtDuration
- ›Smart board: low_knowledge fires when brain has 1-4 entries (thin context gap between empty and drought)
- ›Analytics: Pipeline words chip shows total body word count for ready-to-record + scheduled items
fmtShortDate utility, low_outlier_multiple trigger, top scheduled day chip (TASK-580→582)
2026-05-06
- ›lib/format.ts: fmtShortDate(d) returns 'May 6' — month+day without year, UTC-safe
- ›Smart board: low_outlier_multiple fires when ≥5 outliers average below 1.5× — weak swipe file signal
- ›Analytics: Top scheduled day shows the day of week with most scheduled items (gated ≥2 distinct days)
fmtISODate utility, high_voice_stale trigger, caption coverage chip (TASK-577→579)
2026-05-06
- ›lib/format.ts: fmtISODate(d) returns UTC ISO 8601 date string — '2026-05-06'
- ›Smart board: high_voice_stale fires when ≥3 active items were generated before the last voice card update
- ›Analytics: Caption coverage chip shows % of published items with captions filled (gated ≥3 published)
fmtAge utility, no_description_published trigger, description coverage chip (TASK-574→576)
2026-05-06
- ›lib/format.ts: fmtAge(d) returns compact age from date to now — '3d', '2w', '4mo', '2y'
- ›Smart board: no_description_published fires when ≥3 published items lack a description — SEO/preview copy gap
- ›Analytics: Description coverage chip shows % of published items with description filled (gated ≥3 published)
fmtRatio utility, no_captions_published trigger, avg schedule lead chip (TASK-571→573)
2026-05-06
- ›lib/format.ts: fmtRatio(a, b) normalises to ':1' form — '7/3' → '2.3:1', strips trailing .0
- ›Smart board: no_captions_published fires when ≥3 published items lack caption copy — repurpose readiness signal
- ›Analytics: Avg schedule lead chip shows average days between item creation and scheduling (gated ≥3 items)
fmtTimeOfDay utility, all_hooks_same trigger, scheduled-next-7d chip (TASK-568→570)
2026-05-06
- ›lib/format.ts: fmtTimeOfDay(d) returns time-only string like '2:34 PM' — complement to fmtDatetime
- ›Smart board: all_hooks_same fires when ≥5 published posts all use the same hook type — nudges toward variety
- ›Analytics: Scheduled next 7 days chip shows forward-looking scheduled item count for the coming week
fmtDayOfWeek utility, publish_gap_widening trigger, oldest active chip (TASK-565→567)
2026-05-06
- ›lib/format.ts: fmtDayOfWeek(d) returns full day name ('Monday') using UTC timezone
- ›Smart board: publish_gap_widening fires when the last publish gap is >2× the prior gap — early warning of slowing momentum
- ›Analytics: Oldest active item chip shows age of the stalest non-published queue item (gated at ≥7 days)
fmtMultiplier utility, no_ready_items trigger, next publish chip (TASK-562→564)
2026-05-06
- ›lib/format.ts: fmtMultiplier(n) formats a number as '3.4×', stripping trailing .0
- ›Smart board: no_ready_items trigger fires when ≥5 active items exist but none are ready-to-record — pipeline front is blocked
- ›Analytics: Next publish chip shows the soonest future scheduled item as a relative date with exact datetime hint
fmtQuarter utility, overdue_scheduled trigger, overdue chip (TASK-559→561)
2026-05-06
- ›lib/format.ts: fmtQuarter(d) formats a date as 'Q2 2026' using UTC month/year
- ›Smart board: overdue_scheduled trigger fires when ≥1 item is in scheduled state but past its scheduled_at date
- ›Analytics: Overdue scheduled chip surfaces count of past-due scheduled items inline with pipeline stats
fmtMonthYear utility, wasted_hooks trigger, published all-time chip (TASK-556→558)
2026-05-06
- ›lib/format.ts: fmtMonthYear(d) formats a date as 'May 2026' using toLocaleDateString
- ›Smart board: wasted_hooks trigger fires when ≥2 hook types each have ≥2 queued items but zero published — surfaces hook strategies that never convert
- ›Analytics: Published all-time chip shows total published count with % of queue hint
fmtDatetime utility, outlier_conversion_low trigger, outlier use rate chip (TASK-553→555)
2026-05-06
- ›lib/format.ts: fmtDatetime(d) formats date+time as 'Mon D, H:MM AM/PM' with auto year
- ›Smart board: outlier_conversion_low trigger fires when < 20% of outliers (≥10) seed queue items
- ›Analytics StatStrip: Outlier use rate chip shows % of outliers that inspired at least one queue item
fmtDecimal utility, low_hook_coverage trigger, top AI endpoint chip (TASK-550→552)
2026-05-06
- ›lib/format.ts: fmtDecimal(n, decimals, opts) formats to fixed decimals with optional zero stripping
- ›Smart board: low_hook_coverage trigger fires when < 50% of published items have hook_type classified
- ›Analytics StatStrip: Top AI endpoint chip promotes highest-spend endpoint out of hint into own slot
fmtWeek utility, publish_weekly_miss trigger, longest published chip (TASK-547→549)
2026-05-06
- ›lib/format.ts: fmtWeek(d) formats any date as 'Week of Mon D' normalised to ISO Monday
- ›Smart board: publish_weekly_miss trigger fires on Friday/weekend when nothing published that week
- ›Analytics StatStrip: Longest published chip surfaces the highest-word-count published script
fmtBool utility, no_published_this_month trigger, words published MTD chip (TASK-544→546)
2026-05-06
- ›lib/format.ts: fmtBool(v, trueLabel?, falseLabel?) renders booleans as configurable labels
- ›Smart board: no_published_this_month trigger fires when it's past the 15th with zero publishes
- ›Analytics StatStrip: Words published MTD chip shows total script word output for the current month
fmtCurrencyCompact utility, low_script_completion trigger, wordiest hook chip (TASK-541→543)
2026-05-06
- ›lib/format.ts: fmtCurrencyCompact(n) renders dollar amounts in K/M/B compact notation
- ›Smart board: low_script_completion trigger fires when script fill rate < 30% with ≥10 items
- ›Analytics StatStrip: Wordiest hook type chip shows which hook pattern produces the longest published scripts
fmtInitials utility, no_blueprint trigger, best outlier × chip (TASK-538→540)
2026-05-06
- ›lib/format.ts: fmtInitials(name, maxChars?) extracts uppercase initials from any name string
- ›Smart board: no_blueprint trigger fires when ideal client profile (ICA) has not been configured
- ›Analytics StatStrip: Best outlier × chip promotes peak multiple out of the avg hint into its own slot
fmtMs utility, identity_near_complete trigger, avg outlier views chip (TASK-535→537)
2026-05-06
- ›lib/format.ts: fmtMs(ms) formats latency as ms/s/m s with clean decimal stripping
- ›Smart board: identity_near_complete trigger fires at ≥80% quiz completion with remaining-count hint
- ›Analytics StatStrip: Avg outlier views chip shows mean views across outliers that have view data
fmtPlural utility, incomplete_scripts trigger, script fill rate chip (TASK-532→534)
2026-05-06
- ›lib/format.ts: fmtPlural(n, singular, plural?) renders count with correct noun form
- ›Smart board: incomplete_scripts trigger fires when ≥3 ready-to-record scripts are missing captions or description
- ›Analytics StatStrip: Script fill rate chip shows % of scripts with all 4 sections filled + MTD delta hint
fmtSign utility, outlier_drought trigger, inspired MTD chip (TASK-529→531)
2026-05-06
- ›lib/format.ts: fmtSign(n, fmt?) renders explicit +/− prefix with optional inner formatter
- ›Smart board: outlier_drought trigger fires when outliers exist but none added in 30 days
- ›Analytics StatStrip: Inspired MTD chip promotes outlier-seeded queue items this month to its own slot
fmtScore utility, low_outlier_views trigger, heaviest draft chip (TASK-526→528)
2026-05-06
- ›lib/format.ts: fmtScore(value, max?) formats scores as 'N/max' (e.g. 87/100, 3/5)
- ›Smart board: low_outlier_views trigger fires when ≥5 outliers have no view count data
- ›Analytics StatStrip: Heaviest draft chip shows word count + title of largest unpublished draft
fmtRange utility, no_source_url trigger, avg multiple MTD chip (TASK-523→525)
2026-05-06
- ›lib/format.ts: fmtRange(min, max, fmt?) formats numeric ranges as 'A–B' with optional formatter
- ›Smart board: no_source_url trigger fires when ≥5 active items are missing a source reference link
- ›Analytics StatStrip: Avg multiple MTD chip shows mean outlier multiple for the current month (min 2 outliers)
fmtOrdinal utility, high_cancel_rate trigger, MTD throughput chip (TASK-520→522)
2026-05-06
- ›lib/format.ts: fmtOrdinal(n) returns ordinal strings (1st/2nd/3rd/…) with correct teen-number handling
- ›Smart board: high_cancel_rate trigger fires when ≥50% of queue items are cancelled (min 5 items)
- ›Analytics StatStrip: MTD throughput chip shows published/created this month as conversion % (min 3 items)
fmtFileSize utility, linkedin_stale trigger, total LI chars stat (TASK-517→519)
2026-05-06
- ›lib/format.ts: fmtFileSize(bytes) formats byte counts as B/KB/MB/GB with .0 stripping
- ›Smart board: linkedin_stale trigger fires when posts exist but none generated in 30 days
- ›Analytics StatStrip: Total LI chars chip shows all-time LinkedIn character output with per-post avg hint
Voice stale count, pipeline depth stat, Supabase Storage check (TASK-514→516)
2026-05-06
- ›Analytics StatStrip: Voice stale chip shows scripts that need regeneration after voice card update
- ›Analytics StatStrip: Pipeline depth chip shows % of active items near recording stage
- ›Status page: Supabase Storage health check added (14th parallel probe via /storage/v1/bucket)
Brain drought trigger, queue momentum chip, outliers missing views (TASK-511→513)
2026-05-06
- ›Smart board: brain_drought trigger fires when brain has entries but none added in 30 days
- ›Analytics StatStrip: Queue momentum chip shows this-week vs last-week creation velocity
- ›Analytics StatStrip: Outliers missing views chip surfaces incomplete reference data
LinkedIn efficiency stat, hook-missing-ready trigger, Anthropic check (TASK-508→510)
2026-05-06
- ›Analytics StatStrip: LinkedIn/publish chip shows how many posts are generated per shipped script
- ›Smart board: hook_missing_ready trigger fires when ready-to-record scripts have no hook type set
- ›Status page: Anthropic AI health check added (13th parallel probe via /v1/models)
Brain freshness, outlier-to-publish rate, Pinecone status check (TASK-505→507)
2026-05-06
- ›Analytics StatStrip: Brain freshness chip shows avg age of knowledge entries
- ›Analytics StatStrip: Outlier → published chip shows what % of outlier-inspired items actually shipped
- ›Status page: Pinecone vector DB health check added (12th parallel probe via /indexes)
Most-published hook, hook coverage stat, Replicate status check (TASK-502→504)
2026-05-06
- ›Analytics StatStrip: Most published hook chip shows dominant hook type by raw published count
- ›Analytics StatStrip: Hook coverage chip shows % of published items with hook_type classified
- ›Status page: Replicate inference health check added (11th parallel probe via /v1/account)
Knowledge top kind, recording-failed API count, stale-ready trigger (TASK-499→501)
2026-05-06
- ›Analytics StatStrip: Top knowledge kind chip surfaces dominant brain category
- ›Today API: recording_failed_count added for external dashboards to surface items needing attention
- ›Smart board: stale_ready trigger fires when 2+ scripts sit in ready-to-record for 7+ days
Untitled trigger, LinkedIn QTD chip, ElevenLabs status check (TASK-496→498)
2026-05-06
- ›Smart board: untitled_items trigger fires when 2+ active queue items have no real title
- ›Analytics StatStrip: LinkedIn QTD chip appears when quarter spans multiple months of output
- ›Status page: ElevenLabs voice synthesis health check added (10th parallel probe)
Top outlier chip, queue-since date, Stripe status check (TASK-493→495)
2026-05-06
- ›Analytics StatStrip: Top outlier chip shows best-performing outlier multiple + title
- ›Analytics StatStrip: Queue since chip shows when the first item was created via fmtDate
- ›Status page: Stripe payments health check added (9th parallel probe via /v1/balance)
All-time spend stat, no-upcoming-scheduled trigger, fmtDate helper (TASK-490→492)
2026-05-06
- ›Analytics StatStrip: All-time AI spend chip appears once history exceeds current month
- ›Smart board: no_upcoming_scheduled trigger fires when scripts are ready but calendar is empty for 7 days
- ›lib/format: fmtDate() — short locale date ('May 6' or 'May 6, 2025') with auto year logic
Reference sources stat, Groq status check, voice baseline words (TASK-487→489)
2026-05-06
- ›Analytics StatStrip: Reference sources count chip surfaces how full your source library is
- ›Status page: Groq inference health check added (8th parallel probe via /openai/v1/models)
- ›Analytics StatStrip: Voice baseline word count chip shows voice signal strength
Last published chip, scheduled density, outlier age stats (TASK-484→486)
2026-05-06
- ›Analytics StatStrip: Last published chip shows 'today / yesterday / N days ago' via fmtRelativeDay
- ›Analytics StatStrip: Scheduled/week MTD chip tracks content scheduling cadence this month
- ›Analytics StatStrip: Avg outlier age chip shows how fresh your reference material is
OpenRouter status check, fmtRelativeDay helper, last-published API (TASK-481→483)
2026-05-06
- ›Status page: OpenRouter AI gateway health check added (7th parallel probe)
- ›lib/format: fmtRelativeDay() — today/yesterday/N days ago with calendar-day precision
- ›Today API: last_published_at timestamp added so external dashboards can show recency
Stuck-recording trigger, cancel rate + source coverage stats (TASK-478→480)
2026-05-06
- ›Smart board: stuck_recording trigger fires when items sit in recording status for 3+ days
- ›Analytics StatStrip: Cancel rate chip shows % of all items ever abandoned
- ›Analytics StatStrip: Source coverage chip shows % of items with a source URL attached
Published-this-week API, high draft ratio trigger, avg per week stat (TASK-475→477)
2026-05-06
- ›Today API: published_this_week added (published_at >= Monday-origin week start)
- ›Smart board: high_draft_ratio trigger fires when ≥80% of active items are stuck in draft (min 5 items)
- ›Analytics StatStrip: Avg per week chip shows long-run publishing cadence across full history
Digest email counters, analytics QTD chip, published-today API (TASK-472→474)
2026-05-06
- ›Weekly digest cron: emailsSent/emailsFailed counters tracked per user, exposed in response JSON
- ›Analytics StatStrip: Published QTD chip shown when QTD exceeds MTD — surfaces quarter momentum
- ›Today API: published_today count added (queue_items published_at within current calendar day)
Weekly digest email, digest cron wired, quarterStart helper (TASK-469→471)
2026-05-06
- ›lib/email/digest.ts: sendDigestEmail() with HTML + text renders for 6-metric weekly recap
- ›Weekly digest cron: email now fires after each user's insert via auth.admin.getUserById — fire-and-forget, failure never blocks cron
- ›lib/dates: quarterStart() added — UTC-safe, returns start of current Q1/Q2/Q3/Q4
Resend status check, fmtTruncate in LinkedIn + brain pages (TASK-466→468)
2026-05-06
- ›Status checks: checkResend() added — GET /domains probe with RESEND_API_KEY, wired as 6th parallel check
- ›LinkedIn: PostCard preview uses fmtTruncate(firstLine, 110) — replaces manual slice+concat
- ›Brain: source URL display uses fmtTruncate(url, 60) — replaces manual .slice(0,60)
Status error boundary, Fal check, fmtTruncate utility (TASK-463→465)
2026-05-06
- ›Status: error.tsx added — last public page without an error boundary
- ›Status checks: checkFal() added — HEAD ping to queue.fal.run, wired into runAllChecks()
- ›lib/format: fmtTruncate(s, maxLen, suffix?) added — null-safe truncation with configurable suffix
Error boundaries: about, pricing, legal (TASK-460→462)
2026-05-06
- ›About: error.tsx added
- ›Pricing: error.tsx added
- ›Legal: error.tsx added at app/legal/ — covers both /legal/privacy and /legal/terms via segment inheritance
Error boundaries: onboarding, login, changelog (TASK-457→459)
2026-05-06
- ›Onboarding: error.tsx added — covers both /onboarding and /onboarding/[step] via Next.js segment inheritance
- ›Login: error.tsx added — sign-in crashes now show section-labelled recovery UI
- ›Changelog: error.tsx added — public changelog page now has its own boundary
Outlier thumbnail alt text, og:image, teleprompter error boundary (TASK-454→456)
2026-05-06
- ›Outliers: thumbnail alt attribute fixed from empty string to meaningful title — accessibility improvement
- ›Layout: openGraph.images + twitter.images wired to /og.png (1200×630) — social share previews now have an image slot
- ›Teleprompter: error.tsx added — crash in beat-reader now shows correct section label instead of bubbling to queue-item boundary
Error boundaries: dashboard, queue item, settings (TASK-451→453)
2026-05-06
- ›Added error.tsx to app/dashboard — catches root dashboard crashes with section context
- ›Added error.tsx to app/dashboard/queue/[id] — catches queue item detail crashes
- ›Added error.tsx to app/settings — single boundary covers all three settings sub-pages
Identity trigger gap, today API this-week LinkedIn + overdue (TASK-448→450)
2026-05-06
- ›Smart board: no_identity_started trigger fires when identity quiz has 0 answers — fills the dead zone the existing identity_low trigger misses
- ›Today API: this_week block now includes linkedin_created count alongside outliers_added + queue_created
- ›Today API: overdue_count field added — items with a past scheduled_at that aren't published or cancelled
Stale-draft trigger, calendar MTD stat, weekly digest sources count (TASK-445→447)
2026-05-06
- ›Smart board: new 'stale_drafts' warn trigger fires when 2+ draft items haven't been touched in 14+ days
- ›Calendar: 'Scheduled this month' stat chip added to stat strip — counts future-dated items in the current calendar month
- ›Weekly digest cron: reference_sources added as 6th parallel query; sources_7d tracked in summary and persisted as sources_count
Today API this-week stats, queue captions count, orphan chunk cleanup (TASK-442→444)
2026-05-06
- ›Today API (/api/dashboard/today): new this_week block with outliers_added + queue_created counts for the current Mon–Sun window
- ›Queue: 'captioned' count shown in stat strip for items with captions generated
- ›Cleanup cron: task 8 removes orphaned reference_chunks whose source_id no longer exists in reference_sources
Brain entries MTD, LinkedIn batches MTD, queue detail source URL (TASK-439→441)
2026-05-06
- ›Brain: knowledge entries added this calendar month now shown in stats strip
- ›LinkedIn: batches generated MTD shown in stats strip alongside all-time batch count
- ›Queue item detail: 'Inspired by' section now shows a clickable ↗ source link when the outlier has a source URL
Queue published MTD stat, digest knowledge count, search reference sources (TASK-436→438)
2026-05-06
- ›Queue: 'published MTD' count shown in stat strip — tracks items published in the current calendar month
- ›Weekly digest: knowledge_entries_7d added as 5th metric alongside shipped/drafts/linkedin/outliers
- ›Search: reference_sources (books, PDFs, URLs, transcripts) now included as a 5th search table
Teleprompter loading state, empty-queue + no-LinkedIn Smart Board triggers (TASK-433→435)
2026-05-06
- ›Teleprompter page now has a loading.tsx shimmer state (centered pulse layout matching the beat reader)
- ›Smart Board: 'Queue is empty' trigger fires when a user has zero queue items
- ›Smart Board: 'No LinkedIn posts yet' trigger fires when no linkedin_posts exist for the project
Onboarding tab titles, no-outliers Smart Board trigger (TASK-430→432)
2026-05-06
- ›Onboarding root page now shows 'Get started' in the browser tab
- ›Onboarding step pages show 'Onboarding · Step N' dynamically in the browser tab
- ›Smart Board: new 'No outliers yet' trigger fires for users who haven't added any outliers, linking to /dashboard/outliers
Landing + login tab titles, empty brain Smart Board trigger (TASK-427→429)
2026-05-06
- ›Landing page now shows 'Nabila Creator Studio' in the browser tab
- ›Login page now shows 'Sign in' in the browser tab
- ›Smart Board: new 'Brain is empty' trigger fires when knowledge_entries count = 0, linking to /dashboard/brain
Dashboard, pricing, teleprompter tab titles (TASK-424→426)
2026-05-06
- ›Dashboard home now has a browser tab title 'Dashboard'
- ›Pricing page now has a browser tab title 'Pricing'
- ›Teleprompter page shows the queue item's title in the browser tab (dynamic metadata)
All-time spend stat, settings page tab titles (TASK-421→423)
2026-05-06
- ›Account: replaced misleading 'last 20' spend display with a true all-time total query across the full ai_generation_audit history
- ›Settings / Identity: browser tab now shows 'Identity' via Next.js metadata export
- ›Settings / Projects: browser tab now shows 'Projects' via Next.js metadata export
Outlier deep-link, untapped filter shortcut, LinkedIn total chars (TASK-418→420)
2026-05-06
- ›Queue item detail: 'Inspired by' link now searches for the source outlier by title instead of landing on the full outliers list
- ›Outliers: untapped count chip is now a clickable link that filters to untapped sort view
- ›LinkedIn: total characters written shown in stats strip alongside avg post length
LinkedIn avg per batch, clickable queue chips, brain sources this month (TASK-415→417)
2026-05-06
- ›LinkedIn: avg posts per batch now shown in stats strip when 2+ batches exist
- ›Queue: draft, ready, scheduled, published, today, overdue, and needs-revision chips are now clickable filter links
- ›Brain: sources added this calendar month shown as a stat in the knowledge strip
Best hook rate in StatStrip, created-this-week chip, ICS hook type (TASK-412→414)
2026-05-06
- ›Analytics: best hook type by publish rate now appears in the stats strip (previously only shown in the hook type chart section)
- ›Queue: new 'this week' chip counts items created since Monday — pairs with the existing 'created this month' chip
- ›Calendar ICS export: hook type now included in DESCRIPTION field of each calendar event
Long pipeline trigger, record time stat, median gap in analytics (TASK-409→411)
2026-05-06
- ›SmartBoard: new 'long pipeline' trigger fires when avg days from idea to publish exceeds 14 — nudges you to push a ready item through
- ›Analytics: total estimated record time shown as a separate stat (at speaking pace, ~110 WPM)
- ›Analytics: median gap between published posts now appears in the pipeline StatStrip alongside avg days to publish
Outlier source links, corpus read time, brain search (TASK-406→408)
2026-05-06
- ›Outliers: video titles now link directly to the original source when a URL is stored — opens in new tab with ↗ indicator
- ›Analytics: total words written stat now shows total corpus read time alongside avg per item
- ›Search: brain entries (knowledge rules, hook formulas, examples) now appear as a 4th search result section
Page titles, needs-revision chip, dynamic queue item tab title (TASK-403→405)
2026-05-06
- ›Browser tab titles now set on Brain, Calendar, LinkedIn Engine, Outliers, and Queue pages
- ›Queue item detail page shows the item title in the browser tab (dynamic metadata)
- ›Queue summary strip now shows needs-revision count in amber when any items are flagged
Brain embed %, dashboard velocity delta, queue scripted count (TASK-400→402)
2026-05-06
- ›Brain page: chunk stats now show embedded % inline (e.g. '42/50 — 84% embedded')
- ›Dashboard: word count strip shows week-over-week velocity delta (+N% / -N%) next to last-week figure
- ›Queue: summary strip now shows scripted count — items with both hook and body written, excl. cancelled
Ready-to-record trigger, account avg cost/call, format test coverage (TASK-398→399)
2026-05-06
- ›SmartBoard: new 'ready_piling' trigger fires when 3+ items are ready to record but nothing is scheduled
- ›Account page: avg cost per AI call shown inline with month-to-date stats (derived from existing data, zero extra queries)
LinkedIn AI Post Visual Modal Phase 1.0 + fmtCount/fmtPct/fmtDuration tests (TASK-397 + feature)
2026-05-06
- ›LinkedIn Visual Modal: Path A (GPT Image 2 via Fal AI) generates post-aware images with 4 AI prompt options, aspect ratio picker, and 3-state progress UX
- ›LinkedIn Visual Modal: Path B (template render) picks photo from Assets Library, Google Drive (Picker API), or upload, then applies Original/Quote/Headline/Split/Logo/Custom templates
- ›Suggested Photos panel scores user's asset library against post keywords and surfaces top 3 matches
- ›Moderation layer: every prompt checked via OpenAI Moderation API, every image checked via xAI vision before gen runs — safety_events table logs all blocks
- ›Cost preflight: live credit counter in modal header, per-tier monthly allotment (trial 25 / starter 200 / pro 1000), low-balance warning at <5 credits
- ›Storage cleanup: cron step 7 soft-deletes unpinned linkedin_visual assets older than 7 days
- ›Migration 012: assets table, safety_events table, linkedin_posts visual columns, users credit columns
- ›11 new API endpoints: suggest-prompt, suggest-photos, generate-from-prompt, generate-from-reference, job-status, render-template, moderate-prompt, moderate-image, credit-balance, picker-token
- ›test-format.ts: 26 new tests covering fmtCount, fmtPct, fmtDuration (51 total, all pass)
Recent-gen cost footer, untapped outliers + no-hook-type triggers (TASK-394→396)
2026-05-06
- ›Recent Generations widget shows total cost of displayed rows as a footer
- ›SmartBoard: new 'untapped outliers' trigger fires when ≥3 outliers have no queue item yet
- ›SmartBoard: new 'missing hook type' trigger fires when ≥5 items lack classification
Search results strip + clear link, calendar this-week stat (TASK-391→393)
2026-05-06
- ›Search: results count strip shows total hits broken down by section (queue · outliers · LinkedIn)
- ›Search: form gains Clear link when a query is active
- ›Calendar: StatStrip gains 'This week' count scoped to the current Mon-Sun window
Calendar past+overdue stats, LinkedIn StatStrip (TASK-388→390)
2026-05-06
- ›Calendar: StatStrip now shows past-scheduled and overdue item counts
- ›LinkedIn: inline chip strip replaced with full StatStrip — posts, batches, formats used, top format, avg post length
Clear-filter links, outlier results strip, all-time spend chip (TASK-385→387)
2026-05-06
- ›Queue: one-click 'clear' link in filter strip when any filter or search is active
- ›Outliers: N results strip with 'clear' link when search or hook filter active
- ›Dashboard: AI spend chip now shows all-time total inline alongside monthly spend
Analytics avg cost/call, peak pub day, consistency score in StatStrip (TASK-382→384)
2026-05-06
- ›Analytics: avg cost per AI call derived from MTD spend and call count
- ›Analytics: best publishing day-of-week surfaced in StatStrip with count hint
- ›Analytics: publish consistency score promoted from card to StatStrip
Queue hook-types chip, analytics AI endpoints stat, brain voice questions (TASK-379→381)
2026-05-06
- ›Queue: summary strip shows distinct hook types in use
- ›Analytics: AI endpoints count in StatStrip with top-endpoint hint
- ›Brain: voice fingerprint completion shown as N/12 in StatStrip
Analytics AI calls MTD, queue created-this-month chip (TASK-376→378)
2026-05-06
- ›Analytics: AI calls month-to-date in StatStrip with all-time hint
- ›Queue: summary strip now shows items created this calendar month
Analytics items with content + published hook types, brain URL sources (TASK-373→375)
2026-05-06
- ›Analytics: items with any written content in StatStrip with % of queue hint
- ›Analytics: published hook types count in StatStrip with total-in-queue context
- ›Brain: URL sources count in StatStrip with manual source count hint
Analytics last month + total words stats, brain custom weight (TASK-370→372)
2026-05-06
- ›Analytics: queue items created last month in StatStrip — comparison baseline for velocity
- ›Analytics: total words written in StatStrip with avg words per item hint
- ›Brain: custom weight count in StatStrip — entries with non-default cosine multiplier
Analytics avg length MTD + knowledge MTD, outliers utilization % (TASK-367→369)
2026-05-06
- ›Analytics: avg post length this month in StatStrip with post count hint
- ›Analytics: knowledge entries added this month in StatStrip
- ›Outliers: utilization % chip — inspired drafts as % of total outliers
Analytics created MTD, queue cancelled chip, outliers total views (TASK-364→366)
2026-05-06
- ›Analytics: queue items created MTD in StatStrip with velocity % vs last month hint
- ›Queue: cancelled count chip in summary strip
- ›Outliers: total views chip in summary strip — sum of views across all tracked outliers
Analytics LinkedIn MTD + posts-per-batch stats, dashboard outlier chip (TASK-361→363)
2026-05-06
- ›Analytics: LinkedIn MTD batch count in StatStrip with month-over-month % hint
- ›Analytics: avg posts per batch in StatStrip with total batches hint
- ›Dashboard: outlier count chip in header stats ('N outliers tracked')
Dashboard spend chip, analytics char trend + scripts complete (TASK-358→360)
2026-05-06
- ›Dashboard: MTD AI spend chip in header stats — shows monthly cost from ai_generation_audit
- ›Analytics: char trend MTD in StatStrip — +/- delta vs last month with direction hint
- ›Analytics: scripts complete count in StatStrip — items with both hook and body filled, % of queue hint
Analytics avg outlier multiple + knowledge total, outliers top hook (TASK-355→357)
2026-05-06
- ›Analytics: avg outlier multiple in StatStrip with best-ever hint
- ›Analytics: knowledge entries total in StatStrip with kind-count hint
- ›Outliers: top hook type chip in summary strip — most common hook type across all outliers
Analytics wasted hooks + typed queue stats, brain top kind (TASK-352→354)
2026-05-06
- ›Analytics: wasted hook types count in StatStrip — hook types with ≥2 items but zero published
- ›Analytics: typed queue count in StatStrip — items with a hook type assigned, with % of total hint
- ›Brain: top kind label in StatStrip — most frequent knowledge entry kind with entry count
Brain avg weight, queue no-hook chip, analytics untyped stat (TASK-349→351)
2026-05-06
- ›Brain: avg entry weight shown in StatStrip — cosine score multiplier across all knowledge rules
- ›Queue: 'N no hook type' chip in summary strip — flags non-template items missing hook classification
- ›Analytics: 'No hook type' StatStrip stat — count of active queue items with no hook assigned
Avg days to publish, total outlier views, queue items MTD (TASK-346→348)
2026-05-06
- ›Analytics: avg days to publish in StatStrip — already computed, now surfaced
- ›Analytics: total outlier views stat — sum across all fetched outliers
- ›Dashboard: queue items created this month chip via 16th parallel head-only query
Queue completion %, outliers max views, brain default rules (TASK-343→345)
2026-05-06
- ›Analytics: queue completion % stat — published items as share of all queue items
- ›Outliers: best views chip in summary strip alongside avg views
- ›Brain: default rules count in StatStrip with 'applied to every generation' hint
Publish streak stat, days in status, last outlier ago (TASK-340→342)
2026-05-06
- ›Analytics: publishing streak stat in StatStrip — computed inline from queue published_at
- ›Queue detail: days item has been in current status shown in status eyebrow
- ›Dashboard: last outlier detected N ago chip in header stats
Outliers this month, avg views, published time ago (TASK-337→339)
2026-05-06
- ›Outliers: 'N this month' chip in summary strip — calendar-month filter in-memory
- ›Outliers: avg views chip with separator — computed from views field, fmtCompact formatted
- ›Queue detail: published date gains relative time in parentheses and hover tooltip
Queue inspired chip, brain entries MTD, same hook type count (TASK-334→336)
2026-05-06
- ›Queue: 'N inspired' chip in summary strip — items seeded from an outlier
- ›Analytics: brain entries added this month shown in knowledge section footer
- ›Queue detail: hook type badge shows '· N others' with same hook type
Words last week, back-to-queue filter breadcrumb, top hook type (TASK-331→333)
2026-05-06
- ›Dashboard: words written last week shown inline alongside this-week count
- ›Queue: clicking an item from a filtered view preserves filter in back breadcrumb
- ›Queue: top hook type chip in summary strip — most-used hook across all items
Queue upcoming chip, avg post length MTD, reference sources count (TASK-328→330)
2026-05-06
- ›Queue: 'N in next 7d' chip in summary strip — scheduled items due within 7 days
- ›Analytics: avg LinkedIn post length this month vs last month with +/-c delta card
- ›Dashboard: reference sources saved count chip alongside brain entries
Top AI endpoint, outliers this week, avg read time (TASK-325→327)
2026-05-06
- ›Analytics: top AI endpoint by MTD spend shown as callout card
- ›Outliers: detected this week count in summary strip (7-day rolling window)
- ›Analytics: avg read time estimate added next to avg words/item chip
Untapped outliers, brain entries chip, all-time AI calls (TASK-322→324)
2026-05-06
- ›Outliers: untapped count (0 inspired drafts) shown in summary strip
- ›Dashboard: brain knowledge entries count chip in header stats
- ›Analytics: MTD spend hint now shows calls MTD + all-time call count
Brain sources count, ⌘A select-all, outlier MTD avg multiple (TASK-319→321)
2026-05-06
- ›Brain: reference sources section shows total count + last-added timestamp
- ›Queue multi-select: ⌘A / Ctrl+A selects all visible rows instantly
- ›Analytics: outliers this month hint now shows avg multiple alongside used count
Outliers this week, brain last-added, script completion delta (TASK-316→318)
2026-05-06
- ›Dashboard: outliers added this week chip alongside weekly created/published stats
- ›Brain: 'last added X ago' timestamp in knowledge entries section header
- ›Analytics: script completion this-month vs last-month delta beneath the stat
Status pill %, outlier max multiple, queue detail context (TASK-313→315)
2026-05-06
- ›Analytics: status pills show count + percentage of total queue items
- ›Outliers: max multiple chip in summary strip alongside avg multiple
- ›Queue detail: ghost 'N others in same status' context in status eyebrow
Escape deselect, LinkedIn MTD trend, words this week (TASK-310→312)
2026-05-06
- ›Queue multi-select: press Escape to clear all selected rows instantly
- ›Analytics: LinkedIn batches this month vs last month with trend badge
- ›Dashboard: words written this week chip above the monthly words stat
Queue date tooltip, brain entry count, dashboard LinkedIn MTD (TASK-307→309)
2026-05-06
- ›Queue list: hover any date to see relative age (e.g. '3 days ago') as tooltip
- ›Brain: total knowledge entry count shown inline next to section header
- ›Dashboard: LinkedIn batches generated this month chip below words stat
All-time cost footnote, brain kind breakdown, outlier tier distribution (TASK-304→306)
2026-05-06
- ›Dashboard: all-time AI spend shown as footnote beneath monthly CostMeter
- ›Analytics: brain knowledge entry kind breakdown bar chart (new Brain knowledge section)
- ›Analytics: outlier multiple tier distribution (< 2× / 2–3× / 3–5× / 5×+) inside Outlier mix
Recent published list, brain ingest date, monthly outliers (TASK-301→303)
2026-05-06
- ›Dashboard: last 5 published titles with dates shown inline below upcoming items
- ›Brain: reference sources show 'ingested X ago' timestamp beneath the URL
- ›Analytics StatStrip: outliers detected this month + how many became queue items
Consistency score, longest drafts, queue health pills (TASK-298→300)
2026-05-06
- ›Analytics velocity card: publish consistency % shows how many of the last 12 weeks had ≥1 published item
- ›Analytics: top 3 longest unpublished drafts by word count — shows what heavy work is sitting unreleased
- ›Dashboard: queue health pill row links to draft / ready / recorded / scheduled filtered views with live counts
DOW peak label, showing N of M, hook efficiency (TASK-295→297)
2026-05-06
- ›Analytics DOW chart: peak day label is bold + dark; caption now reads 'Best day: X · N published'
- ›Queue list: filter ghost line shows 'Showing N of M' total so you know scope at a glance
- ›Analytics hook table: each row now shows avg total words per published item of that type
Wasted hooks, monthly words chart, publish gap alert (TASK-292→294)
2026-05-06
- ›Analytics: warns on hook types with 2+ items drafted but zero ever published
- ›Analytics: words-published-per-month bar chart for the last 6 calendar months
- ›Dashboard: publishing gap alert fires after 7+ days without shipping (only when streak is 0)
Hook count badge, longest published, edited ago (TASK-289→291)
2026-05-06
- ›Queue rows: hook type pill now shows (N) count when multiple items share the same hook pattern
- ›Analytics: 'Longest published' callout shows the published item with the most total words
- ›Queue list: draft rows show 'edited X ago' from updated_at so stale work is visible at a glance
Words this month, updated sort, avg words per item (TASK-286→288)
2026-05-06
- ›Dashboard: 'N words written this month' chip derived from published items in the current calendar month
- ›Queue list: new 'Edited ↓' sort pill orders by updated_at DESC, surfacing recently touched drafts
- ›Analytics total words card: ~N avg/item chip shows average word count across all items with content
Total words written card, explicit word count, stale count (TASK-283→285)
2026-05-06
- ›Analytics: highlight card shows total words written across all queue items with hook / body / captions / description breakdown chips
- ›Queue detail: word count progress now shows explicit 'X / 1,300w · N%' instead of just a percentage
- ›Queue list header stats: stale draft count shown when any drafts have had no progress in 30+ days
Caption/desc words, related queue by hook type (TASK-280→282)
2026-05-06
- ›Analytics StatStrip now shows caption words and description words written alongside hook and body counts
- ›Queue detail shows a Same hook type section linking to up to 4 other items sharing the same hook pattern
Body words, stale draft tag, kind select (TASK-277→279)
2026-05-06
- ›Analytics StatStrip now shows total body words written alongside hook words
- ›Queue list flags drafts with no progress in 30+ days with a ghost stale tag
- ›Brain knowledge entry kind is now an inline dropdown — change without leaving the page
Template border, inspired tag, hook word count (TASK-274→276)
2026-05-06
- ›Queue list template rows now have a subtle brass border and background — visually distinct from regular items
- ›Queue rows seeded from an outlier show a ✦ outlier tag so you can see which ideas came from research
- ›Analytics StatStrip shows total hook words written across all queue items
Top hook callout, source rename, created-ago (TASK-271→273)
2026-05-06
- ›Analytics highlights your best-converting hook type by publish rate with a callout card below the breakdown
- ›Brain reference sources support click-to-rename inline editing — same optimistic pattern as knowledge entries
- ›Queue detail header shows how long ago the item was created with a full timestamp on hover
Conversion rate, inline edit, filter count (TASK-267→269)
2026-05-06
- ›Analytics StatStrip shows how many queue items were inspired by outliers and the conversion rate
- ›Brain knowledge entries support click-to-rename inline editing with optimistic update and re-embedding on save
- ›Queue list shows a Showing N breadcrumb with active filter and search when the view is narrowed
Hook badge, overdue alert, publish rate (TASK-263→265)
2026-05-06
- ›Queue detail header shows hook type as a pill badge alongside the state label — no scrolling required
- ›Dashboard shows an amber overdue banner when scheduled items are past their date without being published
- ›Analytics hook type breakdown gains a publish rate % column — shows which hook types actually ship
Copy, creation rate, publish cadence (TASK-259→261)
2026-05-06
- ›Queue detail header now shows a Copy Title button alongside the item title
- ›Dashboard header shows queue items created this week vs last week — separate from published count
- ›Analytics velocity card adds median gap between consecutive publishes (days between posts)
Signal + dismiss wave (TASK-255→257)
2026-05-06
- ›Analytics StatStrip adds Published MTD count — items with published_at in the current calendar month
- ›Queue detail completeness bar segment tooltips now show word count per section (e.g. 'Hook: 120w') instead of just 'complete'
- ›Outliers page gains per-card dismiss (×) button — hides cards via localStorage with show/hide/clear-all panel, no DB migration
Velocity + UX wave (TASK-251→253)
2026-05-06
- ›Analytics Content velocity card adds content gap stat — days since last published, tinted orange when > 14 days
- ›Queue detail section headers (Hook / Body / Captions / Description) now show estimated read time alongside word count
- ›Queue list adds Newest / Scheduled ↑ sort toggle in the filter bar — URL-based, preserves active filter and search
Detail + context wave (TASK-247→249)
2026-05-06
- ›Brain kind filter pills now show entry count badges per kind (All + each kind type)
- ›Queue detail shows a LinkedIn caption copy button in the action bar when captions.linkedin exists — no scrolling required
- ›Queue detail source outlier backlink now shows the outlier multiple (N.Nx) alongside the title
Signal + compose wave (TASK-243→245)
2026-05-06
- ›Analytics queue items by hook type bar now shows avg hook word count (Nw avg) per type
- ›Dashboard header shows this-week vs last-week published count — last week tinted orange when you're behind
- ›Queue detail adds an X thread snippet panel — 3-tweet format from hook opener + core insight + takeaway, one-click copy
Velocity + detail wave (TASK-239→241)
2026-05-06
- ›Analytics shows script completion rate — % of non-cancelled queue items with all 4 script sections filled, displayed in the Content velocity card
- ›Dashboard upcoming items now show a countdown label (today / tomorrow / in Nd) next to each scheduled date, tinted amber when within 24 hours
- ›Queue detail adds a collapsible YouTube thumbnail description panel — composed from title + first two hook lines, one-click copy, no AI call
Signal + detail wave (TASK-235→237)
2026-05-06
- ›Analytics outlier hook-type bar now shows average outlier multiple (avg N×) per hook type alongside count
- ›Brain knowledge entries support text search — filter by title with a GET search form that preserves the active kind filter
- ›Queue detail Prev/Next navigation supports [ and ] keyboard shortcuts — hint glyphs appear inline in the nav links
Signal + UX wave (TASK-230→233)
2026-05-06
- ›Queue detail script header shows total char count alongside word count ('· N chars')
- ›Analytics adds queue items by hook_type horizontal bar chart above the outlier hook types card
- ›Queue list gets a 'Select all N' / 'Deselect all N' checkbox above the rows — works with existing bulk action bar
- ›LinkedIn summary strip shows all-time batch count when it exceeds the loaded window
Polish wave (TASK-227→228)
2026-05-06
- ›Queue detail script header adds estimated recording time pill at 110 WPM (on-camera pace) alongside the existing read-time pill
- ›LinkedIn batch list shows 'Copy all N batches as MD' button when more than one batch loaded — joins all with --- separators
Detail + signal wave (TASK-222→224)
2026-05-06
- ›Queue detail script sections now show per-section word counts ('Nw') next to each section header — hook, body, captions, description
- ›Dashboard adds a published-per-week sparkline (8-week TimelineChart) above SmartBoard — zero extra queries, from already-fetched pubDates
Signal + cleanup wave (TASK-218→220)
2026-05-06
- ›Dashboard header now shows total published count ('N published total') below the last-ship row — exact count, not capped at 90
- ›Brain reference sources panel gets 'Delete all N' button (shown when > 1 source) matching the knowledge entries bulk delete
- ›LinkedIn format mix pills now show per-format avg char count inline — e.g. 'Story · 4 · 1,102c'
Outlier add-rate sparkline (TASK-216)
2026-05-06
- ›Analytics page now shows outlier add-rate per week as a 12-week TimelineChart, sitting alongside the queue items created sparkline
Polish + data wave (TASK-212→214)
2026-05-06
- ›LinkedIn batch headers show avg char count with color coding (grey = in sweet spot, orange = near ceiling, burgundy = above 1300)
- ›Analytics adds queue items created per week sparkline (12 weeks, TimelineChart) between content velocity and DOW chart
- ›Brain knowledge entries panel gets 'Delete all N' button when more than one entry — confirm dialog guards the action
Small wins wave (TASK-208→210)
2026-05-06
- ›Analytics StatStrip adds avg LinkedIn post char count with sweet-spot hint (in sweet spot / near ceiling / above sweet spot)
- ›Outlier cards show 'added X ago' relative date in the pill strip — hover shows exact date
- ›Queue list rows now have a Copy Title button — one click to clipboard without opening the detail
Navigation + discovery wave (TASK-204→206)
2026-05-06
- ›Outliers page adds 'Untapped' sort — outliers with 0 inspired drafts surface first (sorted by multiple desc as tiebreak), great for finding unused high-performers
- ›Dashboard shows 'Last ship' row below streak — most recent published item title + date, pulled from existing pubDates query (added title field)
- ›Calendar day cells with items are now clickable links to queue filtered by that date — title shows the day name + date
Action + search wave (TASK-200→202)
2026-05-06
- ›Dashboard shows 'N items ready to record or publish' callout with link to queue — zero extra queries, computed from already-fetched queueItems
- ›Analytics content velocity card now includes pipeline velocity: avg days from draft creation to publish date
- ›LinkedIn batch search — type a keyword to filter batches by focus angle (ilike, up to 50 results, clear link)
Context + clarity wave (TASK-195→198)
2026-05-06
- ›Dashboard shows orange streak-at-risk warning when active streak + no publish in >48h — links to queue to act
- ›Analytics shows top-3 published hook types as ★ pill strip (hook_type added to queue select, zero extra queries)
- ›LinkedIn batch headers show post count (N posts) next to timestamp
- ›Queue list rows show hook_type as a small pill under the title when set — lets you scan script types at a glance
Signal + detail wave (TASK-191→193)
2026-05-06
- ›Outliers page summary strip: total in view / hook types present / avg outlier multiple / inspired drafts — zero extra queries, computed from already-fetched data
- ›Queue detail published_at date shown inline in status eyebrow when status = published (e.g. 'PUBLISHED · May 6, 2026')
- ›LinkedIn format checkboxes show historical post count (N×) next to each format label — helps pick formats you've used before
Surface + strip wave (TASK-187→189)
2026-05-06
- ›Queue summary strip now shows overdue count in burgundy (counts.overdue already computed from TASK-173)
- ›LinkedIn page header stats — total posts / batches / formats used, shown when posts > 0, zero extra DB queries
Detail depth wave (TASK-184→185)
2026-05-06
- ›Queue item detail page gets a Duplicate button (action already existed on list page — wired here too)
- ›Queue item detail shows 'Inspired by [outlier title] →' when item was seeded via the Inspire button
Polish + power wave (TASK-180→182)
2026-05-06
- ›LinkedIn batch headers now show focus angle as subtitle + copy button (was fetched but never rendered)
- ›Queue detail script view gets a word count progress bar toward 1300-word 10-min target — brass fill while building, forest-700 when done
- ›Outliers bulk delete by hook type — visible when a hook type filter is active, deletes all matching outliers for the project
Links + signals wave (TASK-176→178)
2026-05-06
- ›Queue detail 'LinkedIn posts →' link — opens LinkedIn engine with item title pre-filled as source via ?source= searchParam
- ›Analytics avg outlier multiple trend sparkline — weekly average in Outlier mix section, 12-week window, zero extra DB query
- ›Queue page 'n' keyboard shortcut — press n anywhere to focus the add-title input (placeholder hint shown)
Filters + funnel wave (TASK-173→174)
2026-05-06
- ›Queue 'Overdue' filter preset — ⚠ Overdue pill shows items past scheduled date, ordered by most overdue first, count badge from existing allRows query
- ›Analytics queue funnel — 5-stage bar chart (Draft → Ready → Recorded → Scheduled → Published) with count and % of total per stage, zero extra DB query
Discovery + scheduling wave (TASK-169→171)
2026-05-06
- ›Dashboard 'Coming up' widget — next 3 future scheduled items below Today panel, links to item detail, 'View all →' to queue
- ›Analytics outlier hook types bar chart — horizontal bars showing hook type distribution across all outliers, zero extra DB query
- ›Outliers 'Most inspiring' sort — third sort option orders by number of queue drafts seeded from each outlier
Urgency + signals wave (TASK-164→167)
2026-05-06
- ›Queue rows show urgency: orange pulse dot + 'due today' for items scheduled within 24h, burgundy 'overdue' label for past-due items not yet published
- ›LinkedIn format mix highlights top format with forest-700 badge and ★ star
- ›Script completeness bar on queue detail — 4-segment visual (Hook / Body / Captions / Description), zero extra DB queries
Momentum + signal wave (TASK-159→162)
2026-05-06
- ›Publishing streak counter on dashboard — consecutive published days, 3/7/14-day tiers (building momentum / on a roll / unstoppable), shown below greeting
- ›Outlier cards show 'inspired N drafts' count — counts queue items linked via source_outlier_id; zero-query (single fetch + in-memory group)
- ›Calendar month grid gap weeks — empty future week rows tinted orange/dashed with tooltip + gap count label below each month
- ›Analytics day-of-week publishing pattern — 7-bar chart (Mon–Sun), peak day darkened, all-time published items; zero extra DB queries
Polish + data wave (TASK-154→157)
2026-05-06
- ›HANDOFF.md refreshed through TASK-153 — four shipped waves, 93 tests, next free TASK-154
- ›Outliers hook-type filter pills — distinct-types query shows only types present in your data; preserves sort + search state across pill clicks
- ›Analytics content velocity card — this-month vs last-month queue creation count with TrendBadge delta; zero extra DB queries (computed from already-fetched queue rows)
- ›Queue list inline ☆/★ template toggle — flips is_template in place without leaving the list; replaces duplicate-as-template copy action
- ›lib/dates.ts: lastMonthStart() helper
Interaction polish wave (TASK-149→152)
2026-05-06
- ›Script section inline history preview — native <details> collapse shows previous version before reverting (zero JS, zero bundle cost)
- ›Queue page status summary strip — mono row above filter pills: total, draft, ready, scheduled, today, published, template counts
- ›LinkedIn post cards collapse by default — format + first-line preview in summary, expand to see full text and actions
- ›Smart Board trigger snooze — × button on each trigger snoozes for 7 days via httpOnly cookie, no DB migration
UX depth wave (TASK-143→147)
2026-05-06
- ›Script read-time estimator — word count + m:ss read pill in Script Studio header and teleprompter top bar (130 WPM on-camera pace)
- ›Outlier 'Inspire →' button — one click creates a draft queue item seeded with outlier title and hook-type prefix, lands on generate-ready detail page
- ›Related outliers panel on queue item detail — cosine-similarity match of item title against saved outliers (threshold 0.5, top 4, graceful degrade pre-migration)
- ›Dashboard today panel inline quick-publish — '✓ Publish' button directly on scheduled/recorded rows, no trip to queue detail
- ›26 new unit tests for lib/format.ts helpers (scriptWordCount, fmtReadTime, fmtCompact, fmtList) — 93 total passing
- ›HANDOFF.md refreshed through TASK-142, LESSONS.md +9 entries
Quality + power-user wave (TASK-128→140)
2026-05-06
- ›Per-route error boundaries on 7 dashboard routes via shared <RouteError/> primitive (queue, linkedin, brain, calendar, outliers, analytics, search)
- ›wrapAction() server-action error wrapper — catches thrown errors, logs with action name, rethrows Next.js redirect/notFound control-flow
- ›Weekly digest cron (Sunday 14:00 UTC) — per-user 7-day recap (scripts shipped / drafts / LinkedIn / outliers) persisted to weekly_digests table
- ›Multi-select queue checkboxes — per-row checkbox + sticky bulk action bar (→ Ready / Scheduled / Published / Cancelled / Delete). bulkDeleteByIds + bulkTransitionByIds actions.
- ›LinkedIn per-format weekly sparklines — top-4 formats over 90 days in 2x2 grid of TimelineCharts (brass tone)
- ›Voice fingerprint radar on Brain page — 4-axis SVG polygon (Identity / Audience / Positioning / Delivery) + per-stage progress bars
- ›Onboarding tutorial overlay — 3-step localStorage-gated walkthrough (fires once on first /dashboard visit, 900ms delay, progress dots nav)
- ›Calendar month grid — 7-column Mon-first layout for current + next month, item count badges + status dots per day
- ›Outlier semantic similarity search — vector fallback when ILIKE returns 0 results, match_outliers() RPC, 50/night embedding backfill via cron
- ›Sentry error capture wired — instrumentation.ts + client/server/edge configs, captureException in GlobalError + RouteError with section tag
- ›Weekly output cadence sparklines on analytics page — queue items created + LinkedIn batches per week, 12-week window
- ›67 unit tests passing, voice lint clean, build clean, GitNexus 3745/4800/132
Analytics + bulk + auto-tag wave
2026-05-06
- ›/dashboard/analytics page: aggregated brand health + queue status pills + outlier hook-type distribution + top performers across active project
- ›Analytics added to DashboardNav (8th tab)
- ›<TimelineChart/> SVG sparkline component (no deps) — wired onto queue detail to show views-over-time when ≥2 snapshots
- ›bulkTransitionByStatus(from, to) action — 'Lock all N drafts as ready to record' button on queue page filter=draft
- ›Outlier hook_type auto-detect — 14 weighted regex patterns across 8 archetypes. User-supplied tag still wins.
- ›/api/projects cross-project list JSON — counts queue + LinkedIn + outliers per project, marks active
- ›test:lib expanded to 54 assertions covering hook-detect heuristic
Power-user wave
2026-05-06
- ›Global search at /dashboard/search across queue + outliers + LinkedIn batches
- ›Search added to DashboardNav as 7th tab + matching loading skeleton
- ›Tone-tinted status pills on queue list (mint = published, orange = needs revision, burgundy = recording failed, brass = active states)
- ›VoiceLinter client island on identity page — paste prose, see em-dash count + triplet detection live
- ›/about marketing page — bio, product story, voice rule manifesto, operating principles
- ›Keyboard shortcuts: g+h home, g+q queue, g+o outliers, g+c calendar, g+l linkedin, g+b brain, g+s search, g+a/i/p settings, / search, ? help overlay (Esc close)
- ›lib/queue/badges.ts STATE_TONE map — locked palette for status pills
Discipline 80/20 + Phase 1 close-out
2026-05-06
- ›GitNexus indexed (3402 nodes / 4242 edges / 107 flows). gitnexus_impact + detect_changes wired pre-commit.
- ›TodoWrite per wave + TASK-XXX commit prefixes (post-Phase-1 = TASK-100+ namespace) — TASK-100 through TASK-114 logged in PROJECT_SPEC.md §11.
- ›TASK-101: <Section/> migration on account export + sign-out + brain reference sources.
- ›TASK-102: <Eyebrow/> primitive sweep across 7 components + 11 pages (~25 inline call sites collapsed).
- ›TASK-103: calendar uses lib/dates helpers (todayStart, daysFromNow, mondayOf extracted).
- ›TASK-111: Lighthouse perf — non-blocking Google Fonts via <link>, preconnect to fonts subdomains, dns-prefetch for x.ai + openai.
- ›TASK-112: EU cookie banner client island (essential-cookies notice, localStorage ack, no tracking complexity).
- ›TASK-113: beta waitlist form on /, migration 009_WAITLIST.sql, joinWaitlist server action with IP hash + UA capture.
- ›TASK-114: bug bash sweep — defense-in-depth user_id scope on 3 queue_items.update sites, JSON.parse guard in lib/knowledge/load, NaN guard on admin/backfill-embeddings limit param.
Inline actions + analytics surfacing
2026-05-06
- ›Calendar inline ✓ Publish on today/past scheduled rows (skip the queue-detail trip)
- ›LinkedIn page format-mix rollup (which formats Nabila leans on / underuses)
- ›PostCard char count tinted by 1100/1300 budget (forest → orange → burgundy)
- ›BrandHealth surfaces total likes + comments engagement line
- ›Identity completion meter shows 'Last edit: N days ago' via fmtRelativeDate
- ›DashboardNav project name truncates at 12 chars + tooltip
- ›EmptyState accepts optional eyebrow
- ›SmartBoard trigger when voice baseline <75 words (~30s thin fingerprint)
- ›lib/dates coverage in test:lib (45/45 passing)
Banner + flow + cron wave
2026-05-06
- ›<Banner/> primitive (info / warn / danger / success) — migrated dashboard placeholder + plan-changed + paused, queue + linkedin cap-reached banners
- ›Queue detail prev/next sibling navigation with N/M position counter
- ›<Section/> accepts description prop
- ›lib/format: fmtList helper (truncated list with '+ N more')
- ›Cron auto-cancels empty drafts older than 60 days (status=draft AND no hook+body AND updated_at <60d)
- ›<TrendBadge/> accepts delta prop alongside pct (raw counts vs ratios)
Primitives + UX polish wave
2026-05-06
- ›<Eyebrow/> primitive (mono uppercase tone-tinted label) — propagated to PageHeader, Section, DangerZone
- ›<NavPill/> primitive — migrated brain kind filter, queue 7-pill filter, outliers 2-pill sort
- ›Queue page: '📤 Today' filter pill (scheduled today only)
- ›Queue page: 'Cancelled' filter exposed in preset row
- ›Queue rows: scheduled + published dates use fmtRelativeDate ('today' / 'in 3 days' / '5 days ago')
- ›Brain sources: ⌘ Inspect link to /api/brain/sources/[id] chunks JSON
- ›/api/queue/[id]/snapshots returns aggregate metrics block (latest views/ctr/retention, totals, averages)
- ›Changelog + pricing loading skeletons (final 2 routes, complete coverage)
- ›lib/format: fmtRelativeDate + extended test suite (26 assertions all passing)
Composition wave
2026-05-06
- ›<Section/> wrapper for glass-card sections (Profile + Quick links migrated)
- ›<TrendBadge/> primitive for up/down/flat deltas
- ›<EmptyState/> migration on LinkedIn + Outliers (every empty surface now uses the same primitive)
- ›Now Recording callout on dashboard (orange-pulsing banner when status=recording, deep-links to teleprompter)
- ›Queue state machine shortcut transitions (recorded→published, scheduled→published, published→revived)
- ›lib/voice/scrub smoke tests + tightened triplet detector regex (12/12 pass)
- ›scripts: npm run check (typecheck + lint:voice + lint), npm run test:voice
- ›PUBLIC_PATHS covers all bot-crawled assets (sitemap, robots, manifest, opengraph)
- ›Middleware preserves ?next= path through login redirect
- ›SmartBoard trigger when identity completion <50%
- ›/api/dashboard/today includes recording state + identity completion
External APIs + helpers wave
2026-05-06
- ›/api/dashboard/today: one-stop daily snapshot (today items, triggers, BrandHealth, identity completion, MTD spend)
- ›/api/queue/[id]/snapshots: per-item analytics history JSON
- ›requireUserAndProject() helper kills 8+ inline auth+project resolutions
- ›lib/dates.ts: todayStart, monthStart, daysFromNow, last7StartMs etc
- ›lib/voice/completion.ts shared identity completion calc
- ›BrandHealth shows 7d vs prior-7d cadence delta with new <TrendBadge/>
- ›SmartBoard trigger for cadence drop (>50% week-over-week)
- ›scrubVoice triplet detector + chat() warn-only guard
- ›Bulk mark overdue scheduled as published
- ›Duplicate as template combined action
- ›Onboarding step loading skeleton (closes skeleton coverage)
Component library + LinkedIn regen
2026-05-06
- ›<PageHeader/> across every dashboard + settings page (eyebrow + serif title + description)
- ›<StatStrip/> for 3-up + 4-up stat blocks (calendar, brain)
- ›<EmptyState/> for empty surfaces (calendar, queue empty), CTA-paired
- ›<DangerZone/> for destructive panels (identity reset, account delete)
- ›requireUser() helper kills 50+ inline createClient + getUser duplications
- ›lib/format.ts adoption: BrandHealth, CostMeter, RecentGenerations, account, outliers, queue all switched
- ›Single-post regen on LinkedIn batch (cost ~1/7 of full batch regen)
- ›Centralised changelog at lib/changelog/entries.ts (RSS + page share source)
- ›/api/account/usage JSON snapshot (plan, MTD, per-endpoint, 14-day buckets) for external dashboards
Design lock + format helpers
2026-05-06
- ›DESIGN-LOCK.md committed (hybrid mode, Editorial Known Club color/type + Linear/Vercel layout patterns)
- ›Linear-pattern display tracking on every text-4xl/5xl/6xl heading
- ›Editorial focus rings + brass selection (a11y + brand)
- ›Shadow-as-border on .glass (no more 1px border, smoother rounded corners)
- ›.btn-primary / .btn-secondary / .btn-ghost ladder with shadow-as-border + active states
- ›.input-pill / .input-card / .input-pill-sm form classes (replaced 30+ inline chains)
- ›lib/format.ts: fmtCurrency, fmtCount, fmtPct, fmtDuration, fmtCompact, timeAgo
- ›RSS feed at /feed.xml + auto-discovery via metadata alternates
Voice + infra wave
2026-05-06
- ›Markdown builders extracted to lib/markdown/builders.ts (single source for script + LinkedIn batch serialisers)
- ›GDPR export now parallel (16 tables fetched concurrently)
- ›Voice rule scrubber at lib/voice/scrub.ts: strips em/en dashes at gen-time (chat() guard), URL ingest, manual knowledge add, queue title create
- ›All UI prose, AI prompts, MD output purged of em-dashes
- ›Dynamic OG image at /opengraph-image (1200x630 brand-coloured) + summary_large_image Twitter card
- ›RFC 9116 /.well-known/security.txt for responsible disclosure
- ›14-day spend sparkline on account page (pure CSS bars)
- ›PWA manifest (Add to home screen, start at /dashboard, brand colours)
- ›Today panel on dashboard (mint callout for items scheduled today)
- ›ICS events now include Hook line so calendar previews show angle
- ›Loading skeletons across every authenticated route (no more blank flash)
- ›scripts/lint-voice.sh + npm run lint:voice (Perl Unicode regex catches em/en dashes; CI-ready)
- ›Welcome email scrubs user-supplied one-liner
Compound polish wave
2026-05-05
- ›Copy-to-clipboard buttons across LinkedIn posts, every script section, full script as Markdown, and entire LinkedIn batch as Markdown
- ›Reusable <CopyButton/> client island (navigator.clipboard + execCommand fallback)
- ›Duplicate queue item action (clones content as a fresh draft, redirects to new item)
- ›Smart sort per filter: scheduled = scheduled_at asc, published = published_at desc, else created_at desc
- ›Date-aware row markers: 📅 scheduled date / ✓ published date
- ›Outlier title search + sort toggle (top performers vs most recent)
- ›Calendar 3-stat bar: next 7d / next 30d / total scheduled, with today row highlight
- ›ICS calendar feed at /api/calendar/ics, sync to Google/Apple/Outlook
- ›Brain page: chunk + embed status pill per source, ↻ Re-ingest button when chunks=0, kind filter, weight controls (+/−), 3-stat bar
- ›Identity completion meter (answered Q's vs total, color-coded progress bar)
- ›Project list shows content counts (queue items + LinkedIn batches per project)
- ›Account month-to-date AI spend + per-endpoint breakdown chips
- ›Brand Health snapshot freshness pill (today / Nd ago, mint/brass/orange tint)
- ›2 new SmartBoard triggers: scheduled-overdue + stale-analytics
- ›SmartBoard items now link to queue detail
- ›Cron auto-backfills reference_chunks embeddings (≤100/night)
- ›Path A 12-Q wizard with Web Speech voice baseline
- ›Brand Blueprint generator + 5-axis Authority Radar
- ›Outliers manual paste (URL → auto-thumbnail + outlier-multiple)
- ›AI Generate Script (7-step Hook + CRAFT body + 3 captions + 150-word YT description) via xAI Grok-3
- ›Per-section regen (~40% cost vs full)
- ›LinkedIn 7-format batch (story / listicle / framework / contrarian / data_insight / quick_win / founder_receipt)
- ›Cross-pollinate: Send Script to LinkedIn from queue detail
- ›12-stage state machine + Smart Board action triggers (cap / trial / cadence / voice-stale / drafts pile / recording-failed)
- ›Calendar week view + scheduled_at picker
- ›Teleprompter Mode A (auto-scroll, speed slider, mirror, 90s countdown)
- ›Manual performance entry per published item + Brand Health widget (trend, cadence, top performers)
- ›My Brain hub: knowledge entries + reference sources with auto-URL ingest, chunk, embed, retrieve
- ›Real RAG over saved knowledge + reference chunks (cosine similarity × user weight)
- ›Cost tracking + tier-cap enforcement + idempotency on every AI endpoint
- ›Multi-project switcher (Bengali + English isolation, accent_color personalization)
- ›Pricing 4-tier UI + plan switcher + pause/resume
- ›Trial countdown banner + starter checklist
- ›Public status page (4-vendor live health probe)
- ›GDPR data export + soft-delete account (30d recovery)
- ›Welcome email via Resend on onboarding completion
- ›Daily Vercel Cron: cleanup + auto-backfill embeddings
- ›Privacy + Terms with sub-processor table