Skip to content

Commit e948fb9

Browse files
committed
Fix lint and test errors
1 parent 08d571d commit e948fb9

226 files changed

Lines changed: 17460 additions & 553 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.env.example‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ ALLOWED_HOSTS=localhost,127.0.0.1
44
CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1,http://localhost:8080,http://127.0.0.1:8080
55

66
# Docker Compose runtime defaults. Host-side lint and test use .env.test instead.
7-
DATABASE_URL=postgresql://newsletter:newsletter@postgres:5432/newsletter_maker
7+
DATABASE_URL=postgresql://newsletter:newsletter@postgres:5432/digest_engine
88
REDIS_URL=redis://redis:6379/0
99
QDRANT_URL=http://qdrant:6333
1010

1111
OPENROUTER_API_KEY=
1212
OPENROUTER_API_BASE=https://openrouter.ai/api/v1
1313
OPENROUTER_APP_URL=
14-
OPENROUTER_APP_NAME=newsletter-maker
14+
OPENROUTER_APP_NAME=digest-engine
1515

1616
AI_CLASSIFICATION_MODEL=meta-llama/llama-3.1-70b-instruct
1717
AI_RELEVANCE_MODEL=qwen/qwen-2.5-72b-instruct
@@ -32,7 +32,7 @@ OLLAMA_URL=http://ollama:11434
3232

3333
REDDIT_CLIENT_ID=
3434
REDDIT_CLIENT_SECRET=
35-
REDDIT_USER_AGENT=newsletter-maker/0.1
35+
REDDIT_USER_AGENT=digest-engine/0.1
3636

3737
# Used to encrypt project-scoped Bluesky app passwords stored in the database.
3838
# Set this to a stable secret in each environment.

‎.env.test‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
DATABASE_URL=sqlite:///:memory:
22
OPENROUTER_API_KEY=test-key
33
OPENROUTER_API_BASE=https://openrouter.ai/api/v1
4-
OPENROUTER_APP_NAME=newsletter-maker
4+
OPENROUTER_APP_NAME=digest-engine
55
OLLAMA_URL=http://ollama:11434
66
REDDIT_CLIENT_ID=client
77
REDDIT_CLIENT_SECRET=secret
8-
REDDIT_USER_AGENT=newsletter-maker/test
8+
REDDIT_USER_AGENT=digest-engine/test
99
CELERY_BROKER_URL=memory://
1010
CELERY_RESULT_BACKEND=cache+memory://
1111
ALLOWED_HOSTS=localhost,127.0.0.1,nginx,testserver

‎.github/copilot-instructions.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Newsletter Maker Project Instructions
1+
# Digest Engine Project Instructions
22

3-
You are working in Newsletter Maker, a Django + DRF + Celery + Qdrant backend with a Next.js App Router frontend.
3+
You are working in Digest Engine, a Django + DRF + Celery + Qdrant backend with a Next.js App Router frontend.
44

55
## Repository Shape
66

77
- Backend runtime code is split across `core/`, `projects/`, `content/`, `entities/`, `ingestion/`, `newsletters/`, `pipeline/`, `trends/`, and `users/`.
8-
- Django project settings and top-level URLs live in `newsletter_maker/`.
8+
- Django project settings and top-level URLs live in `digest_engine/`.
99
- Backend tests live in app-local `tests/` packages first (`users/tests/`, `projects/tests/`, `ingestion/tests/`, `newsletters/tests/`, `pipeline/tests/`), with `core/tests/` reserved for the remaining cross-cutting coverage.
1010
- The repo-root `tests/` package is for integration coverage only. New unit and app-scoped tests should live in the owning app's `tests/` package.
1111
- Frontend application code lives in `frontend/src/app/`, shared UI in `frontend/src/components/`, and shared API/types/helpers in `frontend/src/lib/`.

