Skill: zhao-weijie/pain2mvp (version 1.0.2)

--- name: pain2mvp description: Discover and structure product opportunities from public user discussions, then convert top opportunities into a lightweight PRD for a coding agent. Use when the user needs direction on what to build, or wants to find recurring pain points, unmet needs, competitor complaints, or market signals around an idea, user group, or product category. version: 1.0.2 metadata: openclaw: install: - kind: brew formula: jq bins: [jq] skillKey: pain2mvp requires: bins: - node - npm env: - TIDB_DATABASE_URL primaryEnv: TIDB_DATABASE_URL --- # Painpoint To MVP ## Modes 1. Discovery mode: find and rank product opportunities from public user discussion evidence. 2. PRD mode: turn one persisted opportunity into a lightweight PRD for a coding agent. If the user asks for both, discovery comes first. ## Hard Rules - `references/contracts.md` is the only runtime contract reference. - Only inspect scripts when a documented helper command fails unexpectedly or when explicitly modifying this skill. - Read `references/contracts.md` once per run, not repeatedly. ## Preferred Commands Use these commands for normal operation: - `npm run bootstrap:tidb` - `npm run tidb -- save-evidence-batch` - `npm run tidb -- save-opportunity-batch` - `npm run tidb -- get-opportunity` - `npm run tidb -- save-prd` - `npm run tidb -- get-prd` - `npm run tidb -- list-runs` Compatibility-only commands: - `npm run tidb -- save-evidence` - `npm run tidb -- save-opportunity` Use the single-row save commands only for manual recovery or compatibility flows. ## Normal Execution Defaults - Check required environment once per run. - Collect evidence first, then persist in batch. - Prefer JSON via stdin over temp files. - Use `--input-file` only when the payload is too large or awkward for stdin. ## Discovery Mode 1. Read `references/contracts.md` once. 2. Check required environment. 3. Collect evidence with search/scraping tools or skills (e.g. bundled websearch, meirkad/bright-data, buksan1950/reddit-readonly). 4. Persist all evidence with `save-evidence-batch`. 5. Cluster and rank opportunities using the contract rubric. 6. Persist ranked opportunities with `save-opportunity-batch`. 7. Return a ranked summary with `run_id`, `opportunity_id`, score, confidence, and caveats. ## PRD Mode 1. Resolve the target opportunity by `opportunity_id`, or by `run_id` plus rank when explicitly provided. 2. Read the persisted opportunity with `get-opportunity`. 3. Generate the PRD from the persisted opportunity and its evidence, not chat memory. 4. Persist the PRD with `save-prd`. 5. Return the human-readable PRD and include `prd_id`. ## Non-Drift Rules - Never invent SQL. Use the documented helper commands. - Never generate a PRD from an unpersisted opportunity summary. - Never use conversational numbering like "opportunity #2" as the only identifier once results are persisted. - Never claim product-market fit. - When evidence is weak, say `insufficient evidence`. - Preserve contradictions when sources disagree. ## Quality Bar - Prefer repeated, concrete complaints over clever one-offs. - Distinguish category pain from vendor-specific complaints. - Keep evidence traceable through `source_url`, `pain_cluster_id`, and persisted identifiers. - Optimize PRDs for a coding agent with explicit scope, non-goals, constraints, and acceptance criteria.

path: package-lock.json
content: {
  "name": "pain2mvp",
  "version": "0.1.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "pain2mvp",
      "version": "0.1.0",
      "dependencies": {
        "@tidbcloud/serverless": "^0.3.0"
      }
    },
    "node_modules/@tidbcloud/serverless": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/@tidbcloud/serverless/-/serverless-0.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "engines": {
        "node": ">=16"
      }
    }
  }
}


path: package.json
content: {
  "name": "pain2mvp",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "bootstrap:tidb": "node scripts/bootstrap_tidb.mjs",
    "tidb": "node scripts/tidb_tool.mjs"
  },
  "dependencies": {
    "@tidbcloud/serverless": "^0.3.0"
  }
}

path: README.md
content: # pain2mvp

OpenClaw skill for turning public user pain points into ranked opportunities and persisted PRDs.

## Install

1. Install this skill via ClawHub.
2. Navigate to your local skills directory for this skill.
3. Run `npm install` to install local dependencies.
4. Set `TIDB_DATABASE_URL` to your TiDB Cloud Zero database URL with `?sslaccept=strict`.
5. Run `npm run bootstrap:tidb` to initialize tables.

## Use

- Discovery mode: ask for top pain points by user group, idea, or existing solution.
- Example: "What are the top pain points for in-house IP counsel?"
- Example: "What are OpenClaw users frustrated by?" or "What are Harvey users complaining about?"
- PRD mode: ask for a PRD from a persisted opportunity id or latest high-confidence result.
- Example: "Generate a PRD from opportunity `opp_20260328_01`."

See `SKILL.md` for runtime flow and `references/contracts.md` for the command contract.


path: scripts/bootstrap_tidb.mjs
content: import { ensureTables, getConnection, parseTidbUrl, printError, printJson } from "./tidb_lib.mjs";

try {
  const { databaseName } = parseTidbUrl(process.env.TIDB_DATABASE_URL);
  const conn = getConnection();
  await ensureTables(conn);
  printJson({
    ok: true,
    command: "bootstrap:tidb",
    database: databaseName,
    tables: ["opportunity_snapshots", "prds", "agent_memory"],
  });
} catch (error) {
  printError(error);
  process.exitCode = 1;
}


path: scripts/tidb_tool.mjs
content: import { dispatchCommand, getConnection, printError, printJson, readCommandInput } from "./tidb_lib.mjs";

try {
  const command = process.argv[2];
  if (!command) {
    throw new Error("Missing command");
  }

  const payload = await readCommandInput(process.argv.slice(3));
  const conn = getConnection();
  const result = await dispatchCommand(conn, command, payload);
  printJson({
    ok: true,
    command,
    result,
  });
} catch (error) {
  printError(error);
  process.exitCode = 1;
}


path: references/contracts.md
content: # Painpoint To PRD Contracts

This file is the runtime contract for discovery, persistence, and PRD generation.

Runtime note:

- `scripts/` is not part of the runtime interface.
- The supported interface is `npm run tidb -- <command>`.

## Scoring Rubric

Score each opportunity from `0-100`:

- `recurrence` (`0-25`)
- `severity_and_urgency` (`0-20`)
- `workaround_burden` (`0-20`)
- `buying_or_switching_signal` (`0-15`)
- `evidence_quality_and_freshness` (`0-20`)

Confidence is separate:

- `High`
- `Medium`
- `Low`

Use `insufficient evidence` when ranking is too weak to support confidence.

## Payloads

### `EvidenceRow`

Required fields:

- `source_url`
- `source_type`
- `author_handle`
- `community_or_site`
- `published_at`
- `snippet`
- `pain_cluster_id`
- `engagement_signals`
- `retrieval_timestamp`
- `traceability_status`

```json
{
  "source_url": "https://example.com/thread",
  "source_type": "reddit_comment",
  "author_handle": "user123",
  "community_or_site": "r/startups",
  "published_at": "2026-03-20T12:00:00Z",
  "snippet": "We still stitch three tools together.",
  "pain_cluster_id": "run_20260328_01:cluster_a",
  "engagement_signals": { "score": 18 },
  "retrieval_timestamp": "2026-03-28T13:00:00Z",
  "traceability_status": "verified"
}
```

### `WorkerEvidenceBundle`

Workers may return only this payload.

Required fields:

- `run_id`
- `worker_id`
- `query_scope`
- `evidence_rows`
- `notes`

```json
{
  "run_id": "run_20260328_01",
  "worker_id": "worker_reddit_a",
  "query_scope": { "source": "reddit", "query_family": "competitor complaints" },
  "evidence_rows": [
    {
      "source_url": "https://example.com/thread",
      "source_type": "reddit_post",
      "author_handle": "user123",
      "community_or_site": "r/legaltech",
      "published_at": "2026-03-20T12:00:00Z",
      "snippet": "The workflow is manual and hard to review.",
      "pain_cluster_id": "run_20260328_01:cluster_a",
      "engagement_signals": { "score": 41 },
      "retrieval_timestamp": "2026-03-28T13:00:00Z",
      "traceability_status": "verified"
    }
  ],
  "notes": "No strong Hacker News threads found."
}
```

### `OpportunitySnapshot`

Required fields:

- `opportunity_id`
- `run_id`
- `rank`
- `title`
- `affected_user`
- `job_to_be_done`
- `pain_statement`
- `score_total`
- `score_breakdown_json`
- `confidence`
- `confidence_reason`
- `pain_cluster_key`
- `supporting_evidence_json`
- `contradictions_json`
- `query_scope_json`

```json
{
  "opportunity_id": "opp_20260328_01",
  "run_id": "run_20260328_01",
  "rank": 1,
  "title": "Review-safe drafting workflow",
  "affected_user": "In-house IP counsel",
  "job_to_be_done": "Draft and review faster without adding risk",
  "pain_statement": "Manual stitching creates slow review loops.",
  "score_total": 83,
  "score_breakdown_json": { "recurrence": 21, "severity_and_urgency": 18 },
  "confidence": "High",
  "confidence_reason": "Repeated recent complaints with concrete workflow detail.",
  "pain_cluster_key": "run_20260328_01:cluster_a",
  "supporting_evidence_json": [{ "source_url": "https://example.com/thread" }],
  "contradictions_json": [{ "note": "Lower pain at low volume" }],
  "query_scope_json": { "sources": ["reddit"], "date_range_days": 365 }
}
```

### `PrdRecord`

Required fields:

- `prd_id`
- `run_id`
- `opportunity_id`
- `title`
- `status`
- `target_user`
- `goal`
- `structured_prd_json`
- `markdown_snapshot`
- `source_evidence_json`

```json
{
  "prd_id": "prd_20260328_01",
  "run_id": "run_20260328_01",
  "opportunity_id": "opp_20260328_01",
  "title": "Review-safe drafting assistant",
  "status": "draft",
  "target_user": "In-house IP counsel",
  "goal": "Reduce manual drafting and review loops.",
  "structured_prd_json": { "problem": "Drafting is slow and brittle." },
  "markdown_snapshot": "# Lightweight PRD: Review-safe drafting assistant",
  "source_evidence_json": [{ "source_url": "https://example.com/thread" }]
}
```

## Command Interface

All commands accept JSON via stdin or `--input-file <path>`.

Success envelope:

```json
{ "ok": true, "command": "name", "result": {} }
```

Failure envelope:

```json
{ "ok": false, "error": "message" }
```

Preferred discovery flow:

1. collect evidence
2. `save-evidence-batch`
3. cluster and rank
4. `save-opportunity-batch`

Preferred commands:

- `save-evidence-batch`
- `save-opportunity-batch`
- `get-opportunity`
- `save-prd`
- `get-prd`
- `list-runs`

Compatibility/manual recovery commands:

- `save-evidence`
- `save-opportunity`

### `save-evidence`

Input: `EvidenceRow`

### `save-evidence-batch`

Input:

```json
{
  "run_id": "run_20260328_01",
  "evidence_rows": [{ "source_url": "https://example.com/thread", "source_type": "reddit_comment" }]
}
```

Result fields:

- `run_id`
- `saved_count`

### `save-opportunity`

Input: `OpportunitySnapshot`

### `save-opportunity-batch`

Input:

```json
{
  "run_id": "run_20260328_01",
  "opportunities": [{ "opportunity_id": "opp_20260328_01", "rank": 1 }]
}
```

Result fields:

- `run_id`
- `saved_count`

### `get-opportunity`

Input:

- `{"opportunity_id":"opp_20260328_01"}`
- `{"run_id":"run_20260328_01","rank":1}`

### `save-prd`

Input: `PrdRecord`

### `get-prd`

Input:

- `{"prd_id":"prd_20260328_01"}`
- `{"opportunity_id":"opp_20260328_01"}`
- `{"run_id":"run_20260328_01"}`
- `{"latest":true}`

### `list-runs`

Input: optional empty object

## PRD Rules

- Generate a PRD only from a persisted `OpportunitySnapshot`.
- Carry forward evidence and constraints instead of inventing scope.
- Optimize for a coding agent.
- Prefer a thin vertical slice.
- Include non-goals, constraints, and acceptance criteria.

## Output Rules

- Prefer repeated, concrete complaints over clever one-offs.
- Separate category pain from vendor-specific complaints.
- Preserve contradictions when evidence conflicts.
- Down-rank hype, memes, and unsupported wishlists.
- Keep evidence traceable through `source_url` and `pain_cluster_id`.


path: agents/openai.yaml
content: interface:
  display_name: "Painpoint to MVP"


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)