عنوان GitHub `pushed_at` كان مضلّلًا في 14 من أصل 35 مستودعًا لأدوات السحب؛ وتم تأكيد نشاط الروبوتات في ثلاثة منها

آخر تحديث في August 14, 2026
عنوان GitHub `pushed_at` كان مضلّلًا في 14 من أصل 35 مستودعًا لأدوات السحب؛ وتم تأكيد نشاط الروبوتات في ثلاثة منها
ملخص AI
تُظهر صفحة مستودع GitHub الحقل pushed_at، وهو طابع زمني يمكن أن يتغيّر عندما يتلقى أي فرع عملية دفع. وقد يختلف ذلك عن أحدث commit على الفرع الافتراضي. تاريخ الفرع الافتراضي هو مؤشر على صيانة المستودع؛ لكنه لا يعبّر بالضرورة عن الكود الذي يثبّته مدير الحزم. عادةً ما يتعامل مديرو الحزم مع أصول السجل أو إصدارات الوحدات البرمجية. ولهذا يتحقق هذا التدقيق من نشاط المستودع والأصل المنشور بشكل منفصل: قد يكون أحدهما حديثًا بينما الآخر قديمًا. لذلك جمعت 35 مستودعًا ما زالت تظهر في التوصيات، ثم قرأت الرقم الذي لا يضعه GitHub في الترويسة: تاريخ أحدث commit على الفرع الافتراضي.

تُظهر صفحة المستودع في GitHub الحقل pushed_at، وهو طابع زمني قد يتغيّر كلما وصل أي فرع إلى عملية دفع جديدة. لذلك قد لا يطابق أحدث commit على الفرع الافتراضي. أمّا تاريخ الفرع الافتراضي نفسه فهو مؤشر على صيانة المستودع، لكنه لا يعبّر بالضرورة عن الكود الذي يثبّته مدير الحزم.

عادةً ما يتعامل مديرو الحزم مع حزم السجلّات أو إصدارات الوحدات البرمجية. ولهذا يفصل هذا التدقيق بين نشاط المستودع والأصل المنشور: فقد يكون أحدهما حديثًا بينما الآخر قديمًا.

لذلك جمعت 35 مستودعًا ما زالت تظهر في التوصيات، ثم قرأت الرقم الذي لا يضعه GitHub في الترويسة: تاريخ أحدث commit على الفرع الافتراضي.

الفجوة حقيقية: 14 من أصل 35 مستودعًا لديها pushed_at متقدّم بأكثر من 180 يومًا عن أحدث commit على الفرع الافتراضي، ويصل الحد الأعلى إلى 1,802 يومًا. تم تأكيد وجود روبوتات في ثلاثة من هذه الـ14؛ وبعد استبعاد المستودعات المؤرشفة وحالات النشاط البشري، تبقّى حالتا روبوت مؤكَّدتان ضمن تسع حالات مرشحة. والخلاصة الأهم هي أن حداثة المستودع وحداثة الحزمة المنشورة قد تسيران في مسارين مختلفين.

ماذا قِيس، وعلى أي أساس

System diagram: What was measured, and on what

المرجع الرسمي: GitHub repository API.

تمت قراءة كل رقم هنا من استجابة حيّة لواجهة API بين 15:44 و15:53 UTC في 2026-07-27 ثم حفظه مؤقتًا. ويحفظ مجموعة البيانات المكوّنة من 35 صفًا، وقائمة المستودعات، والصفوف المبنية، والنصوص البرمجية الخاصة بالجلب/البناء في artifacts/ مدخلات التدقيق ومنطق التحويل المستخدم فيه.

تم جمع أربع فئات من البيانات؛ وكانت طلبات السجلّات والنشاط مشروطة، لا سلسلة موحّدة من أربع طلبات:

  • GET /repos/{owner}/{repo} — النجوم، وarchived، وpushed_at، والترخيص، وdefault_branch.
  • GET /repos/{o}/{r}/commits?sha={default_branch}&per_page=1 — أحدث commit على الفرع الافتراضي، ويُستخدم كمؤشر على صيانة المستودع.
  • GET /repos/{o}/{r}/activity?per_page=30 — لكل مستودع يختلف فيه المؤشران السابقان، ما الذي حرّك pushed_at فعليًا.
  • GET /repos/{o}/{r}/releases بالإضافة إلى سجلات PyPI وnpm — متى شُحن الأصل آخر مرة، وهو ما اتّضح أنه أهم من الاثنين معًا.

staleness_days هو الزمن المنقضي من أحدث commit على الفرع الافتراضي إلى لحظة القياس. أمّا الفجوة بين pushed_at وذلك commit فهي الوهم، محسوبة بالأيام. أي قيمة تتجاوز 180 يومًا تُعلَّم.

هناك منهجان يستحقان الذكر لأنهما غيّرا النتائج.

تم التحقق من نسب الحزمة، ولم يُفترض شيء. وجود مستودع في README الخاص بحزمة ما لا يعني أن الحزمة تابعة لذلك المستودع. كان لا بد من تأكيد كل ربط عبر حقل منظم — إما إدخال repository/project_urls في السجل نفسه، أو manifest مُلتزم داخل المستودع. فشلت ستة تطابقات تبدو معقولة في هذا الاختبار، ولذلك لم تُنسب أعداد تنزيلاتها عمدًا.