‎.github/instructions/backend-python.instructions.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
name: "Backend Python Guidelines"
3-
description: "Use when editing Django, DRF, Celery, plugin, management command, or backend test code in Python. Covers project scoping, workflow placement, docstrings, and focused validation for core/, newsletter_maker/, tests/, and manage.py."
3+
description: "Use when editing Django, DRF, Celery, plugin, management command, or backend test code in Python. Covers project scoping, workflow placement, docstrings, and focused validation for core/, digest_engine/, tests/, and manage.py."
44
applyTo:
55
- "core/**/*.py"
6-
- "newsletter_maker/**/*.py"
6+
- "digest_engine/**/*.py"
77
- "tests/**/*.py"
88
- "manage.py"
99
---

‎.github/instructions/documentation.instructions.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ applyTo:
1414
- When a behavior changes, update the closest existing document instead of adding a new overlapping explanation.
1515
- Keep `docs/DEVELOPER_GUIDE.md` current when the best "where to look first" path changes for contributors.
1616
- Keep `README.md` high-level. Put detailed runtime, workflow, or operator guidance in `docs/` and link to it.
17-
- When documenting backend behavior, align the wording with the real implementation in files like `core/models.py`, `core/tasks.py`, `core/pipeline.py`, `core/newsletters.py`, `core/api.py`, and `newsletter_maker/settings/`.
17+
- When documenting backend behavior, align the wording with the real implementation in files like `core/models.py`, `core/tasks.py`, `core/pipeline.py`, `core/newsletters.py`, `core/api.py`, and `digest_engine/settings/`.
1818
- When documenting frontend behavior, align the wording with the real implementation in `frontend/src/app/`, `frontend/src/components/`, and `frontend/src/lib/`.
1919
- If a doc mentions commands, prefer the repo's real commands from `justfile`, `package.json`, or `manage.py`.
2020
- If a code change affects logging, relevance scoring, ingestion, newsletter intake, or onboarding, check whether `docs/LOGGING.md`, `docs/RELEVANCE_SCORING.md`, `docs/IMPLEMENTATION_OVERVIEW.md`, or `docs/DEVELOPER_GUIDE.md` should change too.

‎.github/workflows/build-release.yml‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ jobs:
3232
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
3333

3434
- name: Lint chart
35-
run: helm lint deploy/helm/newsletter-maker
35+
run: helm lint deploy/helm/digest-engine
3636

3737
- name: Render chart
38-
run: helm template newsletter-maker deploy/helm/newsletter-maker -f
39-
deploy/helm/newsletter-maker/values-minikube.yaml >
40-
/tmp/newsletter-maker-chart.yaml
38+
run: helm template digest-engine deploy/helm/digest-engine -f
39+
deploy/helm/digest-engine/values-minikube.yaml >
40+
/tmp/digest-engine-chart.yaml
4141

4242
- name: Render staging overlay
43-
run: helm template newsletter-maker-staging deploy/helm/newsletter-maker -f
44-
deploy/helm/newsletter-maker/values-staging.yaml >
45-
/tmp/newsletter-maker-staging-chart.yaml
43+
run: helm template digest-engine-staging deploy/helm/digest-engine -f
44+
deploy/helm/digest-engine/values-staging.yaml >
45+
/tmp/digest-engine-staging-chart.yaml
4646

4747
build-frontend:
4848
name: Build frontend
@@ -88,13 +88,13 @@ jobs:
8888
- name: Build backend image
8989
env:
9090
DOCKER_BUILDKIT: "1"
91-
run: docker build -t newsletter-maker-ci:${{ github.sha }} -f
91+
run: docker build -t digest-engine-ci:${{ github.sha }} -f
9292
docker/web/Dockerfile .
9393

