feat(linkedin-thought-leadership): v1.0.0 — initial open-source import
Build LinkedIn thought leadership with algorithmic understanding, strategic consistency, and AI-assisted content creation. Updated for the January 2026 360Brew algorithm change. 16 agents, 25 commands, 6 skills, 9 hooks, 24 reference docs. Personal data sanitized: voice samples generalized to template, high-engagement posts cleared, region-specific references replaced with placeholders. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7194a37129
commit
39f8b275a6
143 changed files with 32662 additions and 0 deletions
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/env node
|
||||
// content-gatekeeper.mjs
|
||||
// Unified PreToolUse/PostToolUse gatekeeper for linkedin-thought-leadership plugin
|
||||
//
|
||||
// Replaces 4 nearly identical bash scripts:
|
||||
// pre-content-quality-gate.sh, pre-voice-guardian.sh,
|
||||
// pre-topic-rotation-gate.sh, post-creation-check.sh
|
||||
//
|
||||
// Usage:
|
||||
// node content-gatekeeper.mjs <prompt-filename> [--no-session-marker]
|
||||
//
|
||||
// Arguments:
|
||||
// prompt-filename - Prompt file in hooks/prompts/ (e.g. content-quality-gate.md)
|
||||
// --no-session-marker - Skip creating session-active marker (for PostToolUse)
|
||||
//
|
||||
// Exit codes:
|
||||
// 0 - Always allow (injects systemMessage or passes through)
|
||||
|
||||
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { isLinkedInContent } from './linkedin-content-filter.mjs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const pluginRoot = join(__dirname, '..', '..');
|
||||
|
||||
const promptFile = process.argv[2];
|
||||
const noSessionMarker = process.argv.includes('--no-session-marker');
|
||||
|
||||
if (!promptFile) {
|
||||
process.stdout.write('{}');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Read and parse stdin JSON
|
||||
let input;
|
||||
try {
|
||||
input = JSON.parse(readFileSync(0, 'utf-8'));
|
||||
} catch {
|
||||
process.stdout.write('{}');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Extract file_path from tool_input
|
||||
const toolInput = input.tool_input ?? {};
|
||||
const filePath = toolInput.file_path ?? toolInput.filePath ?? '';
|
||||
|
||||
// Check if this is LinkedIn content
|
||||
if (!isLinkedInContent(filePath)) {
|
||||
process.stdout.write('{}');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Mark session as having LinkedIn content activity
|
||||
if (!noSessionMarker) {
|
||||
const sessionDir = '/tmp/linkedin-hooks';
|
||||
mkdirSync(sessionDir, { recursive: true });
|
||||
writeFileSync(join(sessionDir, 'session-active'), '');
|
||||
}
|
||||
|
||||
// Load and return prompt
|
||||
const promptPath = join(pluginRoot, 'hooks', 'prompts', promptFile);
|
||||
if (!existsSync(promptPath)) {
|
||||
process.stdout.write('{}');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const promptContent = readFileSync(promptPath, 'utf-8');
|
||||
process.stdout.write(JSON.stringify({ systemMessage: promptContent }));
|
||||
process.exit(0);
|
||||
Loading…
Add table
Add a link
Reference in a new issue