Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/monthly-gap-analysis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Monthly Gap Analysis
name: Gap Analysis
# Runs the Pathfinder gap-analysis pipeline on a 30-day lookback and publishes a
# ranked gap report to Notion, alerting Slack only when NEW high-severity gaps
# appear vs the prior run.
Expand Down Expand Up @@ -27,14 +27,14 @@ name: Monthly Gap Analysis
#
# Prior-run state (for new-gap diffing) is carried across runs as the
# `gap-analysis-state` artifact rather than the Actions cache: caches are
# evicted after 7 days of no access, but this job runs only every ~30 days, so
# evicted after 7 days of no access, but this job runs only every ~2 weeks, so
# the cache was always gone and EVERY high-severity gap re-alerted as "new".
# Artifacts persist 90 days regardless of access, comfortably past the cadence.
on:
schedule:
# Monthly, 1st of the month at 04:00 UTC — after the nightly reindex so the
# 30-day window reflects a freshly indexed corpus.
- cron: "0 4 1 * *"
# Bi-weekly, on the 1st and 15th of the month at 04:00 UTC — after the
# nightly reindex so the 30-day window reflects a freshly indexed corpus.
- cron: "0 4 1,15 * *"
workflow_dispatch:

permissions: {}
Expand Down Expand Up @@ -124,10 +124,10 @@ jobs:
path: /tmp/gap-report.md
if-no-files-found: ignore

# Persist updated state as a durable artifact so the next run (≈30 days
# Persist updated state as a durable artifact so the next run (≈2 weeks
# later) can diff new high-severity gaps. Artifacts live 90 days
# regardless of access — unlike the Actions cache, which evicts after 7
# days idle and so was always gone by the next monthly run. Upload only
# days idle and so was always gone by the next run. Upload only
# when the script actually wrote the state file.
- name: Upload gap-analysis state
if: always()
Expand Down
6 changes: 3 additions & 3 deletions scripts/gap-analysis/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Monthly Gap Analysis
# Gap Analysis

A scheduled pipeline that surfaces the documentation/knowledge gaps in
Pathfinder's indexed corpus by analyzing what users actually search for — and
what comes back empty — over a rolling 30-day window.

It runs from the [`monthly-gap-analysis.yml`](../../.github/workflows/monthly-gap-analysis.yml)
GitHub Action on the 1st of each month (04:00 UTC, after the nightly reindex)
and can be triggered manually via `workflow_dispatch`.
GitHub Action on the 1st and 15th of each month (04:00 UTC, after the nightly
reindex) and can be triggered manually via `workflow_dispatch`.

## What it does

Expand Down
6 changes: 3 additions & 3 deletions scripts/gap-analysis/monthly-gap-analysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* monthly-gap-analysis.ts
*
* Monthly (30-day lookback) Pathfinder gap-analysis pipeline. Designed to run
* Bi-weekly (30-day lookback) Pathfinder gap-analysis pipeline. Designed to run
* from a scheduled GitHub Action WITHOUT polluting production analytics:
*
* - It READS the analytics JSON API (GET /api/analytics/{summary,queries,
Expand Down Expand Up @@ -845,7 +845,7 @@ export async function persistAndMaybeAlert(opts: {
* title. The LLM rephrases gap titles run-to-run; keying on the normalized form
* means a TRIVIALLY reworded title for the same underlying gap (casing,
* punctuation, stop words, word order) is NOT reported as new — which would
* otherwise produce a monthly false-positive Slack storm. The collapse is only
* otherwise produce a recurring false-positive Slack storm. The collapse is only
* as strong as the normalization: a SUBSTANTIAL semantic rephrasing (different
* significant tokens) reduces to a different key and may still be reported as
* new. A null prior (first run, or missing/corrupt state) reports every high
Expand Down Expand Up @@ -1268,7 +1268,7 @@ async function postSlack(text: string): Promise<void> {
// ── Main ─────────────────────────────────────────────────────────────────────

async function main(): Promise<void> {
console.log("=== Pathfinder Monthly Gap Analysis ===");
console.log("=== Pathfinder Gap Analysis ===");

if (!ANALYTICS_TOKEN) {
// Dry/no-secrets mode: this is the expected state in CI lint before the
Expand Down