9494
- name: Scan backend image with Trivy
9595
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
9696
with:
97-
image-ref: newsletter-maker-ci:${{ github.sha }}
97+
image-ref: digest-engine-ci:${{ github.sha }}
9898
scan-type: image
9999
severity: HIGH,CRITICAL
100100
ignore-unfixed: true
@@ -111,22 +111,22 @@ jobs:
111111
- name: Publish backend image
112112
if: github.event_name == 'push'
113113
env:
114-
IMAGE_REPOSITORY: ghcr.io/${{ github.repository_owner }}/newsletter-maker
114+
IMAGE_REPOSITORY: ghcr.io/${{ github.repository_owner }}/digest-engine
115115
run: |
116116
set -euo pipefail
117117
118-
docker tag newsletter-maker-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:${GITHUB_SHA}
118+
docker tag digest-engine-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:${GITHUB_SHA}
119119
docker push ${IMAGE_REPOSITORY}:${GITHUB_SHA}
120120
121121
if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
122-
docker tag newsletter-maker-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:main
122+
docker tag digest-engine-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:main
123123
docker push ${IMAGE_REPOSITORY}:main
124124
fi
125125
126126
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
127127
version_tag="${GITHUB_REF#refs/tags/}"
128-
docker tag newsletter-maker-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:${version_tag}
128+
docker tag digest-engine-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:${version_tag}
129129
docker push ${IMAGE_REPOSITORY}:${version_tag}
130-
docker tag newsletter-maker-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:latest
130+
docker tag digest-engine-ci:${GITHUB_SHA} ${IMAGE_REPOSITORY}:latest
131131
docker push ${IMAGE_REPOSITORY}:latest
132132
fi

‎README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Newsletter Maker
1+
# Digest Engine
22

33
![Image of AI-powered newsletter workflow](readme.jpg)
44

5-
An AI-powered content curation platform for technically-oriented newsletters. Newsletter Maker ingests content from dozens of sources, builds authority models of people and companies in a domain, and surfaces the most relevant articles, trends, and themes for each edition — so editors spend their time writing, not searching.
5+
An AI-powered content curation platform for technically-oriented newsletters. Digest Engine ingests content from dozens of sources, builds authority models of people and companies in a domain, and surfaces the most relevant articles, trends, and themes for each edition — so editors spend their time writing, not searching.
66

77
The system is organized into projects: each newsletter project has its own tracked entities, relevance model, and content pipeline. Projects are assigned to Django groups so editorial access can be shared cleanly. Designed for non-technical editors who don't know what a vector database is and don't need to.
88

@@ -68,7 +68,7 @@ just k8s-build-minikube
6868
just k8s-install-minikube
6969

