fix: address code review issues from Claude and GPT-5.2

- report/SKILL.md: add AskUserQuestion to allowed-tools
- validate_json.py: remove unused imports (List, Any)
- validate_json.py: sort output lists for deterministic order
- validate_json.py: limit recursion to category level only
- validate_json.py: add list-of-dict handling
- EN validate_json.py: remove Chinese from CATEGORY_MAPPING
- EN deep/SKILL.md: change output language from Chinese to English
- deep/SKILL.md: add slug handling for filenames
- report/SKILL.md: fix uncertain_fields -> uncertain naming
- README: add PyYAML dependency note

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jilinchen
2026-01-07 09:59:18 +08:00
co-authored by Claude Opus 4.5
parent 98ddfce42d
commit 779c447670
8 changed files with 93 additions and 55 deletions
+3 -3
View File
@@ -28,7 +28,7 @@ Find `*/outline.yaml` file in current working directory, read items list, execut
- `{item_related_info}`: item's complete yaml content (name + category + description etc.)
- `{output_dir}`: execution.output_dir from outline.yaml (default: ./results)
- `{fields_path}`: absolute path to {topic}/fields.yaml
- `{output_path}`: absolute path to {output_dir}/{item_name}.json
- `{output_path}`: absolute path to {output_dir}/{item_name_slug}.json (slugify item_name: replace spaces with _, remove special chars)
**Hard Constraint**: The following prompt must be strictly reproduced, only replacing variables in {xxx}, do not modify structure or wording.
@@ -44,7 +44,7 @@ Read {fields_path} to get all field definitions
1. Output JSON according to fields defined in fields.yaml
2. Mark uncertain field values with [uncertain]
3. Add uncertain array at the end of JSON, listing all uncertain field names
4. All field values must be in Chinese (research can be in English, but final JSON values in Chinese)
4. All field values must be in English
## Output Path
{output_path}
@@ -70,7 +70,7 @@ Read /home/weizhena/AIcoding/aicoding-history/fields.yaml to get all field defin
1. Output JSON according to fields defined in fields.yaml
2. Mark uncertain field values with [uncertain]
3. Add uncertain array at the end of JSON, listing all uncertain field names
4. All field values must be in Chinese (research can be in English, but final JSON values in Chinese)
4. All field values must be in English
## Output Path
/home/weizhena/AIcoding/aicoding-history/results/GitHub_Copilot.json
+2 -2
View File
@@ -1,6 +1,6 @@
---
description: Summarize deep research results into markdown report, cover all fields, skip uncertain values.
allowed-tools: Read, Write, Glob, Bash
allowed-tools: Read, Write, Glob, Bash, AskUserQuestion
---
# Research Report - Summary Report
@@ -75,7 +75,7 @@ CATEGORY_MAPPING = {
Collect fields that exist in JSON but not defined in fields.yaml, put in "Other Info" category. Note to filter:
- Internal fields: `_source_file`, `uncertain`
- Nested structure top-level keys: `basic_info`, `technical_features` etc.
- `uncertain_fields` list: Display each field name on separate line, don't compress into one line
- `uncertain` array: Display each field name on separate line, don't compress into one line
**5. Uncertain Value Skipping**
Skip conditions:
+44 -28
View File
@@ -9,18 +9,18 @@ import json
import yaml
import sys
from pathlib import Path
from typing import Dict, List, Set, Any, Tuple
from typing import Dict, Set, Tuple
# Category mapping (supports both Chinese and English keys)
# Category mapping (English keys only)
CATEGORY_MAPPING = {
"basic_info": ["basic_info", "基本信息"],
"technical_features": ["technical_features", "technical_characteristics", "技术特性"],
"performance_metrics": ["performance_metrics", "performance", "性能指标"],
"milestone_significance": ["milestone_significance", "milestones", "里程碑意义"],
"business_info": ["business_info", "commercial_info", "商业信息"],
"competition_ecosystem": ["competition_ecosystem", "competition", "竞争与生态"],
"history": ["history", "历史沿革"],
"market_positioning": ["market_positioning", "market", "市场定位"],
"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"],
}
@@ -53,30 +53,41 @@ def load_fields_yaml(fields_path: Path) -> Tuple[Set[str], Set[str], Dict[str, s
def extract_json_fields(data: Dict, category_mapping: Dict = None) -> Set[str]:
"""
Extract all field names from JSON (supports both flat and nested structures)
Only extracts field names at category level, not nested dict/list values
"""
if category_mapping is None:
category_mapping = CATEGORY_MAPPING
# Get all possible nested keys
# Get all possible nested keys (category containers)
nested_keys = set()
for keys in category_mapping.values():
nested_keys.update(keys)
fields = set()
def collect_fields(d: Dict, is_top_level: bool = True):
for k, v in d.items():
# Skip internal fields
if k in {"_source_file", "uncertain"}:
continue
# If it's a top-level nested key, recurse into it
if is_top_level and k in nested_keys:
if isinstance(v, dict):
collect_fields(v, is_top_level=False)
else:
fields.add(k)
if isinstance(v, dict):
collect_fields(v, is_top_level=False)
def collect_fields(d, is_category_level: bool = True):
"""
Collect fields from dict or list structures
is_category_level: True if we're at top level or inside a category container
"""
if isinstance(d, dict):
for k, v in d.items():
# Skip internal fields
if k in {"_source_file", "uncertain"}:
continue
# If it's a category container key, recurse into it
if is_category_level and k in nested_keys:
if isinstance(v, dict):
collect_fields(v, is_category_level=True)
else:
# This is a field name, add it
fields.add(k)
# Don't recurse into field values (avoid counting nested keys as fields)
elif isinstance(d, list):
# Handle list-of-dict structures at category level
for item in d:
if isinstance(item, dict):
collect_fields(item, is_category_level=is_category_level)
collect_fields(data)
return fields
@@ -110,6 +121,10 @@ def validate_json(json_path: Path, all_fields: Set[str], required_fields: Set[st
missing_by_category[cat] = []
missing_by_category[cat].append(field)
# Sort lists within categories for deterministic output
for cat in missing_by_category:
missing_by_category[cat].sort()
return {
"file": json_path.name,
"total_defined": len(all_fields),
@@ -117,10 +132,10 @@ def validate_json(json_path: Path, all_fields: Set[str], required_fields: Set[st
"missing": len(missing),
"extra": len(extra),
"coverage_rate": len(covered) / len(all_fields) * 100 if all_fields else 100,
"missing_required": list(missing_required),
"missing_optional": list(missing_optional),
"missing_required": sorted(missing_required),
"missing_optional": sorted(missing_optional),
"missing_by_category": missing_by_category,
"extra_fields": list(extra),
"extra_fields": sorted(extra),
"valid": len(missing_required) == 0, # Valid if all required fields are covered
}
@@ -140,7 +155,8 @@ def print_result(result: Dict, verbose: bool = True):
if verbose and result["missing_optional"]:
print(f"\n[WARN] Missing optional fields ({len(result['missing_optional'])}):")
for cat, fields in result["missing_by_category"].items():
for cat in sorted(result["missing_by_category"].keys()):
fields = result["missing_by_category"][cat]
optional_fields = [f for f in fields if f not in result["missing_required"]]
if optional_fields:
print(f" [{cat}]: {', '.join(optional_fields)}")