소스 정보
- 저장소
- QianJinGuo/wiki
- 최근 소스 활동
- 2026년 8월 27일 02:02
- 감지된 SKILL.md 언어
- 영어
- 스타
- 1
- 포크
- 1
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/QianJinGuo/wiki --skill wiki-cron-pipeline-reconciliation명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
精选高价值 RSS feeds 扫描,输出到 raw/rss-inbox/ 暂存区。只保留有独立知识深度的 feed(非 digest 类),不再自动入库。包含 rss-inbox-curl-recovery.py 绕过 blogwatcher read-state 漏抓的兜底。
Meta-orchestrator that wires web-content-reviewer, llm-wiki, and wiki-evolver into a single four-phase knowledge pipeline (Triage → Gate → Store → Evolve). Use as the single entry point for all knowledge base operations. Includes a 6-URL-validated user-pasted WeChat URL fast path, three-axis dedup decision matrix (NEW/MERGE/DEDUP), orphan-raw detection protocol, and sibling-subagent race V7 evidence, and a two-variant V6 mid-write fix for matching vs different-slug duplicates.
从 Gmail 中提取 TLDR AI 等 newsletter 的链接,写入 raw/email-inbox/candidates.md,供后续 inbox-screener 评分。只做链接不做评分,与 inbox-screener 配合使用。
| name | wiki-cron-pipeline-reconciliation |
| description | Audit cron batch-script runs for silently dropped inputs. |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| metadata | {"hermes":{"tags":["wiki","cron","pipeline","verification","data-loss","reconciliation"],"category":"wiki","related_skills":["life-screener","wiki-pipeline","wiki/inbox-screener"]}} |
Batch scoring/ingest cron scripts (score_life_inbox.py, inbox-screener variants) print a summary line like 0 入库 | 6 reject | 9 skip | 0 dup | 0 error plus per-URL log lines. When the log line count < input count, or the summary doesn't obviously match the input list, do not trust the summary — reconcile before reporting. The user demands evidence chains, not speculative conclusions; this skill is the evidence chain for "nothing was lost".
[SCORE] / [SKIP] / [FETCH-FAIL] / [QUICK-SKIP])No log line ≠ dropped. Batch scripts have silent branches that consume inputs without logging. The reconciliation question is: which silent branch consumed it, and is that branch legitimate? Only an input that matches NO branch AND is missing from the input file's remaining content is actually lost.
[QUICK-SKIP] / [SCORE] / [FETCH-FAIL] lines from stdout.importlib), never by re-implementing its logic (you'll drift from its constants):
import sys, importlib.util, urllib.parse, re
spec = importlib.util.spec_from_file_location('sl', '/path/to/score_script.py')
sl = importlib.util.module_from_spec(spec); spec.loader.exec_module(sl)
bl = sl.build_blacklist()
for u in silent_urls:
real = sl.decode_convertkit(u) if hasattr(sl, 'decode_convertkit') else u
nu = sl.norm_url(real) if hasattr(sl, 'norm_url') else real
domain = urllib.parse.urlparse(real).netloc.lower()
reason = []
if nu in bl: reason.append('BLACKLIST')
if any(domain.endswith(b) for b in getattr(sl, 'BLOCKLIST_DOMAINS', [])): reason.append('BLOCKLIST_DOMAIN')
if re.search(r'utm_campaign|/lp/|/trial', real) and domain not in getattr(sl, 'HIVALUE_DOMAINS', []): reason.append('UTM/LP')
if any(re.search(p, real) for p (sl, , [])): reason.append()
(.join(reason) reason + u)
reject = scored-then-failed (stars≤2 / v×c<threshold / domain relevance fail) — always logged as [SCORE]skip = [FETCH-FAIL] + keyword-count-filtered inputs — [QUICK-SKIP] lines are logged but NOT counteddup = blacklist hits — silent, not logged, not counted0 入库 | 6 reject | 9 skip | 0 dup | 0 error ✓The RSS inbox pipeline runs SEVERAL writer scripts in sequence (recovery → watchdog → curl-recovery → problem-feeds), each reporting its own "N written / M skipped". Their sums can exceed the physical file count — the writers dedup against each other at write time. Reconciliation question: is the final count a data loss, or a cross-writer collision?
Ground truth hierarchy (in order of trust):
ls raw/rss-inbox/*.md | wc -l + programmatic per-feed/per-domain breakdown (read feed_name: from frontmatter, never infer from filename).url: frontmatter occurrences; any dup-pair count > 0 means two files share a URL (usually slug collisions from title dedup suffixes).Known off-by-N variants:
final = recovery + problem_feeds + curl − case-study_rm − sub-1KB_rm. When formula ≠ physical, trust physical; explain the delta by the curl-recovery "already in inbox" count before suspecting loss.Anticipation pattern (predicting the next run's baseline): when a DRAIN cron (wiki-inbox-scan-v2 / wechat-inbox-pipeline) ran between two scans, check its log.md entry for ingest/MERGE counts BEFORE predicting the next rebuild signature. Drain promotions of limbo articles to raw/articles drop the next recovery count by exactly the promoted set (verified 2026-08-15 twice: 04:50 drain promoted 2 → baseline 0→209 → 0→207, recovery 213→211, skipped 102→104; 09:39 run reproduced the −1 form: 07:15's Interconnects cascade article GLM-5.3 ingested at 07:37 → recovery 212→211, baseline 0→208 → 0→207, all other per-feed splits byte-identical). A recovery-count DECREASE = ingestion, not rotation or feed-health — verify by grepping raw/articles for the promoted filenames (presence confirms ingestion).
⚠️ Slug-normalization grep trap (hit 2026-08-15 09:39): when verifying ingestion by filename, the on-disk slug may differ from the article's published name because slugify normalizes special chars — glm-5.3 (dot) becomes glm-53 (hyphen) on disk. A glob like *glm-5.3* returns 0 matches → false "absent" signal that could misread an ingestion shift as rotation. Rule: grep a loose token (*glm*, *stride*, the distinctive word fragment) instead of the exact dotted title; then confirm via frontmatter (source_url + ingested date). This extends the existing shorthand-name trap to dot/hyphen normalization — exact-title globs are NEVER safe for verification.
⚠️ Organic cascade + ingestion reverse-shift co-occurrence — flat per-feed count ≠ unchanged (2026-08-20 08:22): when a drain ingestion (−1) and a scan organic cascade (+1) hit the SAME feed in the SAME cycle, the per-feed recovery count holds FLAT because the two cancel — superficially "nothing changed," actually two offsetting events. Observed: AWS-ML recovery held at 18 (ingested 1 → 17, New=1 organic → 18) while net inbox dropped −1 (0→171 → 0→170) from the ingested async-agentcore article. Disambiguate by (1) scan New>0 (organic tell), (2) watchdog 100%-hit (cascade corroborated), (3) grep raw/articles for the ingested filename, (4) git log drain commit naming the article, (5) attribute net −N to ingestion, not feed-health. A flat count is "unchanged" ONLY when scan New=0 AND no drain ran between cycles. Full evidence chain: references/2026-08-20-organic-cascade-plus-ingestion-cancel.md.
When the LLM API degrades (JSON parse failure, HTTP error, 402), scripts fall back to a keyword-count heuristic. Detect it in [SCORE] lines by the exact value×confidence products:
If a [WARN] JSON 解析失败 / [WARN] DeepSeek ... line precedes one of these, the batch may be heuristic-scored — treat scores as low-confidence and check for generic-landing-page false positives (sponsor/membership pages score high on vague productivity keywords).
✗ WeChat-小米技术: RSS fetch failed — The read operation timed out) while every other feed writes normally — the summary shows that feed at 0 written, N skipped (小米 18 articles vanished from the cycle). This is the same partial-output class as the fetch-problem-feeds.py end-of-run hang, but for the MAIN writer and for a MIDDLE feed (not the last). Recovery pattern: (1) verify the feed is ALIVE independently — proxy curl to its feed URL returning HTTP=200 + full size (小米: HTTP=200 size=2168034B) proves transient, not feed death; (2) re-run recovery.py BEFORE the filter chain — the "never re-run recovery.py" rule (rss-to-wiki-pipeline pitfall) applies ONLY AFTER filters run (re-running after filters re-pollutes removed files); a pre-filter re-run is the SAFE backfill and writes exactly the missing set (observed: run2 wrote 小米 18 + 量子位 2 that arrived in the interval, all other feeds 0 written, N skipped); (3) verify by per-feed physical count + mtime, not by re-reading the summary. Caveat: the backfill can surface organic content that arrived between the two runs (量子位 +2) — those get absorbed by the downstream case-study filter if they're metric-number news pieces, which is why physical per-feed count can hold flat despite more "written" this cycle (contributes to the off-by-4 variant above).ls -lt timestamps show what completed; (2) re-run the script in the BACKGROUND (terminal background=true) — its inbox-dedup skips already-written URLs, so it completes only the missing set (observed: first run wrote 4/5 HF limbo files, background re-run added exactly the 5th, voiceeq); (3) verify by filename for the known missing member, not by re-reading the summary. Do NOT re-run the whole pipeline chain — only the timed-out writer.references/2026-08-14-life-screener-reconciliation.md — worked example: 40 newsletter candidates, 27 log lines, 13 silent URLs classified (5 pre-fetch filters + 8 keyword-filtered), summary fully reconciled, 0 data loss.references/2026-08-27-life-screener-38-candidates-0-ingest.md — worked example: 38 candidates → 0 ingest, 12 silent removals, ambiguous NO-BRANCH URLs (ianbarber/vocab-break, ipurple/text-template) Jina-fetched to confirm they're AI/ML/security (correctly non-life); adds the ambiguous-URL Jina-fetch confirmation loop to the method.references/2026-08-15-rss-inbox-multi-writer-reconciliation.md — worked example: multi-writer RSS inbox pipeline, off-by-2 between writer-sum and physical count = cross-writer URL collisions (NOT data loss), evidence chain (unique-URL count + per-feed presence + drain-log ingestion check).references/2026-08-15-0715-rss-inbox-offby3-and-partial-write.md — worked example: off-by-3 (collisions + ACTIVE watchdog dup) and the writer-timeout partial-write recovery pattern (fetch-problem-feeds.py 300s timeout with 4/5 files written → background re-run completes the set).references/2026-08-15-rss-inbox-recovery-timeout-backfill.md — worked example: recovery.py per-feed fetch timeout (小米 18 dropped) → feed-alive verification → PRE-FILTER backfill re-run → off-by-4 reconciliation; includes the 腾讯 scan New=1 count-held rotation verification via blogwatcher DB unread list.references/2026-08-18-rss-inbox-post-filter-phantom-and-safe-kill.md — worked example: fetch-problem-feeds SP hang killed at ~490s (HF-written-first safe-kill), plus a post-Step-5-filter HF phantom (voiceeq) that required a SECOND dedup pass to remove (count 167→166). Covers the temp-script-labeling lesson (use hermes-verify- under OS temp dir, not the repo's tracked scripts/ tree).references/2026-08-18-triple-invocation-recovery-rotation.md — worked example: recovery.py killed twice at the 180s default timeout then completed on a 600s third run (idempotent-across-kills, combined output clean); the required source_url corruption-verification snippet; and the rotation off-by-0 reconciliation (organic small entry replacing an outgoing big → zero collision slack, per-feed count held at 10 with a size-class composition shift).references/2026-08-20-organic-cascade-plus-ingestion-cancel.md — worked example: organic cascade (+1) and ingestion reverse-shift (−1) co-occurring on the same feed (AWS-ML recovery held flat at 18, net inbox −1 from async-agentcore ingestion); evidence chain to decompose a flat per-feed count before classifying.??NO-BRANCH → the input was fetched, then consumed by a deeper silent branch (redline filter / keyword-count filter). Still legitimate domain filtering — confirm by checking the summary counters for the extra reject/skip counts. For ambiguous NO-BRANCH inputs whose domain is NOT obviously tech/marketing (a personal blog, an unknown .team/.blog domain that could be life content), Jina-fetch the URL (via proxy — direct r.jina.ai times out on this host) and read the first ~1KB body to judge domain relevance yourself. This both proves the input was actually fetched/processed and confirms the silent keyword-removal was legitimate (closes the loop that nothing in-scope was lost). Worked example: references/2026-08-27-life-screener-38-candidates-0-ingest.md.[FETCH-FAIL] items must be RETAINED for retry (known-good pattern — deleting them silently loses high-value articles); all processed items removed.0 files lacking source_urlexecute_codepython3 -cprocess(kill) is faster and cleaner than a background re-run. Ordering guarantee: fetch-problem-feeds writes HF articles FIRST, then attempts SP — so once the HF files you expect are present in the inbox (verify by ls -lt / filename), killing the still-blowing SP fetch loses NOTHING (SP produces 0 written anyway, Substack CN dead-end). Verified: killed at ~490s, HF set intact (baseten + security-incident re-entry), pipeline unscathed. Distinguish from the 07:15 case (needed a background re-run to complete an incomplete HF set) by checking whether the expected HF files already landed — kill only if they did.voiceeq (a quote-blind phantom already in raw/articles) into the inbox, pushing the count 166→167 mid-reconciliation. dedup_rm=42 (first pass 41) only became 42 after a SECOND dedup pass over the post-fetch state removed the phantom. Rule: whenever fetch-problem-feeds ran (or was killed) AFTER Step 5, run the dedup snippet a second time before trusting the final count — it is idempotent and catches post-filter phantom writes that the first pass missed. This is why the raw reconciliation formula recovery + HF + curl − case-study_rm − sub-1KB_rm can read 168 while physical=166: the −2 cross-writer collisions PLUS a same-URL phantom write both resolve to 1 physical file each.grep -n / sed -n via terminal instead; importlib loading still works fine.