feat(linkedin): progressive onboarding — hide score until 3+ posts, suppress voice guardian noise
- session-start.mjs: count published posts, gate personalization score display and reminder behind >= 3 published posts - voice-guardian.md: suppress LOW CONFIDENCE messages, silently skip drift scoring when < 5 samples - state-file.template.md: add "general" default for expertise_areas - onboarding.md: show friendly defaults message for new users, move score dashboard to returning-user flow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d7a562fc45
commit
8606abf5ee
4 changed files with 44 additions and 6 deletions
|
|
@ -22,6 +22,21 @@ Read `~/.claude/linkedin-thought-leadership.local.md` for current state.
|
||||||
|
|
||||||
**Already onboarded check:** If `first_post_date` is set (not null) AND personalization score > 50:
|
**Already onboarded check:** If `first_post_date` is set (not null) AND personalization score > 50:
|
||||||
- Show: "You've already completed onboarding (first post: [date], personalization: [score]%)."
|
- Show: "You've already completed onboarding (first post: [date], personalization: [score]%)."
|
||||||
|
- If `## Recent Posts` has 3+ entries, show the personalization score dashboard:
|
||||||
|
```
|
||||||
|
Personalization Score: [XX]%
|
||||||
|
|
||||||
|
Category Weight Status
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
Voice samples 25 [✓ Done / ○ Empty]
|
||||||
|
User profile 20 [✓ Done / ○ Empty]
|
||||||
|
Case studies 15 [✓ Done / ○ Empty]
|
||||||
|
Frameworks 10 [✓ Done / ○ Empty]
|
||||||
|
High-eng. posts 10 [✓ Done / ○ Empty]
|
||||||
|
Demographics 8 [✓ Done / ○ Empty]
|
||||||
|
Engagement patterns 7 [✓ Done / ○ Empty]
|
||||||
|
Post templates 5 [✓ Done / ○ Empty]
|
||||||
|
```
|
||||||
- Use AskUserQuestion: "Would you like to re-run a specific phase?"
|
- Use AskUserQuestion: "Would you like to re-run a specific phase?"
|
||||||
1. Re-optimize profile (360Brew) → jump to Phase 1
|
1. Re-optimize profile (360Brew) → jump to Phase 1
|
||||||
2. Improve personalization → jump to Phase 2
|
2. Improve personalization → jump to Phase 2
|
||||||
|
|
@ -68,6 +83,20 @@ After each item, ask if done or needs to skip. Don't block — mark skipped item
|
||||||
╚═════════════════════════════════════════════╝
|
╚═════════════════════════════════════════════╝
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Count published posts by checking `## Recent Posts` entries in state file.
|
||||||
|
|
||||||
|
**If fewer than 3 published posts (new user):**
|
||||||
|
|
||||||
|
Show: "Your plugin is ready to use with sensible defaults. Personalization makes content more authentic — we'll suggest improvements after you've published a few posts."
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
1. **Set up voice profile** (optional, recommended later) — 5 questions about your writing style
|
||||||
|
2. **Set up user profile** (optional, recommended later) — Your name, industry, expertise areas
|
||||||
|
3. **Both** — Do voice + user profile now
|
||||||
|
4. **Skip for now** — Use defaults, I'll run `/linkedin:setup` when ready
|
||||||
|
|
||||||
|
**If 3+ published posts (returning user):**
|
||||||
|
|
||||||
Calculate personalization score:
|
Calculate personalization score:
|
||||||
```bash
|
```bash
|
||||||
node --input-type=module -e "
|
node --input-type=module -e "
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ content_series_active: ""
|
||||||
|
|
||||||
# Profile
|
# Profile
|
||||||
expertise_areas:
|
expertise_areas:
|
||||||
- ""
|
- "general"
|
||||||
- ""
|
- ""
|
||||||
- ""
|
- ""
|
||||||
- ""
|
- ""
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ Score the draft against these 6 dimensions (0 = perfect match, 1 = minor drift p
|
||||||
| 4-5 | ALERT | Significant drift — list all deviating dimensions with rewrites |
|
| 4-5 | ALERT | Significant drift — list all deviating dimensions with rewrites |
|
||||||
| 6 | REWRITE | Content doesn't sound like the user — recommend starting over |
|
| 6 | REWRITE | Content doesn't sound like the user — recommend starting over |
|
||||||
|
|
||||||
**Confidence gate:** If `## Collected Post Samples` has fewer than 5 posts, output: "Voice drift: LOW CONFIDENCE (X/5 samples). Scoring based on voice profile only." and score only against the profile description (dimensions 1-2 and 4-6), skipping opening patterns (dimension 3) which needs real samples.
|
**Confidence gate:** If `## Collected Post Samples` has fewer than 5 posts, perform ONLY the AI Pattern Detection (section 1). Skip the Six-Dimension Voice Drift Scoring entirely — there is insufficient data for meaningful drift analysis. Do NOT output "LOW CONFIDENCE" messages. Instead, silently skip drift scoring and only flag if 3+ AI patterns are detected.
|
||||||
|
|
||||||
**Output format (always include at end of system message):**
|
**Output format (always include at end of system message):**
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,13 @@ if (existsSync(STATE_FILE)) {
|
||||||
// Non-critical: don't block session start on pruning failure
|
// Non-critical: don't block session start on pruning failure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count published posts for progressive onboarding
|
||||||
|
const recentPostsSection = stateContent.match(/^## Recent Posts\n([\s\S]*?)(?=\n## [^R]|\n## $|$)/m);
|
||||||
|
let publishedPostCount = 0;
|
||||||
|
if (recentPostsSection) {
|
||||||
|
publishedPostCount = (recentPostsSection[1].match(/^\s*[-\[]/gm) || []).length;
|
||||||
|
}
|
||||||
|
|
||||||
// Build status line
|
// Build status line
|
||||||
let statusLine = `LinkedIn: ${postsThisWeek}/${weeklyGoal} posts this week | Streak: ${currentStreak} days`;
|
let statusLine = `LinkedIn: ${postsThisWeek}/${weeklyGoal} posts this week | Streak: ${currentStreak} days`;
|
||||||
if (lastPostDate && lastPostDate !== 'null') {
|
if (lastPostDate && lastPostDate !== 'null') {
|
||||||
|
|
@ -177,12 +184,14 @@ if (existsSync(STATE_FILE)) {
|
||||||
statusLine += ` | ${followerCount}/${followerTarget} followers (${milestonePhase})`;
|
statusLine += ` | ${followerCount}/${followerTarget} followers (${milestonePhase})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Personalization score
|
// Personalization score (only show after 3+ published posts — progressive onboarding)
|
||||||
let pScore = null;
|
let pScore = null;
|
||||||
try {
|
try {
|
||||||
const { score } = calculateScore(PLUGIN_ROOT);
|
const { score } = calculateScore(PLUGIN_ROOT);
|
||||||
pScore = score;
|
pScore = score;
|
||||||
statusLine += ` | Personalization: ${score}%`;
|
if (publishedPostCount >= 3) {
|
||||||
|
statusLine += ` | Personalization: ${score}%`;
|
||||||
|
}
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
|
|
||||||
// New creator window
|
// New creator window
|
||||||
|
|
@ -272,8 +281,8 @@ if (existsSync(STATE_FILE)) {
|
||||||
reminders += `- ${weekRemaining} posts remaining to hit weekly goal of ${weeklyGoal}. It's late in the week.\\n`;
|
reminders += `- ${weekRemaining} posts remaining to hit weekly goal of ${weeklyGoal}. It's late in the week.\\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Personalization score check
|
// Personalization score check (only after 3+ posts — progressive onboarding)
|
||||||
if (pScore !== null && pScore < 50) {
|
if (pScore !== null && pScore < 50 && publishedPostCount >= 3) {
|
||||||
reminders += `- Personalization score is ${pScore}%. Run /linkedin:setup to improve content quality with your real voice, case studies, and audience data.\\n`;
|
reminders += `- Personalization score is ${pScore}%. Run /linkedin:setup to improve content quality with your real voice, case studies, and audience data.\\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue