# Tech Medium Pipeline

> Tech Medium Pipeline

- Skill: `arvindrk/tech-medium-pipeline` (Agent Skill)
- Install (CLI): `npx skillmds@latest add arvindrk/tech-medium-pipeline`
- Raw SKILL.md: https://api.skillmd.com/api/skills/arvindrk/tech-medium-pipeline/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: arvindrk (https://skillmd.com/u/arvindrk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/arvindrk/tech-medium-pipeline

---


# Tech Medium Pipeline

This is the main orchestrator skill for the entire Medium content workflow. It coordinates discovery, topic selection, drafting, approval, and publication while preserving conversation state across WhatsApp messages.

## When to Use This Skill

Use this skill when:

- the user wants the full Medium workflow rather than a single subtask
- a cron trigger should start the daily research cycle
- an incoming WhatsApp reply must be interpreted as topic selection, edit intent, or publish approval
- shared state must be advanced to the next valid stage

Do not use this skill when the user explicitly wants only isolated research, only drafting, or only publication and no orchestration is required.

## Mission

Manage the full lifecycle of a tech article:

1. discover timely topics
2. send the shortlist to the user
3. resolve the user's selected topic
4. draft the article
5. wait for explicit publishing approval
6. publish to Medium
7. send the live URL back to the user

This skill should feel like one coherent assistant, even though it delegates to specialized skills internally.

## Internal Skills

Delegate to these skills whenever the corresponding stage is reached:

- `tech-news-researcher`
- `medium-article-drafter`
- `medium-browser-publisher`

Do not duplicate their core work unless invocation is impossible. Orchestration belongs here; specialized execution belongs in the worker skills.

## Defaults and Gotchas

- Default to reading shared state before interpreting the latest user message.
- Default to advancing exactly one workflow stage per invocation unless a worker skill completes synchronously and hands back the next state.
- Never treat ambiguous acknowledgements like `ok` or `looks good` as publish approval.
- Never let a fresh cron run overwrite an active draft awaiting approval unless the user explicitly wants a reset.

## Operating Model

Treat WhatsApp as the primary user interface and shared memory as the source of truth for pipeline state.

This skill should be able to start from:

- a cron trigger
- a direct user request like "find topics"
- a user reply containing a shortlist selection
- a user reply containing a publish approval

## Shared State Schema

Use a shared namespace:

- namespace: `tech-medium-pipeline`

Maintain at least these keys:

- `conversation_state`
- `latest_shortlist`
- `selected_topic`
- `latest_draft`
- `latest_publication`

The state object should be equivalent to:

```json
{
  "phase": "idle | awaiting_topic_selection | drafting | awaiting_publish_confirmation | publishing | published",
  "last_action": "string",
  "last_updated_at": "ISO-8601 timestamp",
  "active_topic_number": 3,
  "active_topic_headline": "Topic title",
  "draft_markdown_path": "/Users/.../drafts/2026-04-04-topic.md",
  "published_url": "https://medium.com/..."
}
```

## First-Run Initialisation

On the very first invocation the `tech-medium-pipeline` namespace will not exist in memory. Before reading any state, check whether `conversation_state` is present in the namespace.

If it is missing or empty, initialise the namespace with a clean baseline:

```json
{
  "conversation_state": {
    "phase": "idle",
    "last_action": "initialised",
    "last_updated_at": "<current ISO-8601 timestamp>"
  },
  "latest_shortlist": null,
  "selected_topic": null,
  "latest_draft": null,
  "latest_publication": null
}
```

After writing this baseline, continue with normal trigger handling as if the phase is `idle`.

Do not re-initialise if the namespace already contains a valid `conversation_state`. Only overwrite if the key is absent or the `phase` field is missing entirely.

## State Machine

### `idle`

No active cycle is underway.

Allowed next actions:

- start fresh research
- show the latest shortlist if it still exists and the user asks for it

### `awaiting_topic_selection`

The shortlist has been sent and the pipeline is waiting for the user to choose a topic.

Allowed user inputs:

- numeric selection such as `1`, `4`, or `topic 2`
- fuzzy selection such as `the second one`
- topic-name selection such as `do the local llm one`
- a request to refresh or regenerate the shortlist

### `drafting`

The selected topic is being researched and drafted.

While in this state:

- avoid parallel draft attempts for the same conversation
- complete the draft before switching stages

### `awaiting_publish_confirmation`

The user has received the draft and the system is waiting for explicit publish approval.

Treat these as positive publish intents:

- `yes`
- `publish`
- `post`
- `approve`
- `approved`
- `go ahead`
- `ship it`
- `post it`

Treat these as non-publish responses:

- edit requests
- revision requests
- questions about the draft
- vague acknowledgements like `ok` when intent is not explicit

When intent is ambiguous, ask a short confirmation question instead of publishing.

### `publishing`

The browser publisher is actively posting to Medium. Avoid duplicate publish attempts unless recovery is clearly needed.

### `published`

The story is live. The user can ask for the URL, request a new cycle, or ask for a follow-up article.

## Trigger Handling

### Cron Trigger

When triggered by cron:

1. set state to `idle` if no active publish-critical stage exists
2. invoke `tech-news-researcher`
3. save the refreshed shortlist
4. set state to `awaiting_topic_selection`
5. send the shortlist over WhatsApp

Do not auto-draft or auto-publish from cron alone.

### User Trigger: New Research Request

If the user says anything equivalent to:

- `find topics`
- `research today's topics`
- `what should I write about`
- `give me options`

Invoke `tech-news-researcher` and send a fresh shortlist.

### User Trigger: Topic Selection

If the system is waiting for a topic and the user responds with a valid selection:

1. resolve the selected topic against `latest_shortlist`
2. store the resolved topic in `selected_topic`
3. set state to `drafting`
4. invoke `medium-article-drafter`
5. set state to `awaiting_publish_confirmation`
6. send the draft over WhatsApp

### User Trigger: Publish Approval

If the system is waiting for approval and the user sends an approval phrase:

1. verify a draft exists
2. set state to `publishing`
3. invoke `medium-browser-publisher`
4. save the publication result
5. set state to `published`
6. send the live URL over WhatsApp

## Input Resolution Rules

### Numeric Selection Resolution

When the user sends a number:

- parse integers conservatively
- resolve the topic whose stored `number` exactly matches the user's selected number
- reject out-of-range values and ask the user to choose a valid topic

### Topic Name Resolution

When the user sends a topic phrase:

- compare it against shortlist headlines and angles
- prefer exact or near-exact matches
- if two entries are plausible, ask a disambiguation question

### Approval Resolution

Only publish when the approval is clearly affirmative and clearly refers to the current draft. If the user asks a question and says `yes` in the same message, interpret the overall intent before acting.

## WhatsApp Messaging Rules

Every outbound message should be optimized for chat:

- short introduction
- clear action or outcome
- no internal state dumps
- no raw JSON

Message patterns:

- shortlist message: numbered topics plus selection instruction
- draft message: full Markdown article plus explicit publish instruction
- publish message: title plus live URL plus short confirmation
- error message: brief explanation plus next step

## Recovery Rules

- If the user selects a topic before a shortlist exists, either regenerate one or ask whether to research the named topic directly.
- If the draft is missing at publish time, do not publish. Rebuild or ask the user to pick a topic again.
- If publication fails after the browser opens, preserve state and report whether the issue is login, UI, content insertion, or final publish confirmation.
- If a new cron run arrives while waiting for publish approval on an existing draft, do not overwrite the active cycle unless the user explicitly wants a new one.

## Concurrency and Safety Rules

- Never run two publish attempts for the same draft at once.
- Never publish from an old approval if a newer draft has replaced the active one.
- Never overwrite the active shortlist during an in-progress drafting or publishing stage unless the user requests a refresh.
- Never discard prior memory silently; update it deliberately.

## Editorial Rules

The pipeline should bias toward:

- timely but technically meaningful stories
- clear builder relevance
- concrete implications rather than vague trend talk
- strong articles over fast articles

The pipeline should avoid:

- duplicate article cycles for the same story unless the angle changed materially
- publication without approval
- shallow output produced only to keep the flow moving

## Completion Checklist

Before ending any invocation:

1. Determine the current phase from shared memory.
2. Interpret the incoming trigger correctly.
3. Execute only the next valid stage in the workflow.
4. Update shared memory to reflect the new state.
5. Send the correct WhatsApp response for that stage.
6. Leave the pipeline in a recoverable state if any downstream step fails.

