Skip to content
Back to skills

Whats Next

ASecurity

Use when: kullanıcı "ne yapayım", "şimdi ne", "next step", "öncelikli işler", "what to work on", "where do I start" der ya da UserPromptSubmit drift-router hook önerir. Also use when: yeni session açıldı, pending approval check gerek, decay/quick-wins prioritization istendi, tüm projeleri tarayıp en acil iş seçilecek. Do not use when: spesifik skill direkt çağrıldı (init-project, sf-import, quick-wins, drift-check) — whats-next router skill'dir, başka skill'leri SUGGEST eder, çağırmaz; adviso...

  • 27 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 2, 2026
ai-agentspythongoshellgit

Works with

  • cli
  • mcp

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add popiliadam/platinum-seo-engine --skill whats-next --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Whats Next?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Whats Next
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/popiliadam-whats-next/badge)](https://www.skillsdirectory.com/skills/popiliadam-whats-next)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: whats-next
description: |
  Use when: kullanıcı "ne yapayım", "şimdi ne", "next step", "öncelikli
  işler", "what to work on", "where do I start" der ya da UserPromptSubmit
  drift-router hook önerir.
  Also use when: yeni session açıldı, pending approval check gerek,
  decay/quick-wins prioritization istendi, tüm projeleri tarayıp en
  acil iş seçilecek.
  Do not use when: spesifik skill direkt çağrıldı (init-project,
  sf-import, quick-wins, drift-check) — whats-next router skill'dir,
  başka skill'leri SUGGEST eder, çağırmaz; advisory-only.
version: "1.0"
status: active
category: meta
inputs:
  user_intent:
    type: string
    required: false
    description: "Kullanıcı niyeti — varsa ranking'e bias eklenir."
  project_slug:
    type: string
    required: false
    description: "Tek proje filtre. Yoksa tüm projects/* taranır."
  top_k:
    type: integer
    required: false
    default: 3
    description: "Döndürülecek ranked recommendation sayısı."
outputs:
  - "events.jsonl"
consumes:
  - "init-project:projects/{slug}/master.xlsx"
  - "quick-wins:master.xlsx#quick_wins"
produces: []
triggers:
  manual: []
  natural_language: |
    "ne yapayım", "şimdi ne", "next step", "öncelikli işler",
    "what to work on", "where do I start", "öncelik sırası",
    "pending approval", "bekleyen onay"
  hooks: ["UserPromptSubmit"]
  scheduled: []
mcp_tools:
  required: []
  optional: []
budget:
  uses_paid_mcp: false
  estimated_credits: 0
autonomy:
  confidence: MEDIUM
  requires_approval: false
  safe_auto_execute: false
---

# whats-next — meta skill (Phase 5 Wave 2, router pattern)

Advisory-only **router** skill. Reads project state across four signal
sources (`master_task`, `content_decay`, `_state/workflows/*.json`
awaiting_approval, `quick_wins` pending approval), scores each
candidate with a fixed heuristic, and emits a Top-K ranked list of
*next skills to invoke*. Whats-next never invokes those skills itself
— a manager (or the user) reads the recommendation and picks one.

This is the **convention authority** for future router-style meta
skills (e.g. `daily-summary`, `incident-triage`). 10 numbered steps,
single workflow run shell, deterministic heuristic, schema-shaped
event emission. Reuse the structure verbatim; deviate only with an
ADR.

## Inputs (frontmatter contract)

| Name           | Type    | Default | Notes                                                        |
|----------------|---------|---------|--------------------------------------------------------------|
| `user_intent`  | string  | —       | Optional NL hint; passed through to the recommendation note. |
| `project_slug` | string  | —       | If omitted, all `projects/*/master.xlsx` are scanned.        |
| `top_k`        | integer | 3       | Cap on returned recommendations (1..10 enforced at runtime). |

## Outputs (artifacts produced)

- `projects/{slug}/_state/events.jsonl` — single `event_kind=work`,
  `event_type=skill_whats_next` row per run (canonical v1.6-Phase-2 H-E;
  replaces legacy DSL workaround `event_type=manual + note=[skill=...]`),
  `note` carries the markdown summary of the ranked recommendations
  (router event).
- Console / return-value: short markdown bullet list of the Top-K
  recommendations (advisory; no Excel writes).

## 10-Step Body Protocol

> Each step name must match the `steps[*].name` passed to
> `workflow_runner.create_run`. Names are stable identifiers across
> runs and form the audit trail in `_state/workflows/{run_id}.json`.

### Step 1 — `create_run`

Open a single workflow run shell. The state file lives at
`projects/{slug}/_state/workflows/{run_id}.json` (ADR-019, ADR-021).
Whats-next is single-project per run; if `project_slug` is omitted the
caller iterates the loop externally (one run per project).

```python
from scripts.state import workflow_runner
handle = workflow_runner.create_run(
    skill="whats-next",
    project_slug=project_slug,
    steps=[
        {"name": "scan_master_task"},
        {"name": "scan_content_decay"},
        {"name": "scan_pending_approvals"},
        {"name": "scan_quick_wins_pending"},
        {"name": "score_and_rank"},
        {"name": "emit_router_event"},
    ],
)
```

### Step 2 — `scan_master_task`

Open `projects/{slug}/master.xlsx` read-only via openpyxl
(`data_only=True`, `read_only=True`). If the sheet `master_task` is
absent, return an empty list (init-project not run yet — this is
AMBER, not RED). Otherwise iterate rows starting at
`data_start_row=4` and collect rows where:

- column J (`status`) == `"TODO"`, AND
- column G (`priority`) ∈ `{"CRITICAL", "HIGH", "MEDIUM", "LOW"}`.

Each row becomes a candidate `{kind: "master_task", row_id: A, task:
B, priority: G, ...}`.

### Step 3 — `scan_content_decay`

Same workbook. If the sheet `content_decay` is absent, return an
empty list (sheet not bootstrapped — AMBER, not error). Otherwise
iterate from `data_start_row=6` (per master-excel.schema) and collect
rows where:

- column F (`trend`) starts with `"RED"`, AND
- the row is recent (within last 7 days; if no date column is
  present, every RED row qualifies — date-gating is a Phase 6+
  refinement).

Each row becomes a candidate
`{kind: "content_decay_red", url: A, delta_pct: E, trend: F}`.

### Step 4 — `scan_pending_approvals`

Scan `projects/{slug}/_state/workflows/*.json`. For each file whose
top-level `status == "awaiting_approval"`, build a candidate
`{kind: "pending_approval", run_id, skill, subject:
approval_meta.subject, approver: approval_meta.approver}`.

Implementation: `workflow_runner.list_runs(project_slug,
status_filter="awaiting_approval")`.

### Step 4.5 — `scan_sf_crawl_freshness` (v1.8 Phase 4, non-blocking)

When the project's `project.config.json` carries
`sf.mcp.enabled == true` (Phase 1 D-SF-12 additive block), inspect
`_state/workflows/*.json` for the most recent completed
`sf-crawl-orchestrator` run. If the newest done run is older than
30 days (or NO done run exists), surface a non-blocking suggestion:
"consider running /pseo-sf-crawl {slug}".

```python
from scripts.meta import whats_next
suggestion = whats_next.suggest_sf_crawl_when_stale(
    project_slug,
    workspace_root=workspace_root,
    threshold_days=30,
)
if suggestion:
    candidates.append(suggestion)
```

Suggestion shape:
`{kind: "sf_crawl_stale", row_id: "<sentinel>", suggested_skill:
"sf-crawl-orchestrator", reason: "last sf-crawl > 30d (or none)"}`.

Score = 30 (below `master_task_medium=40` and `quick_wins_pending=50`)
so the suggestion never bumps a higher-priority signal off the
top-K. SF MCP not enabled in the config → helper returns `None` and
no candidate is added (no surface in suggestions).

### Step 5 — `scan_quick_wins_pending`

Same workbook. If the sheet `quick_wins` is absent, return empty.
Otherwise treat *every* `quick_wins` row as a "pending approval"
candidate (the row exists because Wave 1 quick-wins skill wrote it
and is waiting for the user to greenlight a downstream
`apply-quickwin` action). Candidate:
`{kind: "quick_wins_pending", query: A, url: B, opportunity: H}`.

### Step 6 — `score_and_rank` (heuristic, deterministic)

Each candidate gets a fixed score:

| Candidate kind                              | Score |
|---------------------------------------------|-------|
| `pending_approval` (workflow status)        | 100   |
| `content_decay_red` (RED trend, last 7d)    | 80    |
| `master_task` priority=`CRITICAL`/`HIGH`    | 60    |
| `quick_wins_pending` (row in `quick_wins`)  | 50    |
| `master_task` priority=`MEDIUM`             | 40    |
| `sf_crawl_stale` (v1.8 Phase 4 SF MCP)      | 30    |
| `master_task` priority=`LOW` / other        | 20    |

Sort `score DESC`, then by stable secondary key (kind alphabetic,
then row index) to keep output deterministic across runs. Truncate
to `top_k` (clamped to `[1, 10]`).

Each ranked entry maps to a *suggested* downstream skill:

| kind                | suggested skill          |
|---------------------|--------------------------|
| pending_approval    | (resume / approve via workflow_runner) |
| content_decay_red   | content-decay (Phase 6)  |
| master_task         | done-protocol / done-cascade |
| quick_wins_pending  | apply-quickwin (Phase 7) |

### Step 7 — Top-K ranked recommendation list (return value)

Build the structured output:

```python
recommendations = [
    {
      "rank": 1,
      "score": 100,
      "kind": "pending_approval",
      "suggested_skill": "(resume awaiting_approval run)",
      "reason": f"workflow {run_id} ({skill}) waiting on {approver}",
    },
    ...
]
```

### Step 8 — `emit_router_event` (events.jsonl router event)

Single `event_kind=work`, `event_type=skill_whats_next` row per run
(canonical v1.6-Phase-2 H-E). The `task_id` is a synthetic router id
derived from the workflow run_id
hex token (events.schema requires `^T-[0-9]{4,}$`; we map the 4-char
hex token → 5-digit decimal prefixed with `9` so router ids never
collide with master_task `T-NNNN` ids):

```python
from scripts.state import events_writer
hex_token = handle.run_id.split("-")[-1]            # e.g. "1a2b"
synthetic = 90000 + (int(hex_token, 16) % 9999)     # T-9XXXX
task_id = f"T-{synthetic}"
note = render_markdown_summary(recommendations, user_intent)
events_writer.append_work(
    project_id=project_slug,
    event_type="skill_whats_next",
    task_id=task_id,
    note=note,           # required for skill_X canonical (events.schema v1.6-Phase-2 H-E)
    primary_source="manual",
)
```

The `note` field is the same markdown bullet list returned to the
caller — keeping events.jsonl self-describing for archival replay.

### Step 9 — Output structured ranking (return + console)

Render the recommendations to a short markdown bullet list:

```
**whats-next — Top-3 recommendations** (project: {slug})

1. [score 100] pending_approval — workflow {run_id} ({skill}) bekliyor; approve veya reject.
2. [score  80] content_decay_red — https://example.com/page (RED, -42%); content-decay skill çalıştır.
3. [score  60] master_task HIGH — T-0042 "Refresh meta tags"; done-protocol başlat.
```

Return as a string to the caller (stdout if invoked as CLI, function
return value if invoked from a manager). No Excel writes.

### Step 10 — `complete`

```python
workflow_runner.complete(handle.run_id, project_slug=project_slug, outputs={
    "recommendations_count": str(len(recommendations)),
    "top_skill": recommendations[0]["suggested_skill"] if recommendations else "(none)",
})
```

**F5 invariant:** every value in `outputs` is a STRING. `int` outputs
break workflow-run.schema validation (Wave 1 lesson, applies forever).

## Heuristic rationale

- **pending_approval=100** — a paused workflow blocks all forward
  progress. Always surface first.
- **content_decay_red=80** — recent RED trend = active loss. Outranks
  optimizations.
- **master_task HIGH=60** — explicit human priority signal.
- **quick_wins_pending=50** — opportunity, not loss; below decay.
- **master_task MEDIUM=40 / LOW=20** — tail.

Ties broken by `(kind, row_id)` for run-to-run stability.

## Router discipline (advisory only)

Whats-next **NEVER** invokes another skill. It reads, scores, and
suggests. The caller (manager session, /whats-next slash, or
UserPromptSubmit drift-router hook output) is responsible for picking and invoking the
recommended skill. This separation keeps the router bug surface small
(read-only + one event emit) and lets the user override every
recommendation.

## DURUR conditions (4)

Stop and flag the manager — do not patch, do not fall back.

1. `workflow_runner.create_run` fails (schema, lock, or
   workspace_root resolution).
2. `master.xlsx` for the requested `project_slug` does not exist
   (project not initialized — route the user to `init-project`
   instead of returning empty).
3. `PSEO_WORKSPACE_ROOT` env unset AND no `workspace_root` argument
   passed.
4. `events_writer.append_work` raises `EventValidationError` (router
   event itself failed schema — never proceed silently).

Sheet-absent (master_task / content_decay / quick_wins) is **NOT** a
DURUR — those are AMBER (return empty candidate list, continue).

## Cross-references

- Schemas: `schemas/skill-frontmatter.schema.json` (frontmatter),
  `schemas/events.schema.json` (event_kind=work, event_type=skill_whats_next,
  task_id pattern, note required), `schemas/workflow-run.schema.json`
  (outputs string-typed, F5).
- Cross-modules: `scripts/state/workflow_runner.py`,
  `scripts/state/events_writer.py`, `openpyxl` (read-only).
- Tests: `tests/skills/test_whats_next.py` (7 cases; all tmp_path
  fixtures — no live workspace-staging side effects).
- ADRs: ADR-013 (use_when string), ADR-019 (retry_count), ADR-020
  (event_kind=workflow), ADR-021 (`_state/` path).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.