reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
---
name: research
description: Conduct preliminary research on a topic and generate research outline. For academic research, benchmark research, technology selection, etc.
---
# Research Skill - Preliminary Research
## Trigger
`/research <topic>`
## Workflow
### Step 1: Generate Initial Framework from Model Knowledge
Based on topic, use model's existing knowledge to generate:
- Main research objects/items list in this domain
- Suggested research field framework
Output {step1_output}, use request_user_input to confirm:
- Need to add/remove items?
- Does field framework meet requirements?
### Step 2: Web Search Supplement
Use request_user_input to ask for time range (e.g., last 6 months, since 2024, unlimited).
**Parameter Retrieval**:
- `{topic}`: User input research topic
- `{YYYY-MM-DD}`: Current date
- `{step1_output}`: Complete output from Step 1
- `{time_range}`: User specified time range
**Hard Constraint**: The following prompt must be strictly reproduced, only replacing variables in {xxx}, do not modify structure or wording.
Launch 1 web-search-agent (background), **Prompt Template**:
```python
prompt = f"""## Task
Research topic: {topic}
Current date: {YYYY-MM-DD}
Based on the following initial framework, supplement latest items and recommended research fields.
## Existing Framework
{step1_output}
## Goals
1. Verify if existing items are missing important objects
2. Supplement items based on missing objects
3. Continue searching for {topic} related items within {time_range} and supplement
4. Supplement new fields
## Output Requirements
Return structured results directly (do not write files):
### Supplementary Items
- item_name: Brief explanation (why it should be added)
...
### Recommended Supplementary Fields
- field_name: Field description (why this dimension is needed)
...
### Sources
- [Source1](url1)
- [Source2](url2)
"""
```
**One-shot Example** (assuming researching AI Coding History):
```
## Task
Research topic: AI Coding History
Current date: 2025-12-30
Based on the following initial framework, supplement latest items and recommended research fields.
## Existing Framework
### Items List
1. GitHub Copilot: Developed by Microsoft/GitHub, first mainstream AI coding assistant
2. Cursor: AI-first IDE, based on VSCode
...
### Field Framework
- Basic Info: name, release_date, company
- Technical Features: underlying_model, context_window
...
## Goals
1. Verify if existing items are missing important objects
2. Supplement items based on missing objects
3. Continue searching for AI Coding History related items within since 2024 and supplement
4. Supplement new fields
## Output Requirements
Return structured results directly (do not write files):
### Supplementary Items
- item_name: Brief explanation (why it should be added)
...
### Recommended Supplementary Fields
- field_name: Field description (why this dimension is needed)
...
### Sources
- [Source1](url1)
- [Source2](url2)
```
### Step 3: Ask User for Existing Fields
Use request_user_input to ask if user has existing field definition file, if so read and merge.
### Step 4: Generate Outline (Separate Files)
Merge {step1_output}, {step2_output} and user's existing fields, generate two files:
**outline.yaml** (items + config):
- topic: Research topic
- items: Research objects list
- execution:
- batch_size: Number of parallel agents (confirm with request_user_input)
- items_per_agent: Items per agent (confirm with request_user_input)
- output_dir: Results output directory (default: ./results)
**fields.yaml** (field definitions):
- Field categories and definitions
- Each field's name, description, detail_level
- detail_level hierarchy: brief -> moderate -> detailed
- uncertain: Uncertain fields list (reserved field, auto-filled in deep phase)
### Step 5: Output and Confirm
- Create directory: `./{topic_slug}/`
- Save: `outline.yaml` and `fields.yaml`
- Show to user for confirmation
## Output Path
```
{current_working_directory}/{topic_slug}/
├── outline.yaml # items list + execution config
└── fields.yaml # field definitions
```
## Follow-up Commands
- `/research-add-items` - Supplement items
- `/research-add-fields` - Supplement fields
- `/research-deep` - Start deep research

View File

