Skip to content
This repository was archived by the owner on Jun 23, 2026. It is now read-only.

Commit 1145de7

Browse files
committed
fix: address gemini-code-assist 4th review on PR #1
Accepted (5 / 9): - .pre-commit-config.yaml: bump astral-sh/ruff-pre-commit rev v0.8.4 → v0.15.13. The 0.8.4 tag really does not exist (gemini was right); v0.15.13 is current and matches the pinned `ruff` runtime version. [HIGH] - .github/dependabot.yml: Asia/Tokyo → Etc/UTC for all three update blocks. Neutral default for a public repo. [MEDIUM] - README.md: rewrite the scoring formula description to match the actual `(freshness × 2) + (keyword × source-weight) + severity` implementation (it was incorrectly listed as fully multiplicative). Also update the Layout block: `pr-checks.yml` was replaced by `ci.yml` plus `codeql.yml` and `audit.yml` two commits ago but the doc still pointed at the old name. [MEDIUM] - scripts/awsdd/_dates.py (new): house the shared `parse_iso` and an EPOCH constant. score.py and report.py now import from it instead of carrying duplicate `_parse_iso` definitions. [MEDIUM - DRY] - web/src/lib/data.ts: hoist the `86_400_000` magic number into a `MS_IN_DAY` constant. [MEDIUM] Rejected (4 / 9), reasoning: - requirements{,-dev}.txt "version does not exist" [CRITICAL ×2]: verified via `curl https://pypi.org/pypi/<pkg>/<ver>/json` — all seven pinned versions return HTTP 200 and `pip install` succeeds both locally and in every prior CI run. Gemini's knowledge cutoff predates these releases; the pins stay. - pyproject.toml `SIM108` (ternary nag) [MEDIUM]: deliberately disabled because `if/else` blocks often read clearer than nested ternaries in this code base. No change. - collect_rss `BeautifulSoup` swap [MEDIUM]: regex strip + DOMPurify sanitization on the rendering side already cover the layered defense; the dep cost outweighs the marginal robustness gain for the well-formed AWS feeds we consume. No change. Regenerated seed reports so the committed sample matches the (byte- identical) output the formatter now produces.
1 parent 4b7692d commit 1145de7

7 files changed

Lines changed: 41 additions & 37 deletions

File tree

.github/dependabot.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ updates:
77
interval: weekly
88
day: monday
99
time: "09:00"
10-
timezone: Asia/Tokyo
10+
timezone: Etc/UTC
1111
open-pull-requests-limit: 5
1212
labels:
1313
- dependencies
@@ -21,7 +21,7 @@ updates:
2121
interval: weekly
2222
day: monday
2323
time: "09:00"
24-
timezone: Asia/Tokyo
24+
timezone: Etc/UTC
2525
open-pull-requests-limit: 5
2626
labels:
2727
- dependencies
@@ -50,7 +50,7 @@ updates:
5050
interval: weekly
5151
day: monday
5252
time: "09:00"
53-
timezone: Asia/Tokyo
53+
timezone: Etc/UTC
5454
open-pull-requests-limit: 5
5555
labels:
5656
- dependencies

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.8.4
3+
rev: v0.15.13
44
hooks:
55
- id: ruff
66
args: [--fix]

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Site: <https://0-draft.github.io/aws-deepdive/>
2121
collect (RSS + GitHub Releases) → normalize → score → report (daily | weekly)
2222
```
2323

24-
Score = `freshness × keyword × source-weight × severity`. Items below the threshold stay in `normalized.json` but are not surfaced in the report.
24+
Score = `(freshness × 2) + (keyword × source-weight) + severity`. The keyword × source-weight product means an item with zero keyword hits only gets the freshness baseline, so generic What's-New noise does not float into topic-specific tracks. See [`scripts/awsdd/score.py`](./scripts/awsdd/score.py) for the exact weights.
2525

2626
## Layout
2727

@@ -38,10 +38,12 @@ tracks/<name>/
3838
reports/{daily,weekly}/<date>.md
3939
deep-dives/<topic>.md
4040
.github/workflows/
41+
ci.yml # PR + push to main: lint / test / build
42+
codeql.yml # CodeQL SAST (python + js/ts)
43+
audit.yml # pip-audit + npm audit + license report
4144
daily-update.yml # 06:00 UTC, matrix.track
4245
weekly-digest.yml # Mon 08:00 UTC
4346
deploy-pages.yml # push to main → Pages
44-
pr-checks.yml
4547
web/ # Astro 6 + Tailwind v4 + recharts (React island)
4648
```
4749

@@ -63,14 +65,14 @@ Python 3.12 / Node 22+ (Astro 6 requirement).
6365

6466
## CI
6567