7070
# Terminal 2
71-
kubectl port-forward svc/newsletter-maker-newsletter-maker-nginx 8080:80
71+
kubectl port-forward svc/digest-engine-digest-engine-nginx 8080:80
7272
```
7373

7474
- Admin UI: <http://localhost:8080/admin/>
@@ -99,7 +99,7 @@ For full workflows and troubleshooting, see [docs/developer-guide/local-developm
9999

100100
## What This Does That Existing Tools Don't
101101

102-
Tools like Feedly, UpContent, and ContentStudio handle parts of the content curation problem. Newsletter Maker combines several capabilities none of them offer:
102+
Tools like Feedly, UpContent, and ContentStudio handle parts of the content curation problem. Digest Engine combines several capabilities none of them offer:
103103

104104
- **Authority scoring from newsletter cross-referencing.** By ingesting peer newsletters, the system builds an authority model based on who real editors actually link to — a human-curated endorsement signal no existing tool provides.
105105
- **Per-project relevance training.** Upvote/downvote feedback trains a personalized relevance model per project. The tool learns what each editorial project considers valuable.
@@ -172,7 +172,7 @@ The system is designed for graceful failure, not silent corruption. Unparseable
172172

173173
## Project Documentation
174174

175-
Newsletter Maker documentation is organized by audience inside the `docs/` folder:
175+
Digest Engine documentation is organized by audience inside the `docs/` folder:
176176

177177
- [User Guide](docs/user-guide/getting-started-saas.md) covers managing projects, intaking content, and curating drafts.
178178
- [Admin Guide](docs/admin-guide/overview.md) covers installation, configuration, user management, and operational health.

‎content/admin.py‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
"""Admin configuration for content-domain models."""
22

3+
from typing import cast
4+
35
from django.contrib import admin, messages
46
from django.db.models import Avg
57
from django.utils.html import format_html
68
from unfold.admin import ModelAdmin
79

810
from content.models import Content, UserFeedback
11+
from core.settings_types import CoreSettings
912

1013

1114
def _score_to_percent(value):
@@ -124,6 +127,8 @@ def view_trace(self, obj):
124127
from django.conf import settings
125128
from django.urls import reverse
126129

130+
typed_settings = cast(CoreSettings, settings)
131+
127132
latest_skill_result = (
128133
obj.skill_results.filter(superseded_by__isnull=True)
129134
.order_by("-created_at")
@@ -173,12 +178,8 @@ def view_trace(self, obj):
173178
trace_id = value
174179
break
175180

176-
if (
177-
not trace_url
178-
and trace_id
179-
and getattr(settings, "AI_TRACE_URL_TEMPLATE", "")
180-
):
181-
trace_url = settings.AI_TRACE_URL_TEMPLATE.format(
181+
if not trace_url and trace_id and typed_settings.AI_TRACE_URL_TEMPLATE:
182+
trace_url = typed_settings.AI_TRACE_URL_TEMPLATE.format(
182183
content_id=obj.id,
183184
run_id=trace_id,
184185
skill_name=latest_skill_result.skill_name,

‎content/api.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from drf_spectacular.utils import extend_schema
44
from rest_framework import serializers, status, viewsets
55
from rest_framework.decorators import action
6+
from rest_framework.permissions import BasePermission
67
from rest_framework.response import Response
78

89
from content.models import Content, UserFeedback
@@ -12,8 +13,8 @@
1213
CONTENT_CREATE_REQUEST_EXAMPLE,
1314
CONTENT_RESPONSE_EXAMPLE,
1415
PROJECT_ID_PARAMETER,
15-
ProjectOwnedQuerysetMixin,
1616
SKILL_NAME_PARAMETER,
17+
ProjectOwnedQuerysetMixin,
1718
build_crud_action_overrides,
1819
document_project_owned_viewset,
1920
)
@@ -54,6 +55,7 @@ class ContentViewSet(ProjectOwnedQuerysetMixin, viewsets.ModelViewSet):
5455
def get_permissions(self):
5556
"""Allow all members to read content, contributors to edit, and admins to delete."""
5657

58+
permission_classes: list[type[BasePermission]]
5759
if self.action == "destroy":
5860
permission_classes = [IsProjectAdmin]
5961
elif self.action in {"create", "update", "partial_update", "run_skill"}:

‎content/tests/test_admin.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ def test_high_value_filter_only_returns_high_value_reference_content(
331331
model=Content,
332332
model_admin=ContentAdmin(Content, AdminSite()),
333333
)
334-
filter_instance.value = lambda: "high_value"
334+
cast(Any, filter_instance).value = lambda: "high_value"
335335

336336
filtered = filter_instance.queryset(_request(), Content.objects.all())
337337

@@ -368,7 +368,7 @@ def test_duplicate_state_filter_returns_canonical_rows_with_duplicate_signals(
368368
model=Content,
369369
model_admin=ContentAdmin(Content, AdminSite()),
370370
)
371-
filter_instance.value = lambda: "canonical_with_duplicates"
371+
cast(Any, filter_instance).value = lambda: "canonical_with_duplicates"
372372

373373
filtered = filter_instance.queryset(_request(), Content.objects.all())
374374

@@ -406,7 +406,7 @@ def test_duplicate_state_filter_returns_suppressed_duplicates(
406406
model=Content,
407407
model_admin=ContentAdmin(Content, AdminSite()),
408408
)
409-
filter_instance.value = lambda: "suppressed_duplicates"
409+
cast(Any, filter_instance).value = lambda: "suppressed_duplicates"
410410

411411
filtered = filter_instance.queryset(_request(), Content.objects.all())
412412

@@ -558,7 +558,7 @@ def test_high_value_filter_lookups_and_noop_queryset(source_admin_context):
558558
model=Content,
559559
model_admin=ContentAdmin(Content, AdminSite()),
560560
)
561-
filter_instance.value = lambda: None
561+
cast(Any, filter_instance).value = lambda: None
562562
content = Content.objects.create(
563563
project=source_admin_context.project,
564564
url="https://example.com/high-value-noop",

0 commit comments

Comments
 (0)