@@ -0,0 +1,198 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import sys
from collections import defaultdict
from pathlib import Path
import yaml
CATEGORY_MAPPING = {
"basic_info": ["basic_info", "Basic Info"],
"technical_features": ["technical_features", "technical_characteristics", "Technical Features"],
"performance_metrics": ["performance_metrics", "performance", "Performance Metrics"],
"milestone_significance": ["milestone_significance", "milestones", "Milestone Significance"],
"business_info": ["business_info", "commercial_info", "Business Info"],
"competition_ecosystem": ["competition_ecosystem", "competition", "Competition Ecosystem"],
"history": ["history", "History"],
"market_positioning": ["market_positioning", "market", "Market Positioning"],
}
_SKIP_KEYS = {"_source_file", "uncertain"}
def load_fields_yaml(fields_path):
"""Parse fields.yaml in the single schema the research skills emit:
fields:
<category>:
- {name: ..., description: ..., detail_level: ...}
...
uncertain: []
This is the ONLY accepted shape. A fields.yaml that does not match fails
loudly instead of silently passing with zero fields.
Required semantics (so the validator can never pass vacuously / "lie"):
- if ANY field carries an explicit `required:` key -> opt-in, preserve it
- else (detail_level-style, no markers) -> ALL fields required, because the
script's stated purpose is COMPLETE field coverage.
"""
with fields_path.open(encoding="utf-8") as f:
data = yaml.safe_load(f) or {}
defs = [] # (name, category, required_or_None)
fn = data.get("fields")
if not isinstance(fn, dict):
print(f"[ERROR] fields.yaml must use the `fields: {{<category>: [{{name, ...}}]}}` shape; got {type(fn).__name__ if fn is not None else 'None'}.")
sys.exit(1)
for cname, flist in fn.items():
if cname in _SKIP_KEYS:
continue
if not isinstance(flist, list):
print(f"[ERROR] category `{cname}` must map to a list of field dicts; got {type(flist).__name__}.")
sys.exit(1)
for field in flist:
if isinstance(field, dict) and "name" in field:
defs.append((str(field["name"]), str(cname), field.get("required", None)))
else:
print(f"[ERROR] field entry under `{cname}` must be a dict with a `name` key; got {field!r}.")
sys.exit(1)
if not defs:
print("[ERROR] fields.yaml parsed zero fields. Ensure at least one category with field dicts.")
sys.exit(1)
all_fields = {n for n, _, _ in defs}
if any(r is not None for _, _, r in defs):
required_fields = {n for n, _, r in defs if r}
else:
required_fields = set(all_fields)
field_categories = {n: c for n, c, _ in defs}
return all_fields, required_fields, field_categories
def extract_json_fields(data, category_mapping=None):
category_mapping = CATEGORY_MAPPING if category_mapping is None else category_mapping
nested_keys = {k for keys in category_mapping.values() for k in keys}
fields = set()
stack = [(data, True)]
while stack:
obj, is_category_level = stack.pop()
if isinstance(obj, dict):
for k, v in obj.items():
if k in _SKIP_KEYS:
continue
if is_category_level and k in nested_keys:
if isinstance(v, dict):
stack.append((v, True))
continue
fields.add(k)
elif isinstance(obj, list):
stack.extend((item, is_category_level) for item in obj if isinstance(item, dict))
return fields
def validate_json(json_path, all_fields, required_fields, field_categories):
with json_path.open(encoding="utf-8") as f:
data = json.load(f)
json_fields = extract_json_fields(data)
covered = all_fields & json_fields
missing = all_fields - json_fields
extra = json_fields - all_fields
missing_required = missing & required_fields
missing_by_category = defaultdict(list)
for field in missing:
missing_by_category[field_categories.get(field, "Unknown")].append(field)
return {
"file": json_path.name,
"total_defined": len(all_fields),
"covered": len(covered),
"missing": len(missing),
"extra": len(extra),
"coverage_rate": len(covered) / len(all_fields) * 100 if all_fields else 100,
"missing_required": sorted(missing_required),
"missing_optional": sorted(missing - required_fields),
"missing_by_category": {k: sorted(v) for k, v in missing_by_category.items()},
"extra_fields": sorted(extra),
"valid": len(missing_required) == 0,
}
def print_result(result, verbose=True):
status = "PASS" if result["valid"] else "FAIL"
line = "=" * 60
print(f"\n{line}")
print(f"[{status}] {result['file']}")
print(line)
print(f"Coverage: {result['coverage_rate']:.1f}% ({result['covered']}/{result['total_defined']})")
if result["missing_required"]:
print(f"\n[ERROR] Missing required fields ({len(result['missing_required'])}):")
print("\n".join(f" - {f}" for f in result["missing_required"]))
if verbose and result["missing_optional"]:
missing_required = set(result["missing_required"])
print(f"\n[WARN] Missing optional fields ({len(result['missing_optional'])}):")
for cat in sorted(result["missing_by_category"]):
optional = [f for f in result["missing_by_category"][cat] if f not in missing_required]
if optional:
print(f" [{cat}]: {', '.join(optional)}")
if verbose and result["extra_fields"]:
extra = result["extra_fields"]
print(f"\n[INFO] Extra fields ({len(extra)}):")
print(f" {', '.join(extra[:10])}")
if len(extra) > 10:
print(f" ... and {len(extra) - 10} more")
def main():
import argparse
parser = argparse.ArgumentParser(description="Validate whether JSON files cover all fields defined in fields.yaml")
parser.add_argument("--fields", "-f", type=str, help="Path to fields.yaml", default="fields.yaml")
parser.add_argument("--json", "-j", type=str, nargs="*", help="JSON file paths to validate")
parser.add_argument("--dir", "-d", type=str, help="Directory containing JSON files", default="results")
parser.add_argument("--quiet", "-q", action="store_true", help="Show summary only")
args = parser.parse_args()
fields_path = Path(args.fields)
if not fields_path.exists():
for p in (Path.cwd() / "fields.yaml", Path.cwd().parent / "fields.yaml"):
if p.exists():
fields_path = p
break
if not fields_path.exists():
print(f"[ERROR] fields.yaml not found: {fields_path}")
sys.exit(1)
print(f"Field definition file: {fields_path}")
all_fields, required_fields, field_categories = load_fields_yaml(fields_path)
print(f"Total fields: {len(all_fields)} (required: {len(required_fields)}, optional: {len(all_fields) - len(required_fields)})")
json_files = (
[Path(p) for p in args.json]
if args.json
else sorted(Path(args.dir).glob("*.json")) if Path(args.dir).exists() else []
)
if not json_files:
print("[WARN] No JSON files found")
sys.exit(0)
results = []
for json_path in json_files:
if not json_path.exists():
print(f"[WARN] File not found: {json_path}")
continue
result = validate_json(json_path, all_fields, required_fields, field_categories)
results.append(result)
print_result(result, verbose=not args.quiet)
line = "=" * 60
print(f"\n{line}")
print("Summary")
print(line)
passed = sum(1 for r in results if r["valid"])
avg_coverage = sum(r["coverage_rate"] for r in results) / len(results) if results else 0
print(f"Validation passed: {passed}/{len(results)}")
print(f"Average coverage: {avg_coverage:.1f}%")
if passed < len(results):
sys.exit(1)
if __name__ == "__main__":
main()