Proactive and schedule-driven; the ledger is what makes the rotation fair across runs.

Step 0 — Orient and resume

bash
# Read the durable ledger first — which pages were refreshed, when, and why.
cat .kortix/memory/content-refresh-log.md 2>/dev/null || echo "(no ledger yet)"

# Check any open refresh PR from a prior run.
gh pr list --repo {{target_repo}} --state open \
  --search 'in:title "content refresh" OR label:content-refresh' \
  --json number,title,headRefName,statusCheckRollup,url
If a prior PR is still open and unreviewed, note it and don't duplicate its pages in this run's batch.

Step 1 — Freshen the repo

bash
if [ -d /workspace/repo/.git ]; then
  cd /workspace/repo && git fetch origin && git checkout main && git reset --hard origin/main
else
  git clone --filter=blob:none https://github.com/{{target_repo}}.git /workspace/repo
  cd /workspace/repo
fi
Never start a refresh on a stale base.

Step 2 — Pull decay signals from Search Console

Through the scoped Search Console connector, pull impressions and clicks per URL for {{site_url}} over the trailing 28 days versus the 28 days before that, restricted to pages under {{content_path}}. Compute, per page:
  • Decay = percentage drop in impressions and clicks between the two windows.
  • Weight = decay severity × the page's absolute traffic in the trailing window (a big page with a small decline still outranks a tiny page in free fall).
Rank pages by weight. This is the raw candidate list before rotation.

Step 3 — Rotate using the ledger

Read each candidate's last-refreshed date from the ledger (never-refreshed pages count as oldest). Re-rank candidates by combining decay weight with staleness of coverage: a page refreshed in the last two weeks drops several places even if it's still the sharpest decliner; a page that's never been touched moves up. Take the top 3–5 pages as this week's batch — enough to make progress, small enough to keep the PR reviewable.

Step 4 — Isolated refresh branch

bash
cd /workspace/repo
BRANCH="content-refresh/$(date +%Y-W%V)"
git checkout -b "$BRANCH" origin/main
One branch per weekly run.

Step 5 — Refresh each page in the batch

For each page:
  1. Open the source file under {{content_path}}.
  2. Copy — rewrite sentences that read as dated (old product names, retired features, superseded positioning) to match current reality.
  3. Stats — find numbers, dates, and claims that have aged out (customer counts, benchmark years, "as of" figures) and update them from the current source of truth; if no current figure is available, soften the claim rather than leave a stale one.
  4. Internal links — grep the repo for the page's outbound internal links; repoint any that reference a renamed, merged, or retired page to its current location.
  5. Leave everything else on the page untouched — this is a refresh, not a rewrite.
bash
cd /workspace/repo
grep -rn "old-slug-or-renamed-page" {{content_path}} 2>/dev/null

Step 6 — Commit

bash
cd /workspace/repo
git add {{content_path}}
git commit -m "content: refresh $(date +%Y-W%V) batch

$(for each page: echo "- <page>: <decay signal> -> <what changed>")"

Step 7 — Open the PR (only, never publish)

bash
cd /workspace/repo
git push origin "$BRANCH"
gh pr create --repo {{target_repo}} --base main --head "$BRANCH" \
  --title "content: refresh $(date +%Y-W%V) batch" \
  --label content-refresh \
  --body "Generated by the content-refresh agent. Pages selected from Search
Console decay signals for {{site_url}}, rotated against pages already covered
recently. Per page: the decay signal that triggered inclusion and what was
refreshed (copy / stats / internal links). This PR is never merged by the
agent — a human reviews and decides what ships."

Step 8 — Update the ledger

Append a dated entry to .kortix/memory/content-refresh-log.md (see <ledger-format>).
Content decay refresh — Kortix Marketplace | Kortix