diff --git a/.agents/scripts/research/broad_scan.py b/.agents/scripts/research/broad_scan.py new file mode 100644 index 0000000..bbe8243 --- /dev/null +++ b/.agents/scripts/research/broad_scan.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +""" +Broad research scan: fetches recent high-signal content from fitness/science +sources without targeted search bias. Run occasionally to catch trends, +new studies, and community discussions. + +Sources: + - Reddit: r/weightroom, r/advancedfitness, r/StrongerByScience + - PubMed: recent articles on general resistance training +""" + +import json +import urllib.request +import urllib.parse +import time +import sys +from datetime import datetime, timezone +from xml.etree import ElementTree + +REDDIT_USER_AGENT = "fitness-agent/1.0 (research script; for personal training logs)" +SOURCES = { + "reddit": [ + "weightroom", + "advancedfitness", + "StrongerByScience", + ], + "pubmed_terms": [ + "resistance training", + "strength training programming", + "exercise physiology", + ], +} + + +def fetch_url(url, max_retries=2): + """Fetch content from a URL with retries.""" + for attempt in range(max_retries): + try: + req = urllib.request.Request(url, headers={"User-Agent": REDDIT_USER_AGENT}) + with urllib.request.urlopen(req, timeout=15) as resp: + return resp.read().decode() + except Exception as e: + if attempt < max_retries - 1: + time.sleep(3) + else: + return None + + +def fetch_reddit_posts(subreddit, limit=10): + """Fetch top posts from a subreddit via RSS.""" + # Use RSS feed (works without auth) + url = f"https://www.reddit.com/r/{subreddit}/hot/.rss?limit={limit}" + content = fetch_url(url) + if not content: + # Fallback: try old.reddit.com + url = f"https://old.reddit.com/r/{subreddit}/hot/.rss?limit={limit}" + content = fetch_url(url) + + if not content: + return [{"title": f"[Could not reach r/{subreddit}]", "url": "", "score": 0, "num_comments": 0}] + + posts = [] + try: + root = ElementTree.fromstring(content) + # RSS namespace + ns = {"": "http://www.w3.org/2005/Atom"} + for entry in root.findall(".//entry", ns): + title_el = entry.find("title", ns) + link_el = entry.find("link", ns) + updated_el = entry.find("updated", ns) + title = title_el.text if title_el is not None else "No title" + link = link_el.get("href", "") if link_el is not None else "" + updated = updated_el.text[:10] if updated_el is not None and updated_el.text else "?" + posts.append({ + "title": title, + "url": link, + "score": "?", + "num_comments": "?", + "date": updated, + }) + except Exception as e: + return [{"title": f"[Parse error: {e}]", "url": "", "score": 0, "num_comments": 0}] + + return posts if posts else [{"title": "No posts found", "url": "", "score": 0, "num_comments": 0}] + + +def fetch_pubmed_articles(term, max_results=5): + """Fetch recent PubMed articles on a broad topic.""" + base_url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/" + + # Search with retmode=json + search_url = ( + f"{base_url}esearch.fcgi?" + f"db=pubmed&term={urllib.parse.quote(term)}&" + f"retmax={max_results}&sort=date&retmode=json" + ) + content = fetch_url(search_url) + if not content: + return [{"title": f"[Could not reach PubMed for '{term}']", "url": "", "authors": "", "source": ""}] + + try: + search_data = json.loads(content) + except json.JSONDecodeError: + return [{"title": f"[Parse error for '{term}']", "url": "", "authors": "", "source": ""}] + + id_list = search_data.get("esearchresult", {}).get("idlist", []) + if not id_list: + return [{"title": "No recent articles found", "url": "", "authors": "", "source": ""}] + + # Respect NCBI rate limits: max 3 requests per second without API key + time.sleep(1) + + # Fetch details as XML + details_url = ( + f"{base_url}efetch.fcgi?" + f"db=pubmed&id={','.join(id_list)}&retmode=xml" + ) + xml_data = fetch_url(details_url) + if not xml_data: + return [{"title": f"[Could not fetch details for '{term}']", "url": "", "authors": "", "source": ""}] + + articles = [] + root = ElementTree.fromstring(xml_data) + for article in root.findall(".//PubmedArticle")[:max_results]: + medline = article.find(".//MedlineCitation") + article_data = medline.find(".//Article") if medline is not None else None + if article_data is None: + continue + + title_el = article_data.find("ArticleTitle") + title = "".join(title_el.itertext()) if title_el is not None else "No title" + + # Authors + author_list = article_data.findall(".//Author") + authors = [] + for author in author_list[:3]: + last = author.find("LastName") + fore = author.find("ForeName") + if last is not None: + name = last.text or "" + if fore is not None: + name += f" {fore.text or ''}" + authors.append(name) + author_str = ", ".join(authors) if authors else "Unknown" + + # Journal + journal = article_data.find(".//Journal/Title") + journal_str = journal.text if journal is not None else "Unknown journal" + + # PMID & link + pmid = medline.find(".//PMID") + pmid_str = pmid.text if pmid is not None else "" + link = f"https://pubmed.ncbi.nlm.nih.gov/{pmid_str}/" if pmid_str else "" + + articles.append({ + "title": title, + "url": link, + "authors": author_str, + "source": journal_str, + }) + + return articles if articles else [{"title": "No structured data", "url": "", "authors": "", "source": ""}] + + +def main(): + output = [] + output.append(f"# Broad Research Scan — {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") + output.append(f"_Auto-generated. Not targeted — general scan of recent content._\n") + + # --- Reddit --- + output.append("## Reddit\n") + for subreddit in SOURCES["reddit"]: + output.append(f"### r/{subreddit}\n") + posts = fetch_reddit_posts(subreddit) + for post in posts: + date_str = post.get("date", "?") + score_str = post.get("score", "?") + comments_str = post.get("num_comments", "?") + output.append(f"- **{post['title']}**") + if score_str != "?" or comments_str != "?" or date_str != "?": + output.append(f" - Score: {score_str} | Comments: {comments_str} | {date_str}") + output.append(f" - {post['url']}") + output.append("") + + # --- PubMed --- + output.append("## PubMed — Recent Articles\n") + for term in SOURCES["pubmed_terms"]: + output.append(f"### Topic: \"{term}\"\n") + articles = fetch_pubmed_articles(term) + for article in articles: + output.append(f"- **{article['title']}**") + if article.get("authors") and article.get("source"): + output.append(f" - {article['authors']} | {article['source']}") + if article.get("url"): + output.append(f" - {article['url']}") + output.append("") + + result = "\n".join(output) + print(result) + + # Save to dated file + import os + logs_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "logs", "research") + os.makedirs(logs_dir, exist_ok=True) + date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d") + filename = os.path.join(logs_dir, f"{date_str}-broad-scan.md") + with open(filename, "w") as f: + f.write(result) + print(f"\n--- Saved to {filename} ---", file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/logs/research/2026-06-26-broad-scan.md b/logs/research/2026-06-26-broad-scan.md new file mode 100644 index 0000000..de17c95 --- /dev/null +++ b/logs/research/2026-06-26-broad-scan.md @@ -0,0 +1,79 @@ +# Broad Research Scan — 2026-06-26 00:58 UTC +_Auto-generated. Not targeted — general scan of recent content._ + +## Reddit + +### r/weightroom + +- **[Could not reach r/weightroom]** + - Score: 0 | Comments: 0 | ? + - + +### r/advancedfitness + +- **[Could not reach r/advancedfitness]** + - Score: 0 | Comments: 0 | ? + - + +### r/StrongerByScience + +- **[Could not reach r/StrongerByScience]** + - Score: 0 | Comments: 0 | ? + - + +## PubMed — Recent Articles + +### Topic: "resistance training" + +- **Advances in Clinical Management Strategies for Sarcopenia: From Exercise and Nutrition to Pharmacotherapy and Comprehensive Interventions.** + - Xue Fei, Xu Hongyi, Yao Xinlei | Molecular neurobiology + - https://pubmed.ncbi.nlm.nih.gov/42348067/ +- **Improved Neuromuscular Performance in Low-Load vs. Moderate-Load Resistance Training Among Young Elite Swimmers.** + - Rodríguez-Rosell David, Neiva Henrique Pereira, Marinho Daniel Almeida | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347471/ +- **Expression of Concern: Barbalho et al. Effects of Adding Single Joint Exercises to a Resistance Training Programme in Trained Women. Sports 2018, 6, 160.** + - Sports Editorial Office | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347464/ +- **Effects of Velocity-Based French Contrast Training on Lower-Limb Power and Delivery Kinetics in Medium-Fast Cricket Bowlers: A Randomized Controlled Trial.** + - Zhao Qidong, Li Chunlei | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347450/ +- **Maximum Sprints Elicit Higher Peak Knee Joint Power than Resistance Training Exercises.** + - Alt Tobias, Clark Kenneth P, Augustsson Jesper | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347445/ + +### Topic: "strength training programming" + +- **Advances in Clinical Management Strategies for Sarcopenia: From Exercise and Nutrition to Pharmacotherapy and Comprehensive Interventions.** + - Xue Fei, Xu Hongyi, Yao Xinlei | Molecular neurobiology + - https://pubmed.ncbi.nlm.nih.gov/42348067/ +- **Resilience Building and Enhancing Mental Health: A Scoping Review of School-to-University Programs.** + - Nakorn Siriphorn Na, Chandler Genevieve E | Journal of psychosocial nursing and mental health services + - https://pubmed.ncbi.nlm.nih.gov/42347579/ +- **Improved Neuromuscular Performance in Low-Load vs. Moderate-Load Resistance Training Among Young Elite Swimmers.** + - Rodríguez-Rosell David, Neiva Henrique Pereira, Marinho Daniel Almeida | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347471/ +- **Expression of Concern: Barbalho et al. Effects of Adding Single Joint Exercises to a Resistance Training Programme in Trained Women. Sports 2018, 6, 160.** + - Sports Editorial Office | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347464/ +- **Sex-Based Differences in the Physical Capacity Profile of Regional Fencers.** + - Gaviria Chavarro Javier, Jiménez Trujillo Óscar Hernán, Gómez García Miguel Ángel | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347462/ + +### Topic: "exercise physiology" + +- **Advances in Clinical Management Strategies for Sarcopenia: From Exercise and Nutrition to Pharmacotherapy and Comprehensive Interventions.** + - Xue Fei, Xu Hongyi, Yao Xinlei | Molecular neurobiology + - https://pubmed.ncbi.nlm.nih.gov/42348067/ +- **Post-diagnosis physical activity in relation to mortality among prostate cancer survivors: a systematic review and meta-analysis.** + - Benker Pauline, Hamann Alina, Leitzmann Michael F | Cancer causes & control : CCC + - https://pubmed.ncbi.nlm.nih.gov/42348026/ +- **Effects of High-Impact Exercise on Bone Marker Concentrations During Controlled Low Energy Availability in Recreational Female Runners.** + - Sterringer Trisha, Sale Craig, Morozov Anna | Calcified tissue international + - https://pubmed.ncbi.nlm.nih.gov/42348018/ +- **Perspective: Personalized Management of Oxidative and Nitrosative Stress in Post-Exercise Recovery with a Particular Emphasis on the Potential of Micro-Immunotherapy.** + - Jacques Camille, Floris Ilaria | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347463/ +- **Effects of High-Intensity Interval Training with Blood Flow Restriction Versus Normobaric Hypoxia on Physiological Parameters in Apparently Healthy Young Men.** + - Narrea Vargas Jose Jairo, Castillo-Paredes Antonio, Iman Torres Alexander Javier | Sports (Basel, Switzerland) + - https://pubmed.ncbi.nlm.nih.gov/42347455/ +