وأحد هذه الاستبعادات وحده يبرّر القاعدة كلها. curl-cffi يسحب 35,763,529 تنزيلًا شهريًا ويبدو من بعيد وكأنه الربط البرمجي لـ lwthiker/curl-impersonate — وهو مستودع خامد منذ 875 يومًا. نسبه إليه كان سيعطي رقمًا أكبر بأربع وأربعين مرة من newspaper3k، لكنه كان سيصبح رقمًا خاطئًا: بيانات PyPI الخاصة بـ curl-cffi تشير إلى lexiforest/curl_cffi، وهو مشروع منفصل ونشط آخر إصدار له كان 2026-04-03. كان الرقم الأكثر لفتًا للنظر هنا هو الرقم الخاطئ.

والحالة السابعة أغرب: steel-dev/steel-mcp-server يعلن @steel-dev/mcp-server داخل ملف package.json الخاص به، لكن npm يرجع 404. لم يُنشر أصلًا، لذا لا يصح القول إنه "ما زال يُثبَّت".

وعندما يتعذّر الحصول على رقم، يُذكر ذلك صراحةً. أدوات Go وJVM و.NET وPHP لا تملك حضورًا في PyPI أو npm، لذا يُكتب أمامها N/A (no PyPI/npm package) — وليس صفرًا. كما أن 17 من أصل 35 لا تنشر GitHub Releases أصلًا؛ وتُسجَّل تلك الحالة على أنها none، لا بيانات مفقودة.

هذه الحقول لم تُدمج عمدًا في "درجة صحة" واحدة. فرع افتراضي قديم، وفرع جانبي حديث، وغياب Release في GitHub، وأصل سجلّات قديم، كلّها تجيب عن أسئلة مختلفة. تتوفر الأدلة على مستوى الصف في مجموعة البيانات ذات الـ35 صفًا، ومعها مدخلات المستودعات والسجلات المبنية. اقرأها كإشارات فرز أولي تحدد الفحص التالي، لا كأصوات أربع تحكم إن كان المشروع حيًا أم لا.

تنبيه منهجي منذ البداية

هذه قائمة صُنعت يدويًا لأدوات كنت أشك في أنها تعيش على سمعتها. ليست عينة عشوائية من منظومة أدوات السحب، و"31 من 35 قديمة" ليست نسبة على مستوى المنظومة — بل هي أقرب إلى قياس جودة اختياري أنا للعينة. النتيجة المثيرة للاهتمام ليست عدد الأدوات القديمة، بل أنه حتى في عينة اختيرت بسبب هذه الظاهرة، فإن الآلية المحددة التي كنت أختبرها فسّرت أقلية من الحالات، وتم تأكيدها بشكل إيجابي في عدد أقل بعد الاستبعاد.

الوهم حقيقي، وهذه أسوأ حالاته

sjdirect/abot، وهو زاحف .NET لديه 2,308 نجمة. GitHub يعرض آخر دفع بتاريخ 2026-07-17، أي قبل تاريخ القياس بعشرة أيام. لكن الفرع الافتراضي كان آخر تعديل له في 2021-08-09.

هذه فجوة قدرها 1,802 يومًا. خمس سنوات. الترويسة تقول الأسبوع الماضي.

أربعة عشر من أصل 35 مستودعًا تظهر فجوة تتجاوز 180 يومًا:

RepoGap (days)Default branch last movedpushed_at
sjdirect/abot1,8022021-08-092026-07-17
dragnet-org/dragnet1,5202021-05-092025-07-08
paquettg/php-html-parser1,3762020-11-012024-08-09
seomoz/simhash-py1,1592020-03-122023-05-15
internetarchive/wayback1,0392021-04-272024-03-01
Rhizome-Conifer/conifer1,0132023-10-122026-07-22
kohlschutter/boilerpipe8562015-08-302018-01-03
scrapinghub/splash8192022-05-052024-08-02
tomnomnom/waybackurls7562022-04-052024-05-01
geziyor/geziyor6892024-08-122026-07-02
crawlab-team/crawlab4882024-10-092026-02-10
ArchiveTeam/wpull4682023-01-162024-04-29
yasserg/crawler4j3962020-10-032021-11-04
apache/any233812022-06-032023-06-20

أربعة عشر من خمسة وثلاثين. هذا حقيقي ومهم، لكنه أقلية ضمن عينة اختيرت أصلًا لتحتوي عليه.

تم تأكيد الروبوتات في ثلاثة مستودعات معلّمة — وتبقت حالتان فقط بعد التصفية

النسخة المتداولة من القصة تذكر dependabot دائمًا. وقد تحققت من ذلك عبر سحب موجز النشاط لكل مستودع معلّم، وتصنيف كل ref دُفع بعد آخر commit على الفرع الافتراضي. وتلك الـ"بعد" مهمة: الأحداث الأقدم من آخر commit لا تقول شيئًا عن سبب الفجوة، واحتساب الموجز كله يغيّر السؤال بهدوء.