66-
| Workflow | Trigger | Purpose |
67-
| -------------------- | -------------------------------------- | ------------------------------------------------------------------------ |
68-
| `ci.yml` | PR + push to `main` (code paths only) | ruff, astro check, markdownlint, actionlint, pytest+coverage, builds |
69-
| `codeql.yml` | PR + push to `main` + weekly cron | CodeQL SAST for Python and TS/JS |
70-
| `audit.yml` | weekly cron + manual + deps PR | `pip-audit`, `npm audit --audit-level=high`, license report (copyleft gate) |
71-
| `daily-update.yml` | 06:00 UTC cron | per-track collect / score / report; commits artefacts to `main` |
72-
| `weekly-digest.yml` | Mon 08:00 UTC cron | per-track weekly digest; commits artefact to `main` |
73-
| `deploy-pages.yml` | push to `main` (web/, tracks/ changes) | builds `web/dist` and publishes to GitHub Pages |
68+
| Workflow | Trigger | Purpose |
69+
| ------------------- | -------------------------------------- | --------------------------------------------------------------------------- |
70+
| `ci.yml` | PR + push to `main` (code paths only) | ruff, astro check, markdownlint, actionlint, pytest+coverage, builds |
71+
| `codeql.yml` | PR + push to `main` + weekly cron | CodeQL SAST for Python and TS/JS |
72+
| `audit.yml` | weekly cron + manual + deps PR | `pip-audit`, `npm audit --audit-level=high`, license report (copyleft gate) |
73+
| `daily-update.yml` | 06:00 UTC cron | per-track collect / score / report; commits artefacts to `main` |
74+
| `weekly-digest.yml` | Mon 08:00 UTC cron | per-track weekly digest; commits artefact to `main` |
75+
| `deploy-pages.yml` | push to `main` (web/, tracks/ changes) | builds `web/dist` and publishes to GitHub Pages |
7476

7577
PRs into `main` should be gated by branch protection requiring `ci.yml` jobs to pass. Configure once in repo Settings → Branches.
7678

scripts/awsdd/_dates.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from __future__ import annotations
2+
3+
from datetime import UTC, datetime
4+
5+
EPOCH = datetime(1970, 1, 1, tzinfo=UTC)
6+
7+
8+
def parse_iso(s: str) -> datetime:
9+
"""Parse an ISO-8601 string into a UTC-aware datetime.
10+
11+
Falls back to the Unix epoch (not "now") so corrupted or missing
12+
timestamps sink to the bottom of freshness rankings instead of being
13+
promoted to the top.
14+
"""
15+
try:
16+
return datetime.fromisoformat(s or "")
17+
except (ValueError, TypeError):
18+
return EPOCH

scripts/awsdd/report.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,13 @@
44
import json
55
from datetime import UTC, datetime, timedelta
66

7+
from ._dates import parse_iso
78
from .config import track_dir
89

910
TOP_N = {"daily": 10, "weekly": 25}
1011
WINDOW = {"daily": timedelta(days=2), "weekly": timedelta(days=7)}
1112

1213

13-
def _parse_iso(s: str) -> datetime:
14-
# Python 3.11+ accepts the "Z" suffix natively.
15-
# Fall back to the Unix epoch (not "now") so corrupted dates sink below
16-
# the freshness window instead of getting promoted to the top.
17-
try:
18-
return datetime.fromisoformat(s or "")
19-
except (ValueError, TypeError):
20-
return datetime(1970, 1, 1, tzinfo=UTC)
21-
22-
2314
def _filename(mode: str, now: datetime) -> str:
2415
if mode == "daily":
2516
return f"{now:%Y-%m-%d}.md"
@@ -32,7 +23,7 @@ def render(track: str, mode: str) -> None:
3223
items: list[dict] = json.loads(p.read_text()) if p.exists() else []
3324
now = datetime.now(UTC)
3425
cutoff = now - WINDOW[mode]
35-
fresh = [it for it in items if _parse_iso(it.get("published_at", "")) >= cutoff]
26+
fresh = [it for it in items if parse_iso(it.get("published_at", "")) >= cutoff]
3627
fresh.sort(key=lambda x: x.get("score", 0.0), reverse=True)
3728

3829
used_fallback = False

scripts/awsdd/score.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,14 @@
55
import math
66
from datetime import UTC, datetime
77

8+
from ._dates import parse_iso
89
from .config import load_sources, track_dir
910

1011
SEVERITY_WEIGHT = {"critical": 3.0, "high": 2.0, "medium": 1.0, "low": 0.5}
1112

1213

13-
def _parse_iso(s: str) -> datetime:
14-
# Python 3.11+ accepts the "Z" suffix natively.
15-
# Fall back to the Unix epoch (not "now") so corrupted dates yield ~0
16-
# freshness instead of an artificial max.
17-
try:
18-
return datetime.fromisoformat(s or "")
19-
except (ValueError, TypeError):
20-
return datetime(1970, 1, 1, tzinfo=UTC)
21-
22-
2314
def score_item(item: dict, sources: dict, now: datetime) -> dict[str, float]:
24-
pub = _parse_iso(item.get("published_at", ""))
15+
pub = parse_iso(item.get("published_at", ""))
2516
days = max(0.0, (now - pub).total_seconds() / 86400.0)
2617
freshness = math.exp(-days / 14.0) # ~14-day decay
2718

web/src/lib/data.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,15 @@ export function loadReports(track: Track, mode: "daily" | "weekly"): Report[] {
6767
}));
6868
}
6969

70+
const MS_IN_DAY = 86_400_000;
71+
7072
function isoWeekKey(d: Date): string | null {
7173
if (Number.isNaN(d.valueOf())) return null;
7274
const tmp = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
7375
const dayNum = tmp.getUTCDay() || 7;
7476
tmp.setUTCDate(tmp.getUTCDate() + 4 - dayNum);
7577
const yearStart = Date.UTC(tmp.getUTCFullYear(), 0, 1);
76-
const week = Math.ceil(((tmp.valueOf() - yearStart) / 86_400_000 + 1) / 7);
78+
const week = Math.ceil(((tmp.valueOf() - yearStart) / MS_IN_DAY + 1) / 7);
7779
return `${tmp.getUTCFullYear()}-W${String(week).padStart(2, "0")}`;
7880
}
7981

0 commit comments

Comments
 (0)