diff --git a/.github/workflows/monthly-gap-analysis.yml b/.github/workflows/monthly-gap-analysis.yml index 841c1c1..adaeecd 100644 --- a/.github/workflows/monthly-gap-analysis.yml +++ b/.github/workflows/monthly-gap-analysis.yml @@ -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. @@ -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: {} @@ -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() diff --git a/scripts/gap-analysis/README.md b/scripts/gap-analysis/README.md index 72a937b..cb88af1 100644 --- a/scripts/gap-analysis/README.md +++ b/scripts/gap-analysis/README.md @@ -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 diff --git a/scripts/gap-analysis/monthly-gap-analysis.ts b/scripts/gap-analysis/monthly-gap-analysis.ts index 5911a51..9542176 100644 --- a/scripts/gap-analysis/monthly-gap-analysis.ts +++ b/scripts/gap-analysis/monthly-gap-analysis.ts @@ -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, @@ -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 @@ -1268,7 +1268,7 @@ async function postSlack(text: string): Promise { // ── Main ───────────────────────────────────────────────────────────────────── async function main(): Promise { - 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