examples/compile/ov-compile-skills/ov-session-report/SKILL.md
Read only the session data supplied by the user. Clean and normalize it, apply time windows, compute metrics, classify topics, review risks, compare with the previous period, and produce one self-contained Markdown file. The default timezone is Asia/Shanghai.
sessions_root. Do not fetch or merge other communities, message streams, directories, or online chat data..md file. Temporary scripts and intermediate files are allowed during analysis, but the report must remain understandable without them.Default output filename:
OpenViking_Community_QA_Weekly_Report_YYYY-MM-DD_to_YYYY-MM-DD.md
sessions_root: Required. Recursively read .jsonl session files from this directory.current_start / current_end: Optional boundaries for the current reporting window.previous_start / previous_end: Optional boundaries for the previous comparison window.previous_report: Optional Markdown report created by this skill. Use it to preserve published definitions and historical figures.output_path: Optional. If omitted, write to reports/qa-weekly-YYYYMMDD-YYYYMMDD/ in the current workspace.session_scope: Optional subdirectory, filename pattern, or explicit session set supplied by the user.history: Optional verified report titles and links for downstream document rendering. Pass these through without querying for them.Infer missing values from the directory structure, timestamps, and previous report when possible. Ask the user only when the target session set or reporting boundary cannot be resolved and different choices would materially change the result.
The Markdown report must use this order:
OpenViking Community Q&A Weekly Report: YYYY-MM-DD to YYYY-MM-DDExecutive SummaryReleases This WeekWeekly Topic RankingOpen High-Priority IssuesWeek-over-Week ComparisonWeekly ActivityTrends and RecommendationsMethodology and Data NotesPrevious ReportsAppendix: Structured Report DataReleases This Week may only summarize versions for which the sessions contain explicit evidence such as "released," "deployed," or "available to install." Statements such as "planned," "expected," or "will be included in the next release" are not completed releases. When there is no qualifying evidence, write: "No formal release could be confirmed from this week's sessions." Do not browse for confirmation.
Use half-open intervals:
Current: [current_start, current_end)
Previous: [previous_start, previous_end)
Choose the cutoff in this order:
current_end + 7 days.Asia/Shanghai.Comparison requirements:
previous_report. If neither is available, keep the comparison section and mark the previous period as unavailable. Never replace unknown values with zero.List candidate files first:
rg --files "$SESSION_ROOT" -g '*.jsonl'
Do not assume every file in the directory belongs to the target dataset:
session_scope, honor it but still verify that it contains data.Do not select the target dataset solely because it contains the largest number of files.
Use a real JSON parser on every line:
bad_lines. Keep filenames and line numbers for local auditing, but do not expose them in the final report._type=metadata, while still using their session identifiers and contextual metadata.timestamp, created_at, create_time, time. Support numeric timestamps in both seconds and milliseconds.Asia/Shanghai. Treat timezone-naive values as Asia/Shanghai and disclose that assumption.Normalize roles as follows:
user, human, and equivalent roles count as human messages.assistant, bot, and equivalent roles count as assistant messages.system, tool, metadata, and equivalent records remain separate and never contribute to human activity or topic initiators.unknown_role_messages and manually sample them before making a decision. Never classify an unknown role as human by default.One unique session is one discussion unit.
Deduplicate in this order:
session_key + timestamp + sender_key + normalized_text.An effective discussion contains a real technical question, failure, design comparison, usage feedback, or actionable answer. Pure sharing, status updates, greetings, bot tests, and content-free link forwarding may remain in total message counts but do not count as effective discussions.
Display names may come only from the session files:
[Name]: or [Name]: prefix repeatedly associated with the same internal identity.Name unavailable. Never guess a name or display an internal identity key.When one identity has multiple display-name candidates, review frequency, temporal continuity, and context. Keep identities separate when the evidence is insufficient.
Masking rules:
*.张三 -> 张*.*, for example 秦浩杰 -> 秦*杰.darren -> d****n and Lin101 -> L****1.胡江涛 -> 胡**.Q\*n; keep the raw value as Q*n in structured JSON.The final Markdown and structured JSON must not contain complete human names, email addresses, phone numbers, raw identity keys, Authorization values, API keys, root keys, tenant keys, or long credential-like strings.
Use the same code and definitions for both windows. At minimum, compute:
discussion_units: Unique sessions.effective_discussions: Effective discussion units.participants: Unique human identities in the window.human_messages: Human messages.assistant_messages: Assistant replies.system_messages: System and tool messages.unknown_role_messages: Messages whose roles remain unresolved.total_messages: All counted messages.The following invariant must hold:
human_messages + assistant_messages + system_messages + unknown_role_messages = total_messages
Participant counts, Top 10 users, and keywords must use human messages only. Assistant messages may help interpret the Q&A context or determine whether a question received a response, but they must not inflate human rankings.
Use stable topic buckets across weeks. Recommended baseline buckets:
Classification rules:
Memory, add_resource, VLM, and MCP.Manually sample sessions behind popular topics and keywords to catch misclassification, log noise, or frequency inflation caused by assistant repetition.
Include only high-priority issues that remain unresolved at the data cutoff, with a default maximum of four. Here, unresolved means that the available sessions contain no complete chain of an explicit fix, usable release, existing-instance recovery, and user-side verification before the cutoff.
A candidate must satisfy at least one of these conditions:
Exclude:
Every issue must contain these six fields:
Priority / CategoryBackgroundUser ImpactEvidenceCurrent AssessmentCommunity FeedbackImmediately follow each issue with its own Human Feedback Excerpt. Include human messages only, omit assistant replies, and omit internal links:
> **08-31 21:16 | O\*\*\*r**
> Session Commit has failed repeatedly...
>
> **08-31 21:19 | 秦\*杰**
> The current fix direction is still incorrect and needs another revision.
Every excerpt must come from sessions associated with that issue and preserve the timestamp, masked name, and essential meaning. Long logs may be shortened and unrelated text may be omitted, but never invent dialogue or mix messages from another issue.
Extract only explicit completed-release signals from the sessions: version, confirmation time, major changes, fixes, upgrade warnings, and related discussion.
Compare the scale first, then the content:
Percentage-change formula:
(current - previous) / previous * 100
When the previous value is zero and the current value is positive, display New. When both are zero, display 0.0%. When the previous value is unknown, display Not comparable; never substitute zero for unknown.
Focus shifts must come from human review of high-frequency session digests from both windows. Do not infer them from keyword deltas alone.
Include:
Render the peak-time series as Mermaid while retaining the full 24-hour table:
xychart-beta
title "Hourly Human Message Distribution (CST)"
x-axis ["00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23"]
y-axis "Messages" 0 --> MAX
line [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
Replace MAX and all 24 data points. If Mermaid cannot render, the full data table must still preserve the result.
Produce three to six actionable recommendations. Each recommendation must include:
Prioritize unresolved P1 issues, repeated high-frequency questions, post-release compatibility warnings, activity changes, and data-quality gaps. Avoid empty language such as "continue monitoring" or "optimize further" without a named action.
This skill does not create online documents, but its Markdown output must directly support the current weekly-report layout.
The structured data must be sufficient to generate:
The structured data must be sufficient to generate:
No important number may exist only in narrative prose while being absent from the structured data.
qa-report.v3 Data ContractThe Markdown must end with one qa-report.v3 JSON object. The prose is for reading; the JSON is the authoritative source for downstream document and whiteboard rendering.
Rules:
NaN, ellipses, or placeholders.<!-- QA_REPORT_DATA_START --> and <!-- QA_REPORT_DATA_END -->, and make it the final fenced JSON block in the document.+08:00, YYYY-MM-DD dates, and integer hours from 0 through 23.null for unknown values; never substitute zero.daily must cover every date slice in the current window. hourly must contain exactly 24 entries, including zeros for inactive hours.Required fields:
{
"schema_version": "qa-report.v3",
"report": {
"title": "OpenViking Community Q&A Weekly Report: YYYY-MM-DD to YYYY-MM-DD",
"generated_at": "YYYY-MM-DDTHH:mm:ss+08:00",
"timezone": "Asia/Shanghai",
"window": {
"current": {"start": "YYYY-MM-DDTHH:mm:ss+08:00", "end": "YYYY-MM-DDTHH:mm:ss+08:00"},
"previous": {"start": "YYYY-MM-DDTHH:mm:ss+08:00", "end": "YYYY-MM-DDTHH:mm:ss+08:00"}
},
"coverage": {
"sessions_root": "user-supplied local path",
"discovered_files": 0,
"included_files": 0,
"excluded_files": 0,
"included_sessions": 0,
"earliest_message": null,
"latest_message": null,
"bad_lines": 0,
"missing_timestamps": 0,
"complete": true,
"notes": []
}
},
"summary": {
"headline": "One overall conclusion",
"top_topic_names": [],
"peak_hour": 0,
"peak_hour_messages": 0,
"peak_day": "YYYY-MM-DD",
"peak_day_messages": 0,
"open_p1_count": 0,
"release_versions": []
},
"presentation": {
"section_order": [
"Executive Summary",
"Releases This Week",
"Weekly Topic Ranking",
"Open High-Priority Issues",
"Week-over-Week Comparison",
"Weekly Activity",
"Trends and Recommendations",
"Methodology and Data Notes",
"Previous Reports"
],
"summary_dashboard": {
"kpi_metric_order": ["discussion_units", "effective_discussions", "participants", "total_messages"],
"topic_limit": 6,
"anomaly_limit": 4,
"hourly_series": "human_messages",
"top_user_limit": 10,
"keyword_limit": 20,
"compact_keyword_limit": 12
},
"comparison_dashboard": {
"metric_order": ["discussion_units", "participants", "total_messages"],
"show_topic_change": true,
"show_focus_shift": true
}
},
"metrics": {
"current": {
"discussion_units": 0,
"effective_discussions": 0,
"participants": 0,
"human_messages": 0,
"assistant_messages": 0,
"system_messages": 0,
"unknown_role_messages": 0,
"total_messages": 0
},
"previous": {
"discussion_units": 0,
"effective_discussions": 0,
"participants": 0,
"human_messages": 0,
"assistant_messages": 0,
"system_messages": 0,
"unknown_role_messages": 0,
"total_messages": 0
}
},
"topics": [
{
"rank": 1,
"name": "Topic name",
"current": {"discussion_units": 0, "participants": 0, "human_messages": 0},
"previous": {"discussion_units": 0, "participants": 0, "human_messages": 0},
"delta_pct": 0.0,
"keywords": [],
"insight": ""
}
],
"keywords": [
{"rank": 1, "keyword": "Memory", "current_count": 0, "previous_count": 0, "delta_pct": 0.0}
],
"activity": {
"daily": [
{"date": "YYYY-MM-DD", "human_messages": 0, "assistant_messages": 0, "total_messages": 0}
],
"hourly": [
{"hour": 0, "human_messages": 0}
],
"peaks": {
"top_hours": [{"hour": 0, "messages": 0}],
"top_day": {"date": "YYYY-MM-DD", "messages": 0}
},
"top_users": [
{"rank": 1, "display_name": "Q*n", "messages": 0, "discussion_units": 0, "keywords": []}
],
"response_metrics": {
"available": false,
"answered_discussions": null,
"answer_rate_pct": null,
"median_latency_seconds": null,
"p90_latency_seconds": null,
"method": ""
}
},
"releases": [
{
"version": "vX.Y.Z",
"published_at": "YYYY-MM-DDTHH:mm:ss+08:00",
"type": "main|hotfix|component",
"url": null,
"highlights": [],
"reliability_fixes": [],
"breaking_changes": [],
"related_topics": [],
"evidence": []
}
],
"anomalies": [
{
"rank": 1,
"title": "Issue title",
"short_label": "Short label for the dashboard risk card",
"priority": "P1",
"category": "Category",
"background": "",
"user_impact": "",
"evidence": "",
"current_assessment": "",
"community_feedback": "",
"unresolved_at_cutoff": true,
"chat": [
{"time": "MM-DD HH:mm", "speaker": "Q*n", "message": "Masked human message"}
]
}
],
"comparison": {
"available": true,
"metric_conclusion": "",
"topic_conclusion": "",
"focus_shifts": [
{"previous_focus": "", "current_focus": "", "interpretation": ""}
],
"overall_conclusion": ""
},
"recommendations": [
{"rank": 1, "observation": "", "impact": "", "action": ""}
],
"history": [
{"title": "Previous report title", "url_or_path": "verified link or relative path"}
]
}
When previous-period data is unavailable, set metrics.previous to null; set each topic and keyword previous/delta_pct value to null; set comparison.available=false; and explain the reason in the prose. Never preserve a fabricated all-zero previous period.
---
report_schema: qa-report.v3
report_type: openviking_qa_weekly
timezone: Asia/Shanghai
current_start: YYYY-MM-DDTHH:mm:ss+08:00
current_end: YYYY-MM-DDTHH:mm:ss+08:00
previous_start: YYYY-MM-DDTHH:mm:ss+08:00
previous_end: YYYY-MM-DDTHH:mm:ss+08:00
generated_at: YYYY-MM-DDTHH:mm:ss+08:00
---
# OpenViking Community Q&A Weekly Report: YYYY-MM-DD to YYYY-MM-DD
## Executive Summary
- Reporting window: ...
- Weekly volume: ...
- Participation: ...
- Leading topics: ...
- Peak period: ...
- Main conclusion: ...
## Releases This Week
| Version | Time | Type | Highlights | Upgrade Notes | Session Evidence |
| --- | --- | --- | --- | --- | --- |
## Weekly Topic Ranking
| Rank | Topic | Discussion Units | Participants | Human Messages | Keywords | Insight |
| ---: | --- | ---: | ---: | ---: | --- | --- |
### Top 20 Keywords
| Rank | Keyword | Current | Previous | Change |
| ---: | --- | ---: | ---: | ---: |
## Open High-Priority Issues
### 1. Issue Title
- **Priority / Category:** P1 / ...
- **Background:** ...
- **User Impact:** ...
- **Evidence:** ...
- **Current Assessment:** ...
- **Community Feedback:** ...
#### Human Feedback Excerpt
> **Time | Masked Name**
> Message...
## Week-over-Week Comparison
### Core Metrics
| Metric | Previous | Current | Absolute Change | Percentage Change |
| --- | ---: | ---: | ---: | ---: |
### Topic Heat Changes
| Topic | Previous | Current | Change | Interpretation |
| --- | ---: | ---: | ---: | --- |
### Focus and Discussion Shifts
| Previous Focus | Current Focus | Interpretation |
| --- | --- | --- |
## Weekly Activity
### Activity Overview
### Daily Distribution
### Peak-Time Line Chart
### 24-Hour Data
### Top 10 Active Community Members
## Trends and Recommendations
1. ...
## Methodology and Data Notes
- Data directory, discovered files, and included scope.
- Both time windows, timezone, and actual data coverage.
- Deduplication, roles, discussion units, effective discussions, and multi-label topic definitions.
- Malformed lines, missing timestamps, unknown roles, and coverage gaps.
- Display-name resolution and masking rules.
## Previous Reports
- [OpenViking Community Q&A Weekly Report: YYYY-MM-DD to YYYY-MM-DD](verified link or path)
## Appendix: Structured Report Data
<!-- QA_REPORT_DATA_START -->
```json
{complete qa-report.v3 object}
```
<!-- QA_REPORT_DATA_END -->
sessions_root and identify the target session set from directories, filename prefixes, and metadata.previous_report when raw previous-window data is absent.qa-report.v3 object first, and render both Markdown prose and Mermaid from that same object to prevent numeric drift..md file that remains understandable without temporary scripts or caches.report_schema: qa-report.v3, and the final JSON parses successfully.activity.hourly is ordered from 0 through 23 with exactly 24 entries; daily covers every current-window date slice.