تأكيد على أن الروبوت هو السبب، وفق منهج ما بعد الـcommit: ثلاثة. scrapinghub/splash (4 من 4 أحداث بعد الـcommit على dependabot/pip/*)، وgeziyor/geziyor (5 من 5 على dependabot/go_modules/*)، وapache/any23 (16 من 16 على dependabot/maven/*). أحد هذه الثلاثة، وهو any23، مؤرشف رسميًا، لذا لا يدخل أصلًا في المجموعة المُصفّاة — ما يترك حالتين مؤكدتين تستوفيان أيضًا كل الشروط الأخرى.

خاطئ تمامًا: حالتان، وكلتاهما أكثر إثارة للاهتمام من قصة الروبوت نفسها.

فجوة dragnet-org/dragnet البالغة 1,520 يومًا ناتجة عن إنسان دفع فرعًا باسم mp/py3.10 — أي محاولة غير مدمجة لنقل المشروع إلى Python 3.10. حاول أحدهم تحديثه ثم توقّف. هذا ليس ضجيجًا آليًا يضخّم الطابع الزمني؛ بل سجلًّا مرئيًا ومؤرخًا لمحاولة إنقاذ فاشلة. ويمكن القول إنه أكثر إشارة مفيدة في مجموعة البيانات كلها، ولو رُويت القصة على أنها "dependabot فعلها" لابتلعت هذه الحقيقة.

مختلطة، وأكبر من أيٍّ من الحالتين: اثنتان. crawlab-team/crawlab لديه 12,250 نجمة — ثاني أكثر مستودع في العينة من حيث النجوم — وفجوة 488 يومًا على main. موجز النشاط يحتوي على فروع dependabot وأيضًا 24 عملية دفع بشرية بعد الـcommit، كلها إلى develop وtest. من يقرأ الترويسة يظن أن فبراير 2026 يعني الصحة؛ ومن يقرأ main يظن أن أكتوبر 2024 يعني الموت. كلاهما مخطئ. التطوير انتقل خارج الفرع الافتراضي، وهذا أمر تفعله المشاريع، ولا تملك GitHub Summary طريقة لشرحه. أما sjdirect/abot فهو الحالة المختلطة الأخرى: الدفع الذي رفع pushed_at في العنوان كان فعلًا من dependabot، لكن إنسانًا دفع upgrade1 في 2024، لذلك يخرج لاحقًا من المجموعة المصفاة.

Rhizome-Conifer/conifer هي الحالة الملتبسة، وقد قرأتها في البداية بشكل خاطئ. فرعها الافتراضي هو main وليس master، وmain لم يتحرك منذ 2023-10-12 — والحدث الوحيد على main في الموجز هو إنشاء فرع في يناير 2025، وهو ما ينسجم مع إعادة تسمية. وفي المقابل، دفع حساب واحد إلى conifer-twilight وtwilight/read-only في 2026-07-22، أي قبل تاريخ القياس بخمسة أيام. هذا نشاط بشري حقيقي، لكن "تطوير نشط" أوسع مما تسمح به هذه المراجع: مساهم واحد، وعلى فروع اسمها read-only، ينسجم مع إغلاق منظم بقدر ما ينسجم مع استمرار التطوير. ما يمكن قوله أضيق من ذلك لكنه لا يزال مهمًا: فجوة 1,013 يومًا ليست ضجيجًا ناتجًا عن روبوتات، كما أنها ليست دليلًا على الهجر أيضًا.

غير معروف: سبع حالات. php-html-parser وsimhash-py وinternetarchive/wayback وboilerpipe وwaybackurls وwpull وcrawler4j جميعها لديها فجوة مؤكدة، وموجز نشاط يرجع فارغًا.

الشرح المغري هو الاحتفاظ السجلّي — فموجز نشاط GitHub لا يرجع إلى ما لا نهاية. لكن التخزين المؤقت ينقض ذلك في معظم هذه الحالات. أقدم حدث في أي من هذه الاستجابات الـ123 هو 2023-03-10، وخمسة من السبعة تقع pushed_at لديها داخل هذه النافذة بوضوح: php-html-parser في 2024-08-09، وwpull في 2024-04-29، وwaybackurls في 2024-05-01، وinternetarchive/wayback في 2024-03-01، وsimhash-py في 2023-05-15. أيًّا كان ما حرّك هذه الطوابع الزمنية، كان ينبغي أن يظهر في الموجز ولم يظهر. الاحتفاظ يفسّر فقط boilerpipe (2018) وcrawler4j (2021).

إذن العبارة الصادقة أضيق من تفسير مرتب: بالنسبة لسبعة مستودعات، الفجوة حقيقة مؤكدة وسببها غير محسوم — النقطة النهائية لم تُرجع شيئًا، ولخمسة منها لا أستطيع أن أقول لماذا. القول بأن "dependabot فعلها" مجرد افتراض في الحالات السبع كلها.

وبجمع الأرقام، عبر المستودعات الـ14 المعلّمة:

Cause of the inflated pushed_atReposWhich, and on what evidence
Confirmed bot-driven3scrapinghub/splash (4 of 4 post-commit events on dependabot/pip/*), geziyor/geziyor (5 of 5 on dependabot/go_modules/*), apache/any23 (16 of 16 on dependabot/maven/*) — any23 is archived, leaving two that also satisfy every other condition
Mixed, bot and human2crawlab-team/crawlab (dependabot branches plus 24 post-commit pushes from humans, all to develop and test), sjdirect/abot (the push that set its headline pushed_at really was dependabot, but a human pushed upgrade1 in 2024)
Outright wrong — human work, zero bot branches2dragnet-org/dragnet (3 post-commit events, 0 on a bot branch) — a human pushing mp/py3.10, an unmerged Python 3.10 port. Rhizome-Conifer/conifer (30 post-commit events, 0 on a bot branch) — a single account pushing conifer-twilight and twilight/read-only on 2026-07-22. Whether conifer is abandoned stays ambiguous, as above; what is not ambiguous is that no bot inflated its pushed_at
Unestablished — activity feed empty7php-html-parser, simhash-py, internetarchive/wayback, boilerpipe, waybackurls, wpull, crawler4j

هذه الصفوف مجموعها 14. وهي تصنّف ما الذي حرّك pushed_at؛ لكنها لا تثبت بشكل مستقل إن كان المشروع مهجورًا أم لا.

ما الذي يبقى بعد الفلتر الكامل، وماذا يعني "يبقى" هنا

الادعاء الأصلي يحتاج أربعة شروط في الوقت نفسه: أن يكون المشروع قديمًا لأكثر من عام، وأن يكون pushed_at متضخمًا بأكثر من 180 يومًا، وأن لا يكون مؤرشفًا، وأن لا توجد إشارة إلى أن التضخيم سببه عمل بشري. تسعة من أصل 35 مرشحًا يجتازون الشروط الأربعة كلها، موضّحة هنا إلى جانب الاستبعادين الأكثر أهمية:

RepoClears all four?Positive evidence that bots drove the inflation
splashyesyes — 4 of 4 post-commit events on dependabot/pip/*
waybackurlsyesnone in either direction
crawler4jyesnone in either direction
geziyoryesyes — 5 of 5 on dependabot/go_modules/*
php-html-parseryesnone in either direction
boilerpipeyesnone in either direction
wpullyesnone in either direction
internetarchive/waybackyesnone in either direction
simhash-pyyesnone in either direction
any23no — archivedyes — 16 of 16 on dependabot/maven/*, the single strongest confirmation in the whole audit
abotno — its record contains a human push (upgrade1, 2024)mixed — the push that set its headline pushed_at really was dependabot

هذا الرقم يحتاج إلى قيد لا يستطيع الفلتر حمله. اثنان فقط من تلك التسعة — splash وgeziyor — لديهما دليل إيجابي على أن الروبوتات كانت سبب التضخيم. أما السبعة الباقية فتنطبق عليها الحالة الرابعة لغياب أي دليل في الاتجاهين. هذه حالات ينجو فيها الادعاء، لا حالات تؤكّده. وأقوى تأكيد في التدقيق كله، وهو any23 مع 16 من 16 حدثًا من dependabot، مستبعد لأن المستودع مؤرشف.

لاحظ أيضًا أن abot، حالة 1,802 يومًا، ليست ضمن التسعة. فالسجل يحتوي على دفع بشري، لذا يفشل الشرط الرابع — أي أن أكثر الوهم دراماتيكية في مجموعة البيانات ليس مثالًا نظيفًا على الآلية التي يوضحها.

بالنسبة لـ21 من 35، كان GitHub صريحًا بشأن القدم

هذه هي النتيجة التي أضعفت فرضيتي أكثر من غيرها. أربعة عشر مستودعًا لديها فجوة تساوي الصفر تمامًا، وسبعة أخرى أقل من 180 يومًا. بالنسبة إلى 21 من أصل 35 مرشحًا، كان pushed_at هو نفسه أحدث commit على الفرع الافتراضي. GitHub لا يخفي شيئًا هنا.

بما في ذلك بعض أكثر العناصر مواتاةً للموت داخل العينة:

RepoStarsStale (days)Gap
Janpot/microdata-node571,8660
1e0ng/simhash1,0371,60621
ekzhu/SetSimilaritySearch6031,3840
GerbenJavado/LinkFinder4,4318340
hakluke/hakrawler5,0995820
lavague-ai/LaVague6,3885510
my8100/scrapydweb3,4115220
getomni-ai/zerox12,2584320
scrapinghub/frontera1,3324150
BuilderIO/gpt-crawler22,3743840

لدى BuilderIO/gpt-crawler 22,374 نجمة، وما زالت ترويته تقول الشيء نفسه منذ 2025-07-07. لا يوجد ما هو مخفي، وما زال حجم التثبيت قائمًا.

هذا يفرض على الادعاء أن يتقلّص إلى شيء أضيق: GitHub يخفي القدم في أقلية من الحالات، وفي الأغلبية يصرّح بها بوضوح بينما تستمر عمليات التثبيت على أي حال. سبب استمرارها خارج ما تستطيع هذه البيانات تفسيره — فالأرقام هنا تعدّ التثبيتات، لا القرارات. لكن لا تغييرًا في واجهة المستخدم يعالج المجموعة الثانية، وهي الأكبر.

قد يختلف نشاط المستودع عن الأصل المنشور

أكثر صف لافت في مجموعة البيانات يقلب الإطار كله.

codelucas/newspaper — 15,126 نجمة — نشِط. أحدث commit على فرعه الافتراضي مؤرخ في 2026-07-21، مقارنة بتاريخ القياس 2026-07-27، وقد كتبه الم维护. وكل فحوصات مستوى المستودع تمرّ بنجاح.

الحزمة التي يثبتها الجميع هي newspaper3k 0.2.8، المنشورة في 2018-09-28. هذا عمره 2,858 يومًا، ويسحب 813,513 تنزيلًا شهريًا.

الفرع الافتراضي حديث، بينما أصل PyPI لم يُنشر منذ 2018. هذا يثبت وجود فجوة في الإصدارات، لا سبب عدم النشر ولا ما إذا كانت هناك مشكلة في خط الإنتاج. وهذا هو نوع الخطر الذي سيفوته أي فحص يقتصر على المستودع، لأن الأصل في السجل هو ما يُشغَّل عادة بعد pip install newspaper3k.

وعندما تنظر إلى الحزم بدلًا من المستودعات، يظهر النمط في كل مكان. من بين 17 حزمة تم التحقق من نسبتها إلى مستودعاتها، 16 لم تُنشَر منذ أكثر من عام، وهذه الـ16 تمثل نحو 2.28 مليون تثبيت شهريًا من أصل 2.30 مليون تقريبًا:

PackageInstalls/monthLast publishedPackage age (days)
newspaper3k813,5132018-09-282,858
tls-client790,3052024-02-02905
simhash317,6152022-03-031,606
microdata-node204,0252020-05-112,267
@modelcontextprotocol/server-puppeteer127,2322025-05-12440
extract-thinker10,9272025-06-09412
SetSimilaritySearch7,9842022-10-111,384
frontera4,7092019-04-052,669
zerox3,3032025-05-20432
scrapydweb1,1632025-02-16525
lavague6062024-08-05720
splash3332020-06-162,231
dragnet2132019-04-162,658
@builder.io/gpt-crawler1372025-01-23549
lmnr-index1202025-06-05416
simhash-py1132017-03-223,413

يستحق tls-client سطرًا مستقلًا: 790,305 تثبيتًا شهريًا من مستودع خامد منذ 905 أيام، في فئةٍ يُعد البقاء فيها على أحدث نسخة جوهر المهمة كلها. سلوك TLS في المتصفحات يتغيّر؛ ومكتبة توقفت عن متابعته في مطلع 2024 تعمل على افتراضات مطلع 2024.

ملاحظتان على هذا الجدول. أعداد التنزيل من السجلات تشمل تشغيلات CI والنسخ المرآة ولا تستبعد التكرار، لذا فهي تقيس حجم التثبيت لا البشر. كما أن النوافذ الزمنية ليست موحّدة النهاية — فقريبة npm تنتهي عند 2026-07-24، بينما أرقام pypistats نسبية إلى وقت الجلب — لذا فالمجموع هو جمع لأشهر متداخلة قليلًا، ويُقرأ على أنه "حوالي 2.28 مليون" لا على أنه رقم دقيق خانة بخانة.

تشابه أسماء يستحق الانتباه

internetarchive/wayback هو OpenWayback مكتوب بـJava وقد مات، وركد منذ 1,916 يومًا. أما wayback على PyPI فهو مشروع مختلف تمامًاedgi-govdata-archiving/wayback — وهو سليم، إذ نشر الإصدار 0.5.1 في 2026-06-19، أي قبل تاريخ القياس بخمسة أسابيع. الاسم نفسه، والحالة معاكسة، ولا علاقة بينهما. كانت هذه واحدة من الحالات الست المستبعدة في النسبة، وهي الأرجح أن تربك مستخدمًا حقيقيًا: البحث بالاسم يعطيك الاثنين، ولا شيء في أي صفحة يوضح أيهما وجدت.

مؤرشف وموقوف وما زال يُثبَّت 127,232 مرة شهريًا

ستة مستودعات في العينة تحمل archived: true، ويعرضها GitHub على شكل شريط عريض أعلى الصفحة. وقرائي الأولى كانت أن هذا يثبت أن الناس يتجاهلون التحذيرات الصاخبة. لكن التخزين المؤقت يقول إن القصة أسوأ من ذلك.

المرجع الرسمي: npm download-count API documentation.

المرجع الرسمي: npm's deprecation documentation.

@modelcontextprotocol/server-puppeteer يسحب 127,232 تثبيتًا شهريًا من modelcontextprotocol/servers-archived. لكن حقل repository في npm لديه هو null — فلا يوجد رابط من صفحة الحزمة إلى المستودع، وبالتالي لا يوجد شريط يمكن أن يتجاوزه المثبّت. معظم من يجلبون هذه الحزمة لم يكن لديهم أصلًا طريق يصلون به إلى المستودع.

ما ينشره npm بالفعل هو الإهمال المعلن. فالإصدار الأحدث من الحزمة يحمل deprecated: "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." — ويطبعه npm في الطرفية عند التثبيت. إذًا وصل التحذير، في المكان الذي يوجد فيه المستخدم فعلًا، ومع ذلك تستمر 127,232 عملية تثبيت شهريًا. وهذه نتيجة أقوى من مجرد الشريط التحذيري، كما أنها تشير إلى مكان مختلف: الإشارة ليست مفقودة، بل تصل داخل سيل من مخرجات التثبيت لا يُجبر أحدًا على قراءتها.

أما browserbase/mcp-server-browserbase فيُظهر كيف يبدو الإغلاق المنظّم: commitه الأخير على الفرع الافتراضي، في 2026-07-20، يحمل حرفيًا عبارة "Mark repository as archived and unmaintained (#198)". أعلنها المساهمون، وأرخوها، ووضعوها في الـAPI. لكن 20,389 تثبيتًا من المشروع تستحق القراءة بعناية — فنافذة npm تمتد من 2026-06-25 إلى 2026-07-24، لذا 26 من تلك الأيام الثلاثين تسبق commit الأرشفة. هذا الرقم يعكس الطلب قبل الإعلان في معظمه، لا تجاهل الإعلان. وما سيحدث بعد ذلك لا يمكن استنتاجه حقًا من هذه اللقطة، وأحتاج قراءة ثانية بعد شهر قبل أن أزعم شيئًا.

57 نجمة، و204,025 تثبيتًا شهريًا

Janpot/microdata-node لديه 57 نجمة ويسحب 204,025 تنزيلًا شهريًا من إصدار مؤرّخ في 2020-05-11.

مع 57 نجمة فقط، يمتلك microdata-node حضورًا محدودًا في المستودع مقارنةً بحجم التثبيت في السجل. ونسبة التثبيت إلى النجوم البالغة 3,579 إلى 1 تتوافق مع الاستخدام غير المباشر، أو التكرار في CI، أو النسخ المرآة، أو الاستهلاك الآلي المباشر. لم يجلب هذا التدقيق رسومًا بيانية للاعتماد، ولا يمكنه ترجيح أي من هذه التفسيرات.

هذا الصف دعوة إلى فحص التعرض غير المباشر، لكن إثبات الاستخدام غير المباشر يحتاج إلى أدلة على التبعيات العكسية أو ملفات القفل، وهي أمور لم يجمعها هذا التدقيق.

القديم ليس بالضرورة معطّلًا

لا بد أن يقول التدقيق الصادق هذا: لا شيء هنا يقيس ما إذا كان شيء ما معطّلًا. إنه يقيس فقط ما إذا كان هناك أحد في البيت.

بعض هذه الأدوات منتهية ببساطة. SetSimilaritySearch يطبّق خوارزميات تشابه المجموعات؛ وهذه لا تتعفّن. وsimhash هو ورقة بحثية من عام 2007. وخوارزمية استخلاص المحتوى في boilerpipe تعمل في 2026 كما كانت تعمل في 2015 — بغضّ النظر عن دقتها أمام الصفحات الحديثة، فالكود نفسه لم ينفصل عن الواقع من تحتك.

ما يتعفّن هو كل ما له طرف متحرك في الجهة الأخرى:

  • أتمتة المتصفح — كل إصدار من Chrome يمكن أن يكسرها.
  • سلوك عميل HTTP الذي يحاكي المتصفحات الحقيقية — المتصفحات تتغير، والمكتبة المتجمّدة تتوقف عن المطابقة؛ tls-client يقع هنا.
  • المحللات الخاصة بموقع معيّن وقواعد الاستخلاص لكل موقع — كل إعادة تصميم لموقع هي خطأ.
  • أي شيء يلفّ API لطرف ثالث — يغيّر المورّد المخطط وتكتشف ذلك في الإنتاج.
  • أي شيء يلفّ LLM — إهمال النماذج أسرع من كل ما سبق.

لذلك فإن "قديم منذ 1,606 يومًا" هو حريق شامل لفئةٍ ما، لكنه أقرب إلى غير ذي صلة لأداة تجزئة. لم يُختبر أي كسر هنا، ولا يُدّعى وقوعه؛ وتصنيف تبعياتك بحسب الفئة التي تنتمي إليها لا يكلف شيئًا، ويمنحك فائدة أكبر بكثير من رقم القدم وحده.

الفحوص الأربعة التي تجيب فعلًا عن السؤال

System diagram: The four checks that actually answer the question

ولا واحد منها هو ترويسة المستودع.

#CheckWhere to read itWhat it catches
1The last commit on the default branchGET /repos/{owner}/{repo}/commits?sha={default_branch}&per_page=1The number that isn't shown to you.
2The last time the artifact shippedpypi.org/pypi/{pkg}/json or registry.npmjs.org/{pkg} → newest version and its upload dateThis is what catches newspaper3k, and check 1 never will. While you're there, read npm's deprecated field, which is how @modelcontextprotocol/server-puppeteer announces itself.
3The archived flagOne field in the repo response, unambiguous and freeNote that it only helps if you reached the repo at all, which repository: null packages don't let you do.
4The gap between 1 and 2— (derived from the two above)A repo with fresh commits and a three-year-old release is a different failure from one that's simply cold: it means the maintainer is present but not shipping. That's a decision to make with your eyes open, not a red flag on its own. The same logic applies in reverse to crawlab: check whether work moved to a non-default branch before concluding anything.

شغّل الفحوص 1 و2 و3 كفرز أولي سريع. ثم ارفع مستوى التدقيق عندما تكون بيانات المستودع الوصفية غائبة، أو عندما تكون نسبة الحزمة إلى المستودع ملتبسة، أو عندما ينتقل النشاط إلى فرع غير افتراضي، أو عندما يختلف الأصل المنشور عن المستودع. كما أن حدود GitHub غير المصرح به وكمون السجلّات يجعل الوعد بزمن ثانية واحدة غير مناسب.

إذا كشف فحص ما شيئًا خامدًا في فئةٍ سريعة الحركة، فهناك بدائل مُصانة ومُوثّقة في اختباراتنا الخاصة: Trafilatura لاستخلاص المحتوى الذي كان dragnet وboilerpipe يقومان به، وScrapy أو Crawlee لأطر الزحف، وCrawl4AI وFirecrawl للاستخلاص الموجّه نحو LLM، وScrapling عندما تكون المرونة مهمة. كما يتتبع العمود الأساسي لأدوات السحب مفتوحة المصدر المجموعة الأوسع. هذه مراجعات من المصدر الأول؛ شغّل الفحوص الأربعة بنفسك قبل أن تثق بأي توصية، بما فيها توصيتنا.

حدود هذه البيانات

  • اختيار العينة. تم اختيارها يدويًا بسبب الاشتباه في الهجر. لا يمكن استنتاج نسب على مستوى المنظومة منها.
  • لا اختبار للكسر. لم يُشغَّل أيٌّ من هذه الأدوات الـ35 على موقع حي. القدم مؤشر صيانة، لا حكم وظيفي.
  • أعداد التنزيل تشمل الآلات. CI، والنسخ المرآة، وعدم إزالة التكرار، ونوافذ زمنية لا تشترك في تاريخ نهاية واحد. إنها حجم تثبيت، لا عدد مستخدمين، ولا قرارات.
  • تظل الأسباب السبع غير المعروفة غير معروفة. موجز النشاط لم يرجع شيئًا، وبالنسبة لخمسة من السبعة لا يفسّر الاحتفاظ ذلك. ترك الخانة فارغة أفضل من ملئها بالتخمين الشائع.
  • staleness_days يستخدم تواريخ الـcommitter. التاريخ المعاد كتابته أو المؤرَّخ سابقًا سيشوّه القياس. لم يُكتشف شيء من هذا، وهذا لا يساوي عدم وجوده.
  • تاريخ قياس واحد. 2026-07-27. كثير من هذه المستودعات سيكون قد تحرك بحلول وقت قراءتك لهذا النص — وnewspaper خصوصًا يلتزم بانتظام. أعد تشغيل الفحوص الأربعة؛ ولا تستشهد بتواريخي.

كيف يغيّرُت الخدمة المُدارة شكلَ هذه المسألة

يوجد كل فحص هنا لأنك مع مكتبة مستضافة ذاتيًا تتحمّل أنت القدم. إذا توقّف عميل HTTP متجمّد عن التصرف مثل متصفح حديث، فهذه حادثتك أنت، في أي ساعة تظهر فيها.

ملاحظة المؤلف: Thunderbit هو منتجنا المُدار لاستخراج البيانات. تنقل الخدمة المُدارة بعض مسؤولية الصيانة إلى المورّد، لكن التغطية وزمن الاستجابة والاعتماد على مزود واحد واستمرارية هذا المزود تصبح جزءًا من نموذج المخاطر. لم يتم تقييم Thunderbit في هذا التدقيق الخاص بالمستودعات.

المقايضة الصادقة: أنت تتخلى عن القدرة على قراءة المصدر، وتثبيت نسخة محددة، وإصلاحها بنفسك عند الثانية صباحًا. بالنسبة لفريق يصون أدوات السحب أصلًا، يكون الخيار مفتوح المصدر غالبًا هو الخيار الصحيح — والفحوص الأربعة هي الطريقة التي تجعل هذا قرارًا لا افتراضًا.

جرّب Thunderbit لاستخراج بيانات الويب

الخلاصة المختصرة

أنشأتُ قائمة لأثبت أن GitHub يخفي الهجر. والوهم حقيقي في 14 من أصل 35 مستودعًا، وبشكل لافت في حالة واحدة: sjdirect/abot يبدو كأنه تلقى دفعًا الأسبوع الماضي بينما الفرع الافتراضي مجمّد منذ 2021، أي بفجوة 1,802 يومًا.

لكن الآلية أضيق من القصة. تسعة مستودعات فقط تجتاز كل شرط يحتاجه الادعاء، واثنان فقط من هذه التسعة — splash وgeziyor — لديهما دليل إيجابي على أن الروبوتات هي التي ضخّمت الطابع الزمني؛ والبقية تجتاز المعيار بغياب الدليل. مستودعان معلَّمان هما بشر يحاولون إحياء مشروع ويفشلون. وواحد، هو crawlab, لديه 12,250 نجمة ونقل التطوير ببساطة إلى develop. وبالنسبة لسبعة، رجع موجز النشاط فارغًا، والاحتفاظ لا يفسّر خمسة منها، لذا فالسبب غير محسوم لا مفترض. كما أن GitHub عرض القدم بدقة في 21 من أصل 35 مستودعًا.

أسوأ حالة في مجموعة البيانات تجتاز كل فحص على مستوى المستودع. فقد تم الالتزام بـ codelucas/newspaper في 2026-07-21؛ أما newspaper3k، الذي صدر آخر مرة في 2018-09-28، فقد تم تثبيته 813,513 مرة في ذلك الشهر. وعلى مستوى العينة كلها، فإن 16 حزمةً لم تُنشر منذ أكثر من عام تمثل نحو 2.28 مليون تثبيت شهريًا.

افحص تاريخ commit الفرع الافتراضي، وتاريخ إصدار الحزمة في السجل، وحقل الأرشفة، وحقل الإهمال في npm كفرز أولي. ثم تحقّق من نسب الحزمة إلى المستودع ومن التطوير خارج الفرع الافتراضي قبل أن تحكم.

جرّب Thunderbit لاستخراج بيانات الويب Get Started Free

الأسئلة الشائعة

ما هو pushed_at ولماذا لا يعني "آخر تحديث"؟ pushed_at هو حقل GitHub API الذي يظهر كطابع النشاط في صفحة المستودع، ويتحدث عندما تُدفع أي تغييرات إلى أي فرع. أما أحدث commit على الفرع الافتراضي فهو أحد مؤشرات صيانة المستودع، بينما يثبّت مديرو الحزم عادةً أصول السجل أو الإصدارات المحسومة من الوحدات. في هذا التدقيق، أظهر 14 من أصل 35 مستودعًا فرقًا يزيد على 180 يومًا بين تاريخي GitHub.

هل dependabot هو دائمًا من يضخّم هذا الطابع الزمني؟ لا، واتضح أن هذا كان أضعف جزء في القصة الشعبية. وعند احتساب الأحداث التي وقعت بعد آخر commit على الفرع الافتراضي فقط، تم تأكيد وجود روبوتات في 3 من أصل 14 مستودعًا معلّمًا (splash 4 من 4، وgeziyor 5 من 5، وany23 16 من 16). وفي حالتين الأمر خاطئ صراحةً: فجوة dragnet سببها إنسان دفع فرع Python 3.10 غير مدمج. وهناك حالتان مختلطتان، منها crawlab حيث نُفذ 24 دفعًا بشريًا إلى develop وtest بينما بقي main ثابتًا. أما في 7 حالات فلم يرجع موجز النشاط شيئًا أصلًا، لذا فالسبب غير محسوم — والاحتفاظ لا يفسر سوى حالتين من هذه السبع.

هل يعني المستودع القديم أن الأداة معطلة؟ ليس بحسب هذه الأدلة — فلم تُشغَّل أي أداة على موقع حي. وتزداد أهمية القدم بحسب سرعة تغيّر الهدف: أتمتة المتصفح، وعملاء HTTP الذين يحاكون سلوك المتصفح، والمحللات الخاصة بالمواقع وملفات API/LLM تتقادم بسرعة، بينما يمكن أن تظل المكتبات الخوارزمية مثل SetSimilaritySearch أو simhash قديمة لسنوات وتكون على ما يرام تمامًا. وtls-client هو أوضح مثال في العينة، إذ لديه 790,305 تثبيتًا شهريًا من مستودع خامد منذ 905 أيام.

كيف يمكن أن يكون المستودع نشطًا لكن الحزمة ميتة؟ هذا هو codelucas/newspaper، وهو أهم ما كشفه هذا التدقيق. ففرعه الافتراضي استُخدم في commit بتاريخ 2026-07-21، أي قبل أيام من تاريخ القياس، لكن newspaper3k على PyPI آخر ما شُحن منه كان 0.2.8 في 2018-09-28 — منذ 2,858 يومًا — ومع ذلك ما زال يسحب 813,513 تنزيلًا شهريًا. كل فحوص مستوى المستودع تمرّ، لكن الأصل الذي تثبّته عمره ثماني سنوات. افحص دائمًا أحدث تاريخ نشر في السجل منفصلًا عن سجل commits.

هل تحل المستودعات المؤرشفة المشكلة؟ GitHub يعرض شريطًا تنبيهيًا. ليس بشكل موثوق، و@modelcontextprotocol/server-puppeteer يوضح السبب. فحقل repository في npm لديه هو null، لذا لا يوجد رابط من الحزمة إلى المستودع المؤرشف ولا يوجد شريط يمكن تجاهله. ما يقدمه npm فعلًا هو سلسلة deprecated الخاصة بالحزمة — "Package no longer supported" — التي تُطبع عند التثبيت، ومع ذلك تستمر 127,232 عملية تثبيت شهريًا. أما browserbase/mcp-server-browserbase فأعلن الإيقاف بشكل صحيح في commitه الأخير؛ ومعظم عملياته البالغة 20,389 تثبيتًا سبقت ذلك الـcommit، لذا لا تقول الكثير في أي اتجاه.

كيف أتحقق من تبعياتي بسرعة؟ ابدأ بتاريخ commit الفرع الافتراضي، وتاريخ إصدار/رفع نسخة السجل، وحقل الإهمال في npm، وعلامة الأرشفة في المستودع. ثم تحقّق من نسبة الحزمة إلى المستودع، وافحص الفروع غير الافتراضية عندما يختلف النشاط، واستخدم خرائط التبعيات أو ملفات القفل قبل اعتبار التعرض غير مباشر. تشابه الأسماء مثل مشروعي wayback غير المرتبطين في Java وPyPI يجعل هذا التصعيد ضروريًا.

Ke
Ke
المدير التقني في Thunderbit | عالم بيانات أول وخبير في تعلّم الآلة بخبرة تقارب عقدًا من الزمن في تعلّم الآلة وعلم البيانات، كيه شين خريج جامعة كولومبيا وكان سابقًا عالم بيانات أول في Walmart Labs. وبفضل خبرته العميقة المعترف بها من قبل الأقران في Python وR وJava والإحصاء، يشارك رؤى مجرّبة حول نقل خوارزميات الذكاء الاصطناعي المعقدة من النظرية إلى بنية جاهزة للإنتاج.
فهرس المحتويات
Thunderbit · وكيل بيانات الويب بالذكاء الاصطناعي

استخرج البيانات من أي صفحة في بنقرة واحدة

موثوق لدى أكثر من 250,000 مستخدم
تتوفر خطة مجانية
من صفحة ويب إلى جدول بيانات
صف ما تحتاجه — ويقوم وكيل Thunderbit بالذكاء الاصطناعي باستخراجه وتصديره إلى Excel أو Google Sheets أو Airtable أو Notion. ابدأ مجانًا.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week