Initial commit: moreminimore-service content pipeline
- 9 mm* skills (orchestrator, article, social, publish, analytics) - 6 dependency skills (content-writer, geo-optimizer, etc.) - 3 analytics scripts (GSC, Google Ads, Meta Ads) - Config template + setup guide - SOUL-MM.md persona extension - OrbitOS integration reference
This commit is contained in:
310
skills/mm-article-from-research/SKILL.md
Normal file
310
skills/mm-article-from-research/SKILL.md
Normal file
@@ -0,0 +1,310 @@
|
||||
---
|
||||
name: mm-article-from-research
|
||||
description: >
|
||||
Data Stage A: Convert a vault research note into an article brief.
|
||||
Scans 30_Research/ for resources not yet used for articles, lets user pick one,
|
||||
reads the content, summarizes key points, asks user which angles to focus on,
|
||||
then creates a brief.md for the content-writer-mm skill.
|
||||
Use when: "เขียนบทความจาก research", "article from research", "ใช้ research เขียนบทความ".
|
||||
---
|
||||
|
||||
# Article From Research
|
||||
|
||||
Converts existing vault research notes into structured article briefs.
|
||||
|
||||
## When This Must Trigger
|
||||
|
||||
- "เขียนบทความจาก research", "article from research"
|
||||
- "ใช้ research เขียนบทความ", "make article from research"
|
||||
- "เลือก research มาเขียน"
|
||||
- "ทั้งหมด", "ทุก research", "batch" (batch mode — see Step 1b)
|
||||
|
||||
## Process
|
||||
|
||||
### Step 1: Determine mode — Single or Batch
|
||||
|
||||
Ask the user if they want to work on ONE research or ALL at once:
|
||||
|
||||
```python
|
||||
# Detect batch intent
|
||||
batch_keywords = ['ทั้งหมด', 'ทุก', 'all', 'batch', 'ทุกไฟล์', '14', '13', '12',
|
||||
'ทุก research', '14 บทความ', 'ทั้งหมดเลย']
|
||||
user_msg = user_message.lower()
|
||||
is_batch = any(kw in user_msg for kw in batch_keywords)
|
||||
```
|
||||
|
||||
- **Single mode** (default): user picks one research → interactive focus questions
|
||||
- **Batch mode**: process ALL unused research at once → skip interactivity
|
||||
|
||||
Trigger batch immediately if user says "ทั้งหมด" or "ทุก research" or "ทุกไฟล์"
|
||||
|
||||
### Step 0: Determine client
|
||||
|
||||
Ask which client this article is for:
|
||||
|
||||
```
|
||||
บทความนี้สำหรับลูกค้าไหน?
|
||||
|
||||
1. [client-1] — [display_name]
|
||||
2. [client-2] — [display_name]
|
||||
```
|
||||
|
||||
If no clients configured, suggest running `mm-article-idea-extract` to add one first.
|
||||
|
||||
### Step 1: Scan 30_Research/<client-id>/ for available resources
|
||||
|
||||
```bash
|
||||
VAULT_PATH="$HOME/vault"
|
||||
```
|
||||
|
||||
Search for research notes in both client-specific and general folders that have
|
||||
NOT been marked as used for articles:
|
||||
|
||||
```python
|
||||
# Search 30_Research/<client-id>/ AND 30_Research/general/
|
||||
# Exclude Archive/ subfolders and notes with article_created: true
|
||||
import os, re
|
||||
|
||||
vault = os.path.expanduser("~/vault/30_Research")
|
||||
results = []
|
||||
search_dirs = [
|
||||
os.path.join(vault, client_id), # client-specific
|
||||
os.path.join(vault, "general"), # general research
|
||||
]
|
||||
|
||||
for search_dir in search_dirs:
|
||||
if not os.path.exists(search_dir):
|
||||
continue
|
||||
for root, dirs, files in os.walk(search_dir):
|
||||
# Skip Archive folders
|
||||
if 'Archive' in root.split(os.sep):
|
||||
continue
|
||||
for f in files:
|
||||
if not f.endswith('.md'):
|
||||
continue
|
||||
path = os.path.join(root, f)
|
||||
try:
|
||||
content = open(path).read()
|
||||
if 'article_created: true' in content[:500]:
|
||||
continue
|
||||
title_match = re.search(r'^#\s+(.+)$', content, re.MULTILINE)
|
||||
title = title_match.group(1) if title_match else f.replace('.md', '')
|
||||
type_match = re.search(r'^type:\s*(.+)$', content, re.MULTILINE)
|
||||
note_type = type_match.group(1).strip() if type_match else 'unknown'
|
||||
results.append({
|
||||
'path': path,
|
||||
'title': title,
|
||||
'type': note_type,
|
||||
'relative': os.path.relpath(path, os.path.expanduser("~/vault"))
|
||||
})
|
||||
except:
|
||||
continue
|
||||
```
|
||||
|
||||
Present results to user as a numbered list:
|
||||
|
||||
```
|
||||
พบ research notes ที่ยังไม่ได้ใช้เขียนบทความ:
|
||||
|
||||
1. [Title] — type: reference — 30_Research/Area/Topic/Topic.md
|
||||
2. [Title] — type: reference — 30_Research/Area/Topic2/Topic2.md
|
||||
...
|
||||
|
||||
เลือกหมายเลขที่ต้องการเขียนบทความ (หรือพิมพ์ชื่อหัวข้อเพื่อค้นหา):
|
||||
```
|
||||
|
||||
If no research notes found, suggest running `article-idea-extract` instead.
|
||||
|
||||
### Step 1b: Batch mode — Process ALL research at once
|
||||
|
||||
Skip interactive selection. Read ALL research notes from 30_Research/ that don't have `article_created: true`.
|
||||
|
||||
Classify into two buckets:
|
||||
|
||||
| Status | Action |
|
||||
|--------|--------|
|
||||
| `reference`, `candidate`, `draft` | Ready — create brief from existing content |
|
||||
| `seed` | **Research first** — search the web for current info, stats, examples, and sources. Compile into a supplementary data block for the brief |
|
||||
|
||||
For seed-status notes, search internet for:
|
||||
- Latest articles/tutorials on the topic
|
||||
- Official documentation or product pages
|
||||
- Statistics, benchmarks, or case studies
|
||||
- Competitor or comparison info
|
||||
|
||||
### Step 1c: Apply date convention (ALL modes)
|
||||
|
||||
**Article date = source research date.** Extract `date:` from research frontmatter:
|
||||
|
||||
```python
|
||||
date_m = re.search(r'^date:\s*(.+)$', content, re.MULTILINE)
|
||||
article_date = date_m.group(1).strip() if date_m else today
|
||||
```
|
||||
|
||||
Use this date for:
|
||||
- Article folder name: `~/vault/60_Articles/<article_date>-<slug>/`
|
||||
- Article frontmatter `date:` field
|
||||
- DO NOT use today's date unless the research has no date field at all
|
||||
|
||||
### Step 2: Read the selected research note (Single mode)
|
||||
|
||||
Read the full content of the selected research note using `read_file`.
|
||||
|
||||
Extract:
|
||||
- **Title** — from H1
|
||||
- **Key concepts** — from H2/H3 headings
|
||||
- **Main points** — from body content
|
||||
- **Related notes** — from wikilinks `[[...]]`
|
||||
- **Area** — from frontmatter `area:` field
|
||||
- **Tags** — from frontmatter `tags:` field
|
||||
|
||||
### Step 3: Summarize and ask for focus
|
||||
|
||||
Present a summary of the research:
|
||||
|
||||
```
|
||||
📄 Research: [Title]
|
||||
📂 Area: [Area]
|
||||
🏷️ Tags: [tags]
|
||||
|
||||
สรุปประเด็นหลัก:
|
||||
1. [Key point 1]
|
||||
2. [Key point 2]
|
||||
3. [Key point 3]
|
||||
...
|
||||
|
||||
บทความนี้ควรเน้นประเด็นไหนบ้าง?
|
||||
(เลือกหมายเลข หรือพิมพ์ประเด็นเพิ่มเติม)
|
||||
```
|
||||
|
||||
### Step 4: Iterate on details
|
||||
|
||||
After user selects focus areas, ask follow-up questions:
|
||||
|
||||
- มีมุมมองเฉพาะที่อยากเพิ่มไหม?
|
||||
- กลุ่มเป้าหมายของบทความคือใคร?
|
||||
- โทนบทความ: ทางการ / casual / technical?
|
||||
- ความยาวที่ต้องการ: สั้น (800 words) / กลาง (1500) / ยาว (2000+)?
|
||||
- ต้องการ SEO keyword ไหม? ถ้ามี คืออะไร?
|
||||
|
||||
### Step 5: Additional research (optional)
|
||||
|
||||
If the research note is thin or user wants more depth:
|
||||
|
||||
1. Search internet for current information on the topic
|
||||
2. Look for statistics, examples, case studies
|
||||
3. Find expert quotes or references
|
||||
4. Check what competitors have written (SERP analysis)
|
||||
|
||||
### Step 6: Create brief.md
|
||||
|
||||
Create the article brief at:
|
||||
|
||||
```
|
||||
~/vault/60_Articles/<client-id>/YYYY-MM-DD-<slug>/brief.md
|
||||
```
|
||||
|
||||
Where `<slug>` is derived from the topic (kebab-case, English).
|
||||
|
||||
```markdown
|
||||
---
|
||||
type: brief
|
||||
status: ready
|
||||
created: YYYY-MM-DD
|
||||
source_research: "[[Original Research Title]]"
|
||||
source_path: "30_Research/Area/Topic/Topic.md"
|
||||
---
|
||||
|
||||
# Article Brief: [Topic]
|
||||
|
||||
## Source
|
||||
- Research: [[Original Research Title]]
|
||||
- Path: 30_Research/Area/Topic/Topic.md
|
||||
|
||||
## Target
|
||||
- Audience: [who]
|
||||
- Tone: [formal/casual/technical]
|
||||
- Length: [target word count]
|
||||
- SEO Keyword: [if provided]
|
||||
|
||||
## Key Angles
|
||||
1. [Angle 1]
|
||||
2. [Angle 2]
|
||||
3. [Angle 3]
|
||||
|
||||
## Outline
|
||||
### H1: [Proposed title]
|
||||
### H2: [Section 1]
|
||||
- [Key point]
|
||||
### H2: [Section 2]
|
||||
- [Key point]
|
||||
### H2: [Section 3]
|
||||
- [Key point]
|
||||
|
||||
## Research Data
|
||||
[Key statistics, quotes, facts from the research note + internet research]
|
||||
|
||||
## Related Content
|
||||
- [[Related Note 1]]
|
||||
- [[Related Note 2]]
|
||||
|
||||
## Content Requirements
|
||||
- Featured image: [description]
|
||||
- Inline images: [list with descriptions]
|
||||
- FAQ section: [yes/no, topics if yes]
|
||||
- Schema markup: [Article/BlogPosting]
|
||||
```
|
||||
|
||||
### Step 7: Mark research note as used AND move to Archive
|
||||
|
||||
Update the original research note's frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
...existing frontmatter...
|
||||
article_created: true
|
||||
article_link: "[[YYYY-MM-DD-slug]]"
|
||||
---
|
||||
```
|
||||
|
||||
Use `patch` to add the two fields to the frontmatter.
|
||||
|
||||
Then move the research note to the client's Archive folder:
|
||||
|
||||
```bash
|
||||
# Determine source location
|
||||
SOURCE_DIR=$(dirname "$RESEARCH_PATH")
|
||||
ARCHIVE_DIR="$SOURCE_DIR/Archive"
|
||||
|
||||
# Create Archive if it doesn't exist
|
||||
mkdir -p "$ARCHIVE_DIR"
|
||||
|
||||
# Move the file
|
||||
mv "$RESEARCH_PATH" "$ARCHIVE_DIR/$(basename $RESEARCH_PATH)"
|
||||
```
|
||||
|
||||
**Important**: Only move if the research is in a client-specific folder.
|
||||
If the research is in `30_Research/general/`, mark as used but DON'T move
|
||||
(general research can be reused for other clients).
|
||||
|
||||
### Step 8: Confirm
|
||||
|
||||
```
|
||||
✅ Brief created: ~/vault/60_Articles/<client-id>/YYYY-MM-DD-slug/brief.md
|
||||
✅ Research marked: article_created: true
|
||||
✅ Research archived: moved to 30_Research/<client-id>/Archive/
|
||||
|
||||
ถัดไป: โหลด mm-content-writer skill เพื่อเริ่มเขียนบทความ
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
- `~/vault/60_Articles/<client-id>/<date>-<slug>/brief.md` — Article brief ready for mm-content-writer
|
||||
- Updated frontmatter in `30_Research/<client-id>/` source note
|
||||
- Source note moved to `30_Research/<client-id>/Archive/` (if client-specific)
|
||||
|
||||
## Notes
|
||||
|
||||
- If user can't find what they want in 30_Research/, suggest `article-idea-extract` skill
|
||||
- The brief is the contract between Data Stage and Content Stage — be thorough
|
||||
- Always preserve the wikilink to the source research
|
||||
Reference in New Issue
Block a user