Skip to content

Commit 107a4fb

Browse files
author
Paolo Gabriel
committed
feat(runner): move outputs to content feeds tree
1 parent 5d08511 commit 107a4fb

12 files changed

Lines changed: 80 additions & 80 deletions

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ Google News link-resolution env toggles:
162162
- `config/interests.<topic>.md` — Keywords + Narrative (+ optional **Companies**; see [Company list](docs/sources.md#company-list-neurotech-startups))
163163
- `config/triage_prompt.txt` — Shared triage prompt
164164
- `content/briefs_articles.csv` — Chosen articles (topic column)
165-
- `content/briefs/` — Weekly briefs (`YYYY week N.md`)
166-
- `content/roundups/` — Monthly roundups (`YYYY-MM.md`)
167-
- `content/annual/` — Annual reviews (`YYYY review.md`)
165+
- `content/feeds/weekly/` — Weekly briefs (`YYYY week N.md`)
166+
- `content/feeds/monthly/` — Monthly roundups (`YYYY-MM.md`)
167+
- `content/feeds/yearly/` — Annual reviews (`YYYY review.md`)
168168
- `logs/` — Logs (at vault root; e.g. topic_actions_*.json, roundup logs)
169169
- `content/topics/` — Optional digital garden for topic redundancy and gardener
170170

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "tocify"
7-
version = "0.9.4"
7+
version = "0.9.5"
88
description = "Weekly Journal ToC Digest (RSS → triage → digest) and vault runner"
99
readme = "README.md"
1010
requires-python = ">=3.10"

tests/test_topic_gardener_default_behavior.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ def get_topic_paths(topic: str, vault_root: Path | None = None):
1515
feeds_path=root / "config" / f"feeds.{topic}.txt",
1616
interests_path=root / "config" / f"interests.{topic}.md",
1717
prompt_path=root / "config" / "triage_prompt.txt",
18-
briefs_dir=root / "content" / "briefs",
19-
roundups_dir=root / "content" / "roundups",
20-
annual_dir=root / "content" / "annual",
18+
weekly_dir=root / "content" / "feeds" / "weekly",
19+
monthly_dir=root / "content" / "feeds" / "monthly",
20+
yearly_dir=root / "content" / "feeds" / "yearly",
2121
logs_dir=root / "logs",
2222
briefs_articles_csv=root / "content" / "briefs_articles.csv",
2323
edgar_ciks_path=root / "config" / f"edgar_ciks.{topic}.txt",
@@ -139,9 +139,9 @@ def test_run_weekly_merge_gardener_allowlist_includes_existing_and_new_rows(self
139139
with tempfile.TemporaryDirectory() as td:
140140
root = Path(td)
141141
write_runner_inputs(root)
142-
briefs_dir = root / "content" / "briefs"
143-
briefs_dir.mkdir(parents=True, exist_ok=True)
144-
brief_path = briefs_dir / "2026-02-16_bci_weekly-brief.md"
142+
weekly_dir = root / "content" / "feeds" / "weekly"
143+
weekly_dir.mkdir(parents=True, exist_ok=True)
144+
brief_path = weekly_dir / "2026 week 08.md"
145145
brief_path.write_text(
146146
(
147147
"---\n"
@@ -166,7 +166,7 @@ def test_run_weekly_merge_gardener_allowlist_includes_existing_and_new_rows(self
166166
(
167167
"topic,week_of,url,title,source,published_utc,score,brief_filename,why,tags\n"
168168
"bci,2026-02-16,https://example.com/old,Existing item,Journal,2026-02-16T00:00:00+00:00,0.80,"
169-
"2026-02-16_bci_weekly-brief.md,Relevant,old\n"
169+
"2026 week 08.md,Relevant,old\n"
170170
),
171171
encoding="utf-8",
172172
)

tests/test_topic_redundant_mentions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ def get_topic_paths(topic: str, vault_root: Path | None = None):
1414
feeds_path=root / "config" / f"feeds.{topic}.txt",
1515
interests_path=root / "config" / f"interests.{topic}.md",
1616
prompt_path=root / "config" / "triage_prompt.txt",
17-
briefs_dir=root / "content" / "briefs",
18-
roundups_dir=root / "content" / "roundups",
19-
annual_dir=root / "content" / "annual",
17+
weekly_dir=root / "content" / "feeds" / "weekly",
18+
monthly_dir=root / "content" / "feeds" / "monthly",
19+
yearly_dir=root / "content" / "feeds" / "yearly",
2020
logs_dir=root / "logs",
2121
briefs_articles_csv=root / "content" / "briefs_articles.csv",
2222
edgar_ciks_path=root / "config" / f"edgar_ciks.{topic}.txt",

tests/test_weekly_google_news_resolution.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ def get_topic_paths(topic: str, vault_root: Path | None = None):
1818
feeds_path=root / "config" / f"feeds.{topic}.txt",
1919
interests_path=root / "config" / f"interests.{topic}.md",
2020
prompt_path=root / "config" / "triage_prompt.txt",
21-
briefs_dir=root / "content" / "briefs",
22-
roundups_dir=root / "content" / "roundups",
23-
annual_dir=root / "content" / "annual",
21+
weekly_dir=root / "content" / "feeds" / "weekly",
22+
monthly_dir=root / "content" / "feeds" / "monthly",
23+
yearly_dir=root / "content" / "feeds" / "yearly",
2424
logs_dir=root / "logs",
2525
briefs_articles_csv=root / "content" / "briefs_articles.csv",
2626
edgar_ciks_path=root / "config" / f"edgar_ciks.{topic}.txt",
@@ -81,7 +81,7 @@ def test_google_news_wrapper_resolves_before_weekly_url_dedupe(self) -> None:
8181
root = Path(td)
8282
write_runner_inputs(root)
8383
weekly.run_weekly(topic="bci", week_spec="2026 week 8", dry_run=0, vault_root=root)
84-
brief_path = root / "content" / "briefs" / "2026 week 08.md"
84+
brief_path = root / "content" / "feeds" / "weekly" / "2026 week 08.md"
8585
content = brief_path.read_text(encoding="utf-8")
8686
csv_text = (root / "content" / "briefs_articles.csv").read_text(encoding="utf-8")
8787

tests/test_weekly_link_resolution.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ def _get_topic_paths(topic: str, vault_root: Path | None = None):
1313
feeds_path=root / "config" / f"feeds.{topic}.txt",
1414
interests_path=root / "config" / f"interests.{topic}.md",
1515
prompt_path=root / "config" / "triage_prompt.txt",
16-
briefs_dir=root / "content" / "briefs",
17-
roundups_dir=root / "content" / "roundups",
18-
annual_dir=root / "content" / "annual",
16+
weekly_dir=root / "content" / "feeds" / "weekly",
17+
monthly_dir=root / "content" / "feeds" / "monthly",
18+
yearly_dir=root / "content" / "feeds" / "yearly",
1919
logs_dir=root / "logs",
2020
briefs_articles_csv=root / "content" / "briefs_articles.csv",
2121
edgar_ciks_path=root / "config" / f"edgar_ciks.{topic}.txt",
@@ -84,7 +84,7 @@ def test_run_weekly_rewrites_heading_to_canonical_url(self) -> None:
8484
root = Path(td)
8585
write_runner_inputs(root)
8686
weekly.run_weekly(topic="bci", week_spec="2026 week 8", dry_run=0, vault_root=root)
87-
brief_path = root / "content" / "briefs" / "2026 week 08.md"
87+
brief_path = root / "content" / "feeds" / "weekly" / "2026 week 08.md"
8888
content = brief_path.read_text(encoding="utf-8")
8989

9090
self.assertIn("## [Paper A](https://canonical.example.com/a)", content)
@@ -103,7 +103,7 @@ def test_run_weekly_delinks_untrusted_heading_when_resolver_errors(self) -> None
103103
root = Path(td)
104104
write_runner_inputs(root)
105105
weekly.run_weekly(topic="bci", week_spec="2026 week 8", dry_run=0, vault_root=root)
106-
brief_path = root / "content" / "briefs" / "2026 week 08.md"
106+
brief_path = root / "content" / "feeds" / "weekly" / "2026 week 08.md"
107107
content = brief_path.read_text(encoding="utf-8")
108108
finally:
109109
weekly._resolve_weekly_heading_links = original_resolver
@@ -120,7 +120,7 @@ def test_run_weekly_new_brief_frontmatter_omits_title(self) -> None:
120120
root = Path(td)
121121
write_runner_inputs(root)
122122
weekly.run_weekly(topic="bci", week_spec="2026 week 8", dry_run=0, vault_root=root)
123-
brief_path = root / "content" / "briefs" / "2026 week 08.md"
123+
brief_path = root / "content" / "feeds" / "weekly" / "2026 week 08.md"
124124
frontmatter = _read_frontmatter(frontmatter_module, brief_path)
125125

126126
self.assertNotIn("title", frontmatter)
@@ -136,7 +136,7 @@ def test_run_weekly_no_items_frontmatter_omits_title(self) -> None:
136136
root = Path(td)
137137
write_runner_inputs(root)
138138
weekly.run_weekly(topic="bci", week_spec="2026 week 8", dry_run=0, vault_root=root)
139-
brief_path = root / "content" / "briefs" / "2026 week 08.md"
139+
brief_path = root / "content" / "feeds" / "weekly" / "2026 week 08.md"
140140
frontmatter = _read_frontmatter(frontmatter_module, brief_path)
141141

142142
self.assertNotIn("title", frontmatter)
@@ -151,9 +151,9 @@ def test_run_weekly_merge_preserves_existing_title(self) -> None:
151151
with tempfile.TemporaryDirectory() as td:
152152
root = Path(td)
153153
write_runner_inputs(root)
154-
briefs_dir = root / "content" / "briefs"
155-
briefs_dir.mkdir(parents=True, exist_ok=True)
156-
brief_path = briefs_dir / "2026 week 08.md"
154+
weekly_dir = root / "content" / "feeds" / "weekly"
155+
weekly_dir.mkdir(parents=True, exist_ok=True)
156+
brief_path = weekly_dir / "2026 week 08.md"
157157
brief_path.write_text(
158158
(
159159
"---\n"
@@ -182,9 +182,9 @@ def test_run_weekly_merge_without_existing_title_keeps_title_absent(self) -> Non
182182
with tempfile.TemporaryDirectory() as td:
183183
root = Path(td)
184184
write_runner_inputs(root)
185-
briefs_dir = root / "content" / "briefs"
186-
briefs_dir.mkdir(parents=True, exist_ok=True)
187-
brief_path = briefs_dir / "2026 week 08.md"
185+
weekly_dir = root / "content" / "feeds" / "weekly"
186+
weekly_dir.mkdir(parents=True, exist_ok=True)
187+
brief_path = weekly_dir / "2026 week 08.md"
188188
brief_path.write_text(
189189
(
190190
"---\n"

tests/test_weekly_newspaper_guard.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ def get_topic_paths(topic: str, vault_root: Path | None = None):
1313
feeds_path=root / "config" / f"feeds.{topic}.txt",
1414
interests_path=root / "config" / f"interests.{topic}.md",
1515
prompt_path=root / "config" / "triage_prompt.txt",
16-
briefs_dir=root / "content" / "briefs",
17-
roundups_dir=root / "content" / "roundups",
18-
annual_dir=root / "content" / "annual",
16+
weekly_dir=root / "content" / "feeds" / "weekly",
17+
monthly_dir=root / "content" / "feeds" / "monthly",
18+
yearly_dir=root / "content" / "feeds" / "yearly",
1919
logs_dir=root / "logs",
2020
briefs_articles_csv=root / "content" / "briefs_articles.csv",
2121
edgar_ciks_path=root / "config" / f"edgar_ciks.{topic}.txt",
@@ -54,7 +54,7 @@ def test_use_newspaper_skips_executor_when_filtered_items_are_empty(self) -> Non
5454
root = Path(td)
5555
write_runner_inputs(root)
5656
weekly.run_weekly(topic="bci", week_spec="2026 week 8", dry_run=0, vault_root=root)
57-
brief_path = root / "content" / "briefs" / "2026 week 08.md"
57+
brief_path = root / "content" / "feeds" / "weekly" / "2026 week 08.md"
5858
self.assertTrue(brief_path.exists())
5959

6060

tocify/runner/annual.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ def main(
8787
if len(roundup_paths) < 12:
8888
tqdm.write(f"[WARN] Only {len(roundup_paths)} monthly roundups for {year} (partial year)")
8989

90-
output_path = output or paths.annual_dir / f"{year} review.md"
90+
output_path = output or paths.yearly_dir / f"{year} review.md"
9191
log_path = paths.logs_dir / f"{year}_{topic}_annual-review.log.md"
9292

93-
paths.annual_dir.mkdir(parents=True, exist_ok=True)
94-
paths.logs_dir.mkdir(parents=True, exist_ok=True)
93+
paths.yearly_dir.mkdir(parents=True, exist_ok=True)
94+
paths.logs_dir.mkdir(parents=True, exist_ok=True)
9595

9696
print(f"[INFO] Generating annual review for {year} from {len(roundup_paths)} monthly roundups")
9797

tocify/runner/clear.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
"""Remove all data for a topic: briefs/logs matching *_<topic>_*, and that topic's rows from briefs_articles.csv.
2-
Also provides cleanup of stray Cursor-produced action JSON files."""
1+
"""Remove all data for a topic: feeds/logs matching *_<topic>_*, and that topic's rows from briefs_articles.csv.
2+
Also provides cleanup of stray Cursor-produced action JSON files."""
33

44
import csv
55
import sys
@@ -88,7 +88,7 @@ def main(topic: str, vault_root: Path | None = None, confirm: bool = False) -> N
8888

8989
if not confirm:
9090
print(f"⚠️ WARNING: This will delete all data for topic '{topic}'!", file=sys.stderr)
91-
print(f" - Briefs and logs matching *_{topic}_*", file=sys.stderr)
91+
print(f" - Feed outputs and logs matching *_{topic}_*", file=sys.stderr)
9292
print(f" - Rows for {topic} in content/briefs_articles.csv", file=sys.stderr)
9393
print("", file=sys.stderr)
9494
print('Type "yes" to confirm: ', end="", file=sys.stderr)
@@ -101,27 +101,27 @@ def main(topic: str, vault_root: Path | None = None, confirm: bool = False) -> N
101101
sys.exit(1)
102102

103103
removed = 0
104-
if paths.briefs_dir.exists():
105-
for p in paths.briefs_dir.glob("* week *.md"):
106-
if p.is_file():
107-
p.unlink()
108-
removed += 1
109-
if paths.roundups_dir.exists():
110-
for p in paths.roundups_dir.glob("*.md"):
111-
if p.is_file():
112-
p.unlink()
113-
removed += 1
114-
if paths.annual_dir.exists():
115-
for p in paths.annual_dir.glob("* review.md"):
116-
if p.is_file():
117-
p.unlink()
118-
removed += 1
104+
if paths.weekly_dir.exists():
105+
for p in paths.weekly_dir.glob("* week *.md"):
106+
if p.is_file():
107+
p.unlink()
108+
removed += 1
109+
if paths.monthly_dir.exists():
110+
for p in paths.monthly_dir.glob("*.md"):
111+
if p.is_file():
112+
p.unlink()
113+
removed += 1
114+
if paths.yearly_dir.exists():
115+
for p in paths.yearly_dir.glob("* review.md"):
116+
if p.is_file():
117+
p.unlink()
118+
removed += 1
119119
if paths.logs_dir.exists():
120120
for p in paths.logs_dir.glob(f"*_{topic}_*"):
121121
if p.is_file():
122122
p.unlink()
123123
removed += 1
124-
print(f"Removed {removed} files for topic {topic} (weekly briefs, roundups, annual, logs)")
124+
print(f"Removed {removed} files for topic {topic} (weekly/monthly/yearly feeds, logs)")
125125

126126
csv_path = paths.briefs_articles_csv
127127
if csv_path.exists():

tocify/runner/monthly.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ def main(
101101
brief_paths = load_briefs_for_date_range(start_date, end_date, topic, vault_root=root)
102102
allowed_source_url_index = build_allowed_url_index_from_sources(brief_paths)
103103

104-
paths.roundups_dir.mkdir(parents=True, exist_ok=True)
105-
paths.logs_dir.mkdir(parents=True, exist_ok=True)
104+
paths.monthly_dir.mkdir(parents=True, exist_ok=True)
105+
paths.logs_dir.mkdir(parents=True, exist_ok=True)
106106
month_name = end_date.strftime("%B %Y")
107107
month_iso = end_date.strftime("%Y-%m")
108-
roundup_filename = paths.roundups_dir / f"{month_iso}.md"
108+
roundup_filename = paths.monthly_dir / f"{month_iso}.md"
109109
log_filename = paths.logs_dir / f"{end_date.isoformat()}_{topic}_monthly-roundup.log.md"
110110
fallback_content = f"# {topic.upper()} Monthly Roundup — {month_name}\n\n*No briefs found for this period.*\n"
111111

0 commit comments

Comments
 (0)