fix: Fix 2 critical CLI issues blocking production (Kimi QA)

**Critical Issues Fixed:**

Issue #1: CLI Commands Were BROKEN ⚠️ CRITICAL
- Problem: 4 CLI commands existed but failed at runtime with ImportError
- Root Cause: Modules had example_usage() instead of main() functions
- Impact: Users couldn't use quality, stream, update, multilang features

**Fixed Files:**
- src/skill_seekers/cli/quality_metrics.py
  - Renamed example_usage() → main()
  - Added argparse with --report, --output flags
  - Proper exit codes and error handling

- src/skill_seekers/cli/streaming_ingest.py
  - Renamed example_usage() → main()
  - Added argparse with --chunk-size, --batch-size, --checkpoint flags
  - Supports both file and directory inputs

- src/skill_seekers/cli/incremental_updater.py
  - Renamed example_usage() → main()
  - Added argparse with --check-changes, --generate-package, --apply-update flags
  - Proper error handling and exit codes

- src/skill_seekers/cli/multilang_support.py
  - Renamed example_usage() → main()
  - Added argparse with --detect, --report, --export flags
  - Loads skill documents from directory

Issue #2: Haystack Missing from Package Choices ⚠️ CRITICAL
- Problem: Haystack adaptor worked but couldn't be used via CLI
- Root Cause: package_skill.py missing "haystack" in --target choices
- Impact: Users got "invalid choice" error when packaging for Haystack

**Fixed:**
- src/skill_seekers/cli/package_skill.py:188
  - Added "haystack" to --target choices list
  - Now matches main.py choices (all 11 platforms)

**Verification:**
 All 4 CLI commands now work:
   $ skill-seekers quality --help
   $ skill-seekers stream --help
   $ skill-seekers update --help
   $ skill-seekers multilang --help

 Haystack now available:
   $ skill-seekers package output/skill --target haystack

 All 164 adaptor tests still passing
 No regressions detected

**Credits:**
- Issues identified by: Kimi QA Review
- Fixes implemented by: Claude Sonnet 4.5

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
yusyus
2026-02-07 23:12:40 +03:00
parent 6f9584ba67
commit a332507b1d
5 changed files with 151 additions and 56 deletions

View File

@@ -379,14 +379,23 @@ class StreamingIngester:
return "\n".join(lines)
def example_usage():
"""Example usage of streaming ingestion."""
def main():
"""CLI entry point for streaming ingestion."""
import argparse
parser = argparse.ArgumentParser(description="Stream and chunk skill documents")
parser.add_argument("input", help="Input file or directory path")
parser.add_argument("--chunk-size", type=int, default=4000, help="Chunk size in characters")
parser.add_argument("--chunk-overlap", type=int, default=200, help="Chunk overlap in characters")
parser.add_argument("--batch-size", type=int, default=100, help="Batch size for processing")
parser.add_argument("--checkpoint", help="Checkpoint file path")
args = parser.parse_args()
# Initialize ingester
ingester = StreamingIngester(
chunk_size=4000,
chunk_overlap=200,
batch_size=100
chunk_size=args.chunk_size,
chunk_overlap=args.chunk_overlap,
batch_size=args.batch_size
)
# Progress callback
@@ -395,26 +404,36 @@ def example_usage():
print(f"Progress: {progress.progress_percent:.1f}% - "
f"{progress.processed_chunks}/{progress.total_chunks} chunks")
# Stream skill directory
skill_dir = Path("output/react")
chunks = ingester.stream_skill_directory(skill_dir, callback=on_progress)
# Stream input
input_path = Path(args.input)
if not input_path.exists():
print(f"❌ Error: Path not found: {input_path}")
return 1
if input_path.is_dir():
chunks = ingester.stream_skill_directory(input_path, callback=on_progress)
else:
chunks = ingester.stream_file(input_path, callback=on_progress)
# Process in batches
all_chunks = []
for batch in ingester.batch_iterator(chunks, batch_size=50):
for batch in ingester.batch_iterator(chunks, batch_size=args.batch_size):
print(f"\nProcessing batch of {len(batch)} chunks...")
all_chunks.extend(batch)
# Save checkpoint every batch
ingester.save_checkpoint(
Path("output/.checkpoints/react.json"),
{"processed_batches": len(all_chunks) // 50}
)
# Save checkpoint if specified
if args.checkpoint:
ingester.save_checkpoint(
Path(args.checkpoint),
{"processed_batches": len(all_chunks) // args.batch_size}
)
# Final progress
print("\n" + ingester.format_progress())
print(f"\n✅ Processed {len(all_chunks)} total chunks")
return 0
if __name__ == "__main__":
example_usage()
import sys
sys.exit(main())