thumbgate 1.4.3 β 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/llms.txt +12 -8
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +18 -8
- package/adapters/README.md +1 -1
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/codex/config.toml +2 -2
- package/adapters/mcp/server-stdio.js +1 -1
- package/adapters/opencode/opencode.json +1 -1
- package/config/github-about.json +2 -2
- package/package.json +158 -10
- package/scripts/billing.js +5 -2
- package/scripts/statusline.sh +1 -0
- package/src/api/server.js +113 -16
- package/src/index.js +3 -0
- package/.claude-plugin/bundle/icon.png +0 -0
- package/.claude-plugin/bundle/icon.svg +0 -18
- package/.claude-plugin/bundle/server/index.js +0 -24
- package/adapters/chatgpt/INSTALL.md +0 -158
- package/adapters/perplexity/.mcp.json +0 -36
- package/adapters/perplexity/config.toml +0 -16
- package/adapters/perplexity/opencode.json +0 -29
- package/bin/memory.sh +0 -64
- package/bin/obsidian-sync.sh +0 -20
- package/plugins/amp-skill/INSTALL.md +0 -52
- package/plugins/amp-skill/SKILL.md +0 -64
- package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +0 -22
- package/plugins/claude-codex-bridge/.mcp.json +0 -14
- package/plugins/claude-codex-bridge/INSTALL.md +0 -43
- package/plugins/claude-codex-bridge/README.md +0 -46
- package/plugins/claude-codex-bridge/scripts/codex-bridge.js +0 -286
- package/plugins/claude-codex-bridge/skills/adversarial-review/SKILL.md +0 -24
- package/plugins/claude-codex-bridge/skills/result/SKILL.md +0 -22
- package/plugins/claude-codex-bridge/skills/review/SKILL.md +0 -28
- package/plugins/claude-codex-bridge/skills/second-pass/SKILL.md +0 -27
- package/plugins/claude-codex-bridge/skills/setup/SKILL.md +0 -21
- package/plugins/claude-codex-bridge/skills/status/SKILL.md +0 -19
- package/plugins/claude-skill/INSTALL.md +0 -55
- package/plugins/claude-skill/SKILL.md +0 -46
- package/plugins/codex-profile/.codex-plugin/plugin.json +0 -43
- package/plugins/codex-profile/.mcp.json +0 -14
- package/plugins/codex-profile/AGENTS.md +0 -20
- package/plugins/codex-profile/INSTALL.md +0 -89
- package/plugins/codex-profile/README.md +0 -61
- package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +0 -23
- package/plugins/cursor-marketplace/CHANGELOG.md +0 -30
- package/plugins/cursor-marketplace/LICENSE +0 -21
- package/plugins/cursor-marketplace/README.md +0 -124
- package/plugins/cursor-marketplace/agents/reliability-reviewer.md +0 -31
- package/plugins/cursor-marketplace/assets/logo-400x400.png +0 -0
- package/plugins/cursor-marketplace/commands/capture-feedback.md +0 -33
- package/plugins/cursor-marketplace/commands/check-gates.md +0 -25
- package/plugins/cursor-marketplace/commands/show-lessons.md +0 -27
- package/plugins/cursor-marketplace/hooks/hooks.json +0 -10
- package/plugins/cursor-marketplace/mcp.json +0 -14
- package/plugins/cursor-marketplace/rules/feedback-capture.mdc +0 -34
- package/plugins/cursor-marketplace/rules/pre-action-gates.mdc +0 -30
- package/plugins/cursor-marketplace/rules/session-continuity.mdc +0 -28
- package/plugins/cursor-marketplace/scripts/gate-check.sh +0 -21
- package/plugins/cursor-marketplace/skills/capture-feedback/SKILL.md +0 -48
- package/plugins/cursor-marketplace/skills/prevention-rules/SKILL.md +0 -31
- package/plugins/cursor-marketplace/skills/recall-context/SKILL.md +0 -30
- package/plugins/cursor-marketplace/skills/search-lessons/SKILL.md +0 -33
- package/plugins/gemini-extension/INSTALL.md +0 -92
- package/plugins/gemini-extension/gemini_prompt.txt +0 -14
- package/plugins/gemini-extension/tool_contract.json +0 -45
- package/plugins/opencode-profile/INSTALL.md +0 -57
- package/public/assets/instagram-card.png +0 -0
- package/public/assets/tiktok-agent-memory.mp4 +0 -0
- package/public/blog.html +0 -474
- package/public/compare/mem0.html +0 -189
- package/public/compare/speclock.html +0 -180
- package/public/compare.html +0 -310
- package/public/dashboard.html +0 -1100
- package/public/guide.html +0 -317
- package/public/guides/claude-code-prevent-repeated-mistakes.html +0 -161
- package/public/guides/codex-cli-guardrails.html +0 -158
- package/public/guides/cursor-prevent-repeated-mistakes.html +0 -161
- package/public/guides/pre-action-gates.html +0 -162
- package/public/guides/stop-repeated-ai-agent-mistakes.html +0 -159
- package/public/index.html +0 -1225
- package/public/js/buyer-intent.js +0 -252
- package/public/learn/agent-harness-pattern.html +0 -180
- package/public/learn/ai-agent-persistent-memory.html +0 -203
- package/public/learn/learn.css +0 -45
- package/public/learn/mcp-pre-action-gates-explained.html +0 -172
- package/public/learn/stop-ai-agent-force-push.html +0 -134
- package/public/learn/vibe-coding-safety-net.html +0 -142
- package/public/learn.html +0 -274
- package/public/lessons.html +0 -967
- package/public/llm-context.md +0 -156
- package/public/pro.html +0 -1087
- package/public/vercel.json +0 -8
- package/scripts/a2ui-engine.js +0 -73
- package/scripts/adk-consolidator.js +0 -274
- package/scripts/agent-security-hardening.js +0 -225
- package/scripts/ai-search-visibility.js +0 -116
- package/scripts/autonomous-sales-agent.js +0 -39
- package/scripts/autoresearch-runner.js +0 -216
- package/scripts/background-agent-governance.js +0 -229
- package/scripts/behavioral-extraction.js +0 -93
- package/scripts/budget-enforcer.js +0 -173
- package/scripts/budget-guard.js +0 -173
- package/scripts/build-claude-mcpb.js +0 -255
- package/scripts/build-codex-plugin.js +0 -152
- package/scripts/capture-railway-diagnostics.sh +0 -97
- package/scripts/changeset-check.js +0 -372
- package/scripts/check-congruence.js +0 -443
- package/scripts/computer-use-firewall.js +0 -280
- package/scripts/content-engine/linkedin-content-generator.js +0 -154
- package/scripts/content-engine/output/linkedin-memento-validation.md +0 -17
- package/scripts/content-engine/output/linkedin-posts-2026-04-09.md +0 -175
- package/scripts/content-engine/reddit-thread-finder.js +0 -154
- package/scripts/context-engine.js +0 -710
- package/scripts/daily-digest.js +0 -11
- package/scripts/data-governance.js +0 -173
- package/scripts/deploy-gcp.sh +0 -44
- package/scripts/deploy-policy.js +0 -249
- package/scripts/disagreement-mining.js +0 -315
- package/scripts/dpo-optimizer.js +0 -206
- package/scripts/ensure-repo-bootstrap.js +0 -130
- package/scripts/ephemeral-agent-store.js +0 -212
- package/scripts/eval-harness.js +0 -56
- package/scripts/export-kto-pairs.js +0 -309
- package/scripts/export-training.js +0 -446
- package/scripts/feedback-fallback.js +0 -111
- package/scripts/feedback-inbox-read.js +0 -162
- package/scripts/feedback-root-consolidator.js +0 -233
- package/scripts/feedback-to-memory.js +0 -185
- package/scripts/gate-satisfy.js +0 -42
- package/scripts/generate-paperbanana-diagrams.sh +0 -99
- package/scripts/generate-pretool-hook.sh +0 -40
- package/scripts/github-about.js +0 -430
- package/scripts/github-outreach.js +0 -65
- package/scripts/gtm-revenue-loop.js +0 -535
- package/scripts/hallucination-detector.js +0 -226
- package/scripts/hf-papers.js +0 -317
- package/scripts/hook-auto-capture.sh +0 -100
- package/scripts/hook-stop-pr-thread-check.sh +0 -68
- package/scripts/hook-stop-self-score.sh +0 -51
- package/scripts/hook-stop-verify-deploy.sh +0 -31
- package/scripts/hook-verify-before-done.sh +0 -20
- package/scripts/managed-dpo-export.js +0 -91
- package/scripts/markdown-escape.js +0 -12
- package/scripts/marketing-experiment.js +0 -657
- package/scripts/memalign-recall.js +0 -111
- package/scripts/memory-migration.js +0 -296
- package/scripts/meta-policy.js +0 -190
- package/scripts/metered-billing.js +0 -16
- package/scripts/model-tier-router.js +0 -310
- package/scripts/money-watcher.js +0 -218
- package/scripts/multi-hop-recall.js +0 -240
- package/scripts/per-step-scoring.js +0 -163
- package/scripts/perplexity-command-center.js +0 -644
- package/scripts/perplexity-marketing.js +0 -454
- package/scripts/pii-scanner.js +0 -153
- package/scripts/plan-gate.js +0 -154
- package/scripts/post-everywhere.js +0 -341
- package/scripts/post-to-x-retry.sh +0 -22
- package/scripts/post-to-x.js +0 -369
- package/scripts/pr-manager.js +0 -421
- package/scripts/principle-extractor.js +0 -162
- package/scripts/pro-features.js +0 -41
- package/scripts/prompt-dlp.js +0 -222
- package/scripts/prove-adapters.js +0 -860
- package/scripts/prove-attribution.js +0 -361
- package/scripts/prove-automation.js +0 -651
- package/scripts/prove-autoresearch.js +0 -304
- package/scripts/prove-claim-verification.js +0 -277
- package/scripts/prove-cloudflare-sandbox.js +0 -161
- package/scripts/prove-data-pipeline.js +0 -408
- package/scripts/prove-data-quality.js +0 -227
- package/scripts/prove-evolution.js +0 -352
- package/scripts/prove-harnesses.js +0 -287
- package/scripts/prove-intelligence.js +0 -257
- package/scripts/prove-lancedb.js +0 -425
- package/scripts/prove-local-intelligence.js +0 -340
- package/scripts/prove-loop-closure.js +0 -263
- package/scripts/prove-packaged-runtime.js +0 -327
- package/scripts/prove-predictive-insights.js +0 -355
- package/scripts/prove-runtime.js +0 -363
- package/scripts/prove-seo-gsd.js +0 -234
- package/scripts/prove-settings.js +0 -279
- package/scripts/prove-subway-upgrades.js +0 -277
- package/scripts/prove-tessl.js +0 -229
- package/scripts/prove-training-export.js +0 -325
- package/scripts/prove-workflow-contract.js +0 -112
- package/scripts/prove-xmemory.js +0 -332
- package/scripts/publish-decision.js +0 -159
- package/scripts/ralph-loop.js +0 -376
- package/scripts/ralph-mode-ci.js +0 -434
- package/scripts/reddit-dm-outreach.js +0 -192
- package/scripts/reddit-monitor-cron.sh +0 -26
- package/scripts/reminder-engine.js +0 -132
- package/scripts/revenue-status.js +0 -472
- package/scripts/rotate-stripe-webhook-secret.js +0 -314
- package/scripts/schedule-manager.js +0 -249
- package/scripts/self-healing-check.js +0 -193
- package/scripts/session-analyzer.js +0 -533
- package/scripts/shieldcortex-memory-firewall-runner.mjs +0 -53
- package/scripts/skill-exporter.js +0 -260
- package/scripts/skill-materializer.js +0 -134
- package/scripts/skill-packs.js +0 -136
- package/scripts/skill-proposer.js +0 -99
- package/scripts/skill-quality-tracker.js +0 -282
- package/scripts/slow-loop.js +0 -72
- package/scripts/social-analytics/db/marketing-db.js +0 -179
- package/scripts/social-analytics/db/schema.sql +0 -55
- package/scripts/social-analytics/digest.js +0 -256
- package/scripts/social-analytics/engagement-audit.js +0 -185
- package/scripts/social-analytics/generate-instagram-card.js +0 -123
- package/scripts/social-analytics/generate-slides.js +0 -268
- package/scripts/social-analytics/instagram-thumbgate-post.js +0 -111
- package/scripts/social-analytics/install-growth-automation.js +0 -114
- package/scripts/social-analytics/load-env.js +0 -77
- package/scripts/social-analytics/mcp-server.js +0 -289
- package/scripts/social-analytics/normalizer.js +0 -580
- package/scripts/social-analytics/notify.js +0 -162
- package/scripts/social-analytics/poll-all.js +0 -107
- package/scripts/social-analytics/pollers/github.js +0 -195
- package/scripts/social-analytics/pollers/instagram.js +0 -253
- package/scripts/social-analytics/pollers/linkedin.js +0 -340
- package/scripts/social-analytics/pollers/plausible.js +0 -245
- package/scripts/social-analytics/pollers/reddit.js +0 -306
- package/scripts/social-analytics/pollers/threads.js +0 -233
- package/scripts/social-analytics/pollers/tiktok.js +0 -203
- package/scripts/social-analytics/pollers/x.js +0 -227
- package/scripts/social-analytics/pollers/youtube.js +0 -304
- package/scripts/social-analytics/pollers/zernio.js +0 -183
- package/scripts/social-analytics/post-video.js +0 -316
- package/scripts/social-analytics/publish-instagram-thumbgate.js +0 -104
- package/scripts/social-analytics/publish-thumbgate-launch.js +0 -322
- package/scripts/social-analytics/publishers/devto.js +0 -122
- package/scripts/social-analytics/publishers/instagram.js +0 -317
- package/scripts/social-analytics/publishers/linkedin.js +0 -294
- package/scripts/social-analytics/publishers/reddit.js +0 -385
- package/scripts/social-analytics/publishers/threads.js +0 -275
- package/scripts/social-analytics/publishers/tiktok.js +0 -217
- package/scripts/social-analytics/publishers/x.js +0 -259
- package/scripts/social-analytics/publishers/youtube.js +0 -223
- package/scripts/social-analytics/publishers/zernio.js +0 -568
- package/scripts/social-analytics/reconcile-thumbgate-campaign.js +0 -165
- package/scripts/social-analytics/run-digest.js +0 -34
- package/scripts/social-analytics/schedule-thumbgate-campaign.js +0 -275
- package/scripts/social-analytics/store.js +0 -455
- package/scripts/social-analytics/sync-launch-assets.js +0 -185
- package/scripts/social-analytics/utm.js +0 -143
- package/scripts/social-pipeline.js +0 -2626
- package/scripts/social-post-hourly.js +0 -228
- package/scripts/social-quality-gate.js +0 -134
- package/scripts/social-reply-monitor.js +0 -592
- package/scripts/status-dashboard.js +0 -155
- package/scripts/stripe-live-status.js +0 -115
- package/scripts/subagent-profiles.js +0 -79
- package/scripts/sync-branch-protection.js +0 -340
- package/scripts/sync-gh-secrets-from-env.sh +0 -70
- package/scripts/sync-github-about.js +0 -55
- package/scripts/sync-version.js +0 -479
- package/scripts/synthetic-dpo.js +0 -234
- package/scripts/tessl-export.js +0 -369
- package/scripts/test-coverage.js +0 -128
- package/scripts/thumbgate-bench.js +0 -494
- package/scripts/thumbgate_session_start.sh +0 -32
- package/scripts/train_from_feedback.py +0 -929
- package/scripts/validate-feedback.js +0 -581
- package/scripts/verify-obsidian-setup.sh +0 -269
- package/scripts/verify-run.js +0 -269
- package/scripts/weekly-auto-post.js +0 -124
- package/scripts/x-autonomous-marketing.js +0 -139
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* social-post-hourly.js β now "social-post-daily.js" in practice
|
|
6
|
-
*
|
|
7
|
-
* Generates ONE quality social post per day and publishes via Zernio
|
|
8
|
-
* to LinkedIn, X/Twitter, and TikTok (text-friendly platforms).
|
|
9
|
-
*
|
|
10
|
-
* Strategy based on research of top SaaS companies (Linear, Vercel, Supabase,
|
|
11
|
-
* PostHog, Cursor, Raycast, Cal.com):
|
|
12
|
-
* - 1 post/day, not 24. Quality over volume.
|
|
13
|
-
* - Rotate 7 content angles across the week (not 4 recycled hourly).
|
|
14
|
-
* - Content ratio: 30% educational, 25% product demo, 25% community, 20% hot takes.
|
|
15
|
-
* - NO Reddit auto-posting (ban risk). Reddit engagement via reply-monitor only.
|
|
16
|
-
* - NO Dev.to auto-posting (counterproductive at high volume).
|
|
17
|
-
*
|
|
18
|
-
* Runs daily via CI (.github/workflows/social-engagement-hourly.yml at 2pm UTC).
|
|
19
|
-
*
|
|
20
|
-
* Usage:
|
|
21
|
-
* node scripts/social-post-hourly.js # publish for real
|
|
22
|
-
* node scripts/social-post-hourly.js --dry-run # preview only
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
require('dotenv').config();
|
|
26
|
-
|
|
27
|
-
const { generateWeeklyStatsPost } = require('./daily-digest');
|
|
28
|
-
const {
|
|
29
|
-
getConnectedAccounts,
|
|
30
|
-
isZernioQuotaError,
|
|
31
|
-
publishPost,
|
|
32
|
-
} = require('./social-analytics/publishers/zernio');
|
|
33
|
-
|
|
34
|
-
// Platforms that support text-only posts.
|
|
35
|
-
// Reddit EXCLUDED β engagement only via reply-monitor, not auto-posting.
|
|
36
|
-
// Instagram EXCLUDED β requires media.
|
|
37
|
-
// TikTok EXCLUDED β requires video.
|
|
38
|
-
const TEXT_PLATFORMS = new Set(['linkedin', 'twitter']);
|
|
39
|
-
|
|
40
|
-
// 7 angles, one per day of the week (Monday=0 through Sunday=6)
|
|
41
|
-
// Ratio: 2 educational, 2 product, 2 hot-take/community, 1 tip
|
|
42
|
-
const DAILY_ANGLES = [
|
|
43
|
-
'horror-story', // Monday: "This AI PR would have broken production"
|
|
44
|
-
'educational', // Tuesday: Teach a concept (context engineering, gate patterns)
|
|
45
|
-
'product-demo', // Wednesday: Specific feature highlight with concrete example
|
|
46
|
-
'hot-take', // Thursday: Contrarian opinion about AI coding agents
|
|
47
|
-
'community', // Friday: Highlight a user, contributor, or community discussion
|
|
48
|
-
'tip', // Saturday: Quick actionable tip
|
|
49
|
-
'stats', // Sunday: Weekly build-in-public numbers
|
|
50
|
-
];
|
|
51
|
-
|
|
52
|
-
function getTodayAngle() {
|
|
53
|
-
const day = new Date().getUTCDay(); // 0=Sun, 1=Mon, ..., 6=Sat
|
|
54
|
-
// Remap: Mon=0, Tue=1, ..., Sun=6
|
|
55
|
-
const idx = day === 0 ? 6 : day - 1;
|
|
56
|
-
return DAILY_ANGLES[idx];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function generatePost(angle) {
|
|
60
|
-
const { post, stats } = generateWeeklyStatsPost({ periodDays: 1 });
|
|
61
|
-
const REPO = 'https://github.com/IgorGanapolsky/ThumbGate';
|
|
62
|
-
|
|
63
|
-
switch (angle) {
|
|
64
|
-
case 'horror-story': {
|
|
65
|
-
const gate = stats.topGate || 'force-push prevention';
|
|
66
|
-
return [
|
|
67
|
-
`A Claude Code agent tried to force-push to main today.`,
|
|
68
|
-
'',
|
|
69
|
-
`The "${gate}" gate caught it before execution. No rollback needed, no incident, no Slack panic.`,
|
|
70
|
-
'',
|
|
71
|
-
`Pre-action gates > post-mortem reviews.`,
|
|
72
|
-
'',
|
|
73
|
-
`ThumbGate is open source: ${REPO}`,
|
|
74
|
-
].join('\n');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
case 'educational':
|
|
78
|
-
return [
|
|
79
|
-
'Context engineering vs prompt engineering for AI agents:',
|
|
80
|
-
'',
|
|
81
|
-
'Prompt engineering: "Please don\'t force-push to main"',
|
|
82
|
-
'Context engineering: Agent physically cannot force-push because a gate blocks it',
|
|
83
|
-
'',
|
|
84
|
-
'One is a suggestion. The other is enforcement.',
|
|
85
|
-
'',
|
|
86
|
-
'The agents that work reliably in production use both β but enforcement is what prevents the 2am incidents.',
|
|
87
|
-
].join('\n');
|
|
88
|
-
|
|
89
|
-
case 'product-demo':
|
|
90
|
-
return [
|
|
91
|
-
'How ThumbGate works in 30 seconds:',
|
|
92
|
-
'',
|
|
93
|
-
'1. Agent tries to run a tool call',
|
|
94
|
-
'2. PreToolUse hook intercepts it',
|
|
95
|
-
'3. Call is checked against prevention rules',
|
|
96
|
-
'4. If it matches a known-bad pattern β blocked',
|
|
97
|
-
'5. Agent tries a different approach',
|
|
98
|
-
'',
|
|
99
|
-
'Rules are generated from your thumbs-down feedback. The system learns from your corrections.',
|
|
100
|
-
'',
|
|
101
|
-
`Try it: npx thumbgate init`,
|
|
102
|
-
].join('\n');
|
|
103
|
-
|
|
104
|
-
case 'hot-take':
|
|
105
|
-
return [
|
|
106
|
-
'Unpopular opinion: CLAUDE.md files are not enough to make AI agents reliable.',
|
|
107
|
-
'',
|
|
108
|
-
'Instructions in markdown are suggestions. The agent can ignore them after context compaction, hallucinate past them, or just decide they don\'t apply.',
|
|
109
|
-
'',
|
|
110
|
-
'You need enforcement β gates that physically block bad actions before execution.',
|
|
111
|
-
'',
|
|
112
|
-
'Memory helps agents remember. Gates make them comply.',
|
|
113
|
-
].join('\n');
|
|
114
|
-
|
|
115
|
-
case 'community':
|
|
116
|
-
return [
|
|
117
|
-
`This week's most common agent mistake caught by ThumbGate users:`,
|
|
118
|
-
'',
|
|
119
|
-
`Agents trying to commit .env files to public repos.`,
|
|
120
|
-
'',
|
|
121
|
-
`It's such a common pattern that we made it a default gate. Works across Claude Code, Cursor, and Codex.`,
|
|
122
|
-
'',
|
|
123
|
-
`What's the most dangerous thing your AI agent has tried to do? Genuinely curious.`,
|
|
124
|
-
].join('\n');
|
|
125
|
-
|
|
126
|
-
case 'tip':
|
|
127
|
-
return [
|
|
128
|
-
'Quick tip for Claude Code users:',
|
|
129
|
-
'',
|
|
130
|
-
'Add a PreToolUse hook that checks for `git push --force` before every Bash call.',
|
|
131
|
-
'',
|
|
132
|
-
'One line of prevention saves hours of rollback.',
|
|
133
|
-
'',
|
|
134
|
-
`ThumbGate automates this β generates hooks from your feedback: ${REPO}`,
|
|
135
|
-
].join('\n');
|
|
136
|
-
|
|
137
|
-
case 'stats':
|
|
138
|
-
return post; // Use the generated weekly stats
|
|
139
|
-
|
|
140
|
-
default:
|
|
141
|
-
return post;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async function main() {
|
|
146
|
-
const dryRun = process.argv.includes('--dry-run');
|
|
147
|
-
const angle = getTodayAngle();
|
|
148
|
-
const content = generatePost(angle);
|
|
149
|
-
|
|
150
|
-
console.log(`[daily-post] Day: ${new Date().toUTCString()}`);
|
|
151
|
-
console.log(`[daily-post] Angle: ${angle}`);
|
|
152
|
-
console.log(`[daily-post] Content:\n${content}\n`);
|
|
153
|
-
|
|
154
|
-
if (dryRun) {
|
|
155
|
-
console.log('[daily-post] Dry run β not posting.');
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Fetch connected accounts, filter to text-friendly platforms (no Reddit, no Instagram)
|
|
160
|
-
const accounts = await getConnectedAccounts();
|
|
161
|
-
const textAccounts = accounts
|
|
162
|
-
.filter(a => TEXT_PLATFORMS.has(a.platform))
|
|
163
|
-
.map(a => ({ platform: a.platform, accountId: a._id || a.accountId }));
|
|
164
|
-
|
|
165
|
-
if (textAccounts.length === 0) {
|
|
166
|
-
console.error('[daily-post] No text-friendly accounts connected.');
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
console.log(`[daily-post] Publishing to ${textAccounts.length} platform(s): ${textAccounts.map(a => a.platform).join(', ')}`);
|
|
171
|
-
|
|
172
|
-
const result = await publishPost(content, textAccounts);
|
|
173
|
-
console.log('[daily-post] Result:', JSON.stringify(result, null, 2));
|
|
174
|
-
|
|
175
|
-
if (result.platformResults) {
|
|
176
|
-
for (const pr of result.platformResults) {
|
|
177
|
-
if (pr.status === 'published') {
|
|
178
|
-
console.log(`[daily-post] ${pr.platform}: published`);
|
|
179
|
-
} else {
|
|
180
|
-
console.error(`[daily-post] ${pr.platform}: ${pr.status} β ${pr.error || 'unknown'}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function isNonFatalPostFailure(err) {
|
|
187
|
-
return isZernioQuotaError(err);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function handlePostFailure(err) {
|
|
191
|
-
if (isNonFatalPostFailure(err)) {
|
|
192
|
-
console.warn(`[daily-post] Skipped: ${err.message}`);
|
|
193
|
-
console.warn('[daily-post] Zernio monthly post quota reached; treating as a controlled skip.');
|
|
194
|
-
return 0;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
console.error('[daily-post] Fatal:', err.message);
|
|
198
|
-
return 1;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function runCli({ run = main, exit = process.exit } = {}) {
|
|
202
|
-
return run().catch(err => {
|
|
203
|
-
const exitCode = handlePostFailure(err);
|
|
204
|
-
if (exitCode !== 0) {
|
|
205
|
-
exit(exitCode);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function isCliEntrypoint(entryModule = require.main) {
|
|
211
|
-
return Boolean(entryModule && entryModule.filename === __filename);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (isCliEntrypoint()) {
|
|
215
|
-
void runCli();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
module.exports = {
|
|
219
|
-
DAILY_ANGLES,
|
|
220
|
-
TEXT_PLATFORMS,
|
|
221
|
-
generatePost,
|
|
222
|
-
getTodayAngle,
|
|
223
|
-
handlePostFailure,
|
|
224
|
-
isCliEntrypoint,
|
|
225
|
-
isNonFatalPostFailure,
|
|
226
|
-
main,
|
|
227
|
-
runCli,
|
|
228
|
-
};
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
const BOT_SLOP_PATTERNS = [
|
|
5
|
-
{ id: 'emoji_spam', pattern: /(?:π|π‘|π₯|β‘|π―|πͺ|π|π){3,}/g, reason: 'Excessive emoji spam' },
|
|
6
|
-
{ id: 'generic_opener', pattern: /^(?:Just|Excited to|Thrilled to|Happy to|Proud to) (?:\w+ )*?(?:launch|ship|release|publish|built|creat|announc)/i, reason: 'Generic shipped opener' },
|
|
7
|
-
{ id: 'hashtag_spam', pattern: /#[A-Za-z]+(?:\s+#[A-Za-z]+){5,}/g, reason: 'Too many hashtags' },
|
|
8
|
-
{ id: 'engagement_bait', pattern: /(?:Like if you agree|Retweet if|Share this|Follow for more|Drop a .* in the comments|Who else)/i, reason: 'Engagement bait' },
|
|
9
|
-
{ id: 'thread_bait', pattern: /^(?:Thread|π§΅|A thread on|Here are \d+ (?:ways|tips|tricks|things|reasons))/i, reason: 'Thread bait opener' },
|
|
10
|
-
{ id: 'ai_generated_tell', pattern: /(?:In today's rapidly evolving|In this comprehensive|Without further ado|It's worth noting that|At the end of the day)/i, reason: 'AI-generated phrasing' },
|
|
11
|
-
{ id: 'fake_urgency', pattern: /(?:Don't miss out|Act now|Limited time|Last chance|You won't believe)/i, reason: 'Fake urgency' },
|
|
12
|
-
{ id: 'self_congratulation', pattern: /(?:We're proud to|I'm honored to|Humbled to|Grateful to announce)/i, reason: 'Self-congratulatory opener' },
|
|
13
|
-
{ id: 'empty_hype', pattern: /(?:game.?changer|revolutionary|disruptive|next.?gen|cutting.?edge|world.?class|best.?in.?class)/i, reason: 'Empty hype words' },
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
const REPLY_TOPIC_PATTERNS = {
|
|
17
|
-
skills: /\bskill|template|process|workflow|review|sprint|implement|phase/i,
|
|
18
|
-
context: /\bcontext doc|context docs|conflicting|inconsisten|claude\.md|cursorrules|instruction/i,
|
|
19
|
-
memory: /\bmemory|remember|amnesia|across sessions|next session|compaction|persist/i,
|
|
20
|
-
setup: /\binstall|setup|config|init|repo|github|link|tool|open source|built/i,
|
|
21
|
-
gates: /\bgate|hook|block|prevent|pretooluse|mcp/i,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const UNSOLICITED_PROMO_PATTERNS = [
|
|
25
|
-
{ id: 'unsolicited_link', pattern: /https?:\/\//i, reason: 'Unsolicited link in reply' },
|
|
26
|
-
{ id: 'unsolicited_install', pattern: /npx thumbgate init/i, reason: 'Unsolicited install CTA in reply' },
|
|
27
|
-
{ id: 'unsolicited_stack_dump', pattern: /\b(?:sqlite\+fts5|thompson sampling|pretooluse|mcp server)\b/i, reason: 'Unsolicited architecture dump in reply' },
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
const MIN_POST_LENGTH = 30;
|
|
31
|
-
const MAX_POST_LENGTH = 2000;
|
|
32
|
-
|
|
33
|
-
function scanForSlop(postText) {
|
|
34
|
-
const text = String(postText || '');
|
|
35
|
-
const findings = [];
|
|
36
|
-
|
|
37
|
-
if (text.length < MIN_POST_LENGTH) {
|
|
38
|
-
findings.push({ id: 'too_short', reason: 'Too short' });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (text.length > MAX_POST_LENGTH) {
|
|
42
|
-
findings.push({ id: 'too_long', reason: 'Too long' });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
for (const rule of BOT_SLOP_PATTERNS) {
|
|
46
|
-
rule.pattern.lastIndex = 0;
|
|
47
|
-
if (rule.pattern.test(text)) {
|
|
48
|
-
findings.push({ id: rule.id, reason: rule.reason });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const words = text.split(/\s+/).filter((word) => word.length > 3);
|
|
53
|
-
const capsWords = words.filter((word) => word === word.toUpperCase() && /[A-Z]/.test(word));
|
|
54
|
-
if (words.length > 5 && capsWords.length / words.length > 0.3) {
|
|
55
|
-
findings.push({ id: 'caps_shouting', reason: 'Too many ALL CAPS' });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
allowed: findings.length === 0,
|
|
60
|
-
findings,
|
|
61
|
-
findingCount: findings.length,
|
|
62
|
-
postLength: text.length,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function detectReplyTopics(text) {
|
|
67
|
-
const content = String(text || '');
|
|
68
|
-
return Object.entries(REPLY_TOPIC_PATTERNS)
|
|
69
|
-
.filter(([, pattern]) => pattern.test(content))
|
|
70
|
-
.map(([topic]) => topic);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function commentExplicitlyRequestsProduct(commentText) {
|
|
74
|
-
return /\b(?:what tool|what is it|which tool|repo|github|link|where can i find|can you share|how do i install|setup details|what did you build)\b/i.test(
|
|
75
|
-
String(commentText || '')
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function gateContextualReply(commentText, replyText, options = {}) {
|
|
80
|
-
const scan = scanForSlop(replyText);
|
|
81
|
-
const findings = [...scan.findings];
|
|
82
|
-
const comment = String(commentText || '');
|
|
83
|
-
const reply = String(replyText || '');
|
|
84
|
-
const platform = String(options.platform || '').toLowerCase();
|
|
85
|
-
const commentTopics = detectReplyTopics(comment);
|
|
86
|
-
const replyTopics = detectReplyTopics(reply);
|
|
87
|
-
|
|
88
|
-
if (commentTopics.length > 0 && !commentTopics.some((topic) => replyTopics.includes(topic))) {
|
|
89
|
-
findings.push({
|
|
90
|
-
id: 'not_contextual',
|
|
91
|
-
reason: 'Reply does not address the commenterβs actual point',
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (platform === 'reddit' && !commentExplicitlyRequestsProduct(comment)) {
|
|
96
|
-
for (const rule of UNSOLICITED_PROMO_PATTERNS) {
|
|
97
|
-
rule.pattern.lastIndex = 0;
|
|
98
|
-
if (rule.pattern.test(reply)) {
|
|
99
|
-
findings.push({ id: rule.id, reason: rule.reason });
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
allowed: findings.length === 0,
|
|
106
|
-
findings,
|
|
107
|
-
findingCount: findings.length,
|
|
108
|
-
replyLength: reply.length,
|
|
109
|
-
commentTopics,
|
|
110
|
-
replyTopics,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function gatePost(postText) {
|
|
115
|
-
const scan = scanForSlop(postText);
|
|
116
|
-
if (!scan.allowed) {
|
|
117
|
-
console.error('[social-quality-gate] BLOCKED:');
|
|
118
|
-
for (const finding of scan.findings) {
|
|
119
|
-
console.error(' -', finding.id, finding.reason);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return scan;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
module.exports = {
|
|
126
|
-
BOT_SLOP_PATTERNS,
|
|
127
|
-
MAX_POST_LENGTH,
|
|
128
|
-
MIN_POST_LENGTH,
|
|
129
|
-
commentExplicitlyRequestsProduct,
|
|
130
|
-
detectReplyTopics,
|
|
131
|
-
gateContextualReply,
|
|
132
|
-
gatePost,
|
|
133
|
-
scanForSlop,
|
|
134
|
-
};
|