Skip to main content
Glama
norton77930

Podcast Ingestion Core MCP Server

by norton77930

Podcast Ingestion Core

Spec034 Task #77 현재 터미널은 startup/plugin closed; credential_provider BLOCKED; overall BLOCKED 상태입니다. H2로 고정된 정확히 20개 파일의 공식 NousResearch/hermes-agent 번들은 정적/오프라인 전용입니다. startup 순서와 고정된 security-guidance 플러그인 identity chain은 닫혀 있고, credential/provider 구성 데이터 흐름, 전체 프로그램 폐쇄(whole-program closure), 동적/사용자/프로젝트/엔트리포인트 플러그인 경로, 런타임/시크릿 엣지, 실제 활성화는 여전히 차단되었거나 관찰되지 않았습니다. runtime_status=not_run; live_actions_authorized=false. 새로 만든 review 전용 bootstrap/final trust chain은 두 review가 모두 PASS된 후 Main을 위해 예약되어 있으며 아직 실행되지 않았습니다.

Podcast Ingestion Core는 범용 Podcast 수집 코어입니다. 현재 RSS episode listing, episode lookup, 오디오 다운로드, 로컬 faster-whisper 전사, transcript validation, 결정적 추출형 Markdown 요약, OpenAI 호환 LLM semantic summary pipeline, 결정적 mention 추출, SQLite metadata cache / search, 그리고 동일한 FastMCP 인스턴스를 공유하는 로컬 stdio 및 loopback Streamable HTTP sidecar가 완성되어 있습니다. Hermes direct MCP/config/Skills 연동은 작동 가능합니다. Spec 026의 C6 before/after metadata/content endpoint equality는 required reviewers와 유일한 live v2 run에서 PASS-current로 검증되었으며, snapshots 사이에 transient mutation이 없다고 주장하지 않습니다. C7은 여전히 안전한 runtime evidence가 부족합니다. v0.20.0 태그 v2026.8.3 hooks는 단지 후보일 뿐이며, 전체 상태는 Blocked로 유지됩니다. Web UI, 스케줄링, embedding 및 vector search는 아직 구현되지 않았습니다.

첫 번째 podcast profile은 Gooaye 股癌이지만, 코어 프로그램은 股癌을 하드코딩해서는 안 됩니다. 모든 podcast별 설정은 config/podcasts.yaml에 있습니다.

AI Agent Handoff / 시작 위치

이 README는 빠른 오리엔테이션(디렉터리 구조, CLI 예제, phase history)이며, 완전한 governance 소스는 아닙니다. 새로 투입되는 AI agent나 개발자는 여기서 시작하세요:

Related MCP server: MCP Podcast Scraper

프로젝트 목표

  • 동일한 core functions 세트로 여러 Podcast를 지원한다.

  • CLI scripts는 인자 파싱과 core functions 호출만 담당하게 한다.

  • 핵심 기능을 향후 MCP tools로 직접 감쌀 수 있게 한다.

  • 모든 출력 파일은 data/에 두고, 결정적(deterministic) 이름을 사용해 도구가 쉽게 찾을 수 있게 한다.

디렉터리 구조

config/
  podcasts.yaml
  industry_chain_mappings.yaml
  external_data_boundary.yaml
  external_market_data_fixtures.yaml
  gooaye_lens.yaml
  llm_profiles.yaml
data/
  audio/
  transcripts/
  summaries/
  mentions/
  reports/
  mappings/
  external/
  stock-lens/
  cache/
  corpus/
docs/
  agent-handoff.md
  ai-development-framework.md
  verification-matrix.md
  architecture-decision-records/
  architecture.md
  mvp-requirements.md
  roadmap.md
  mcp-readiness.md
  mcp-usage.md
  codex-mcp-setup.md
  claude-mcp-setup.md
  mcp-troubleshooting.md
scripts/
  list_episodes.py
  download_episode.py
  transcribe_episode.py
  validate_transcript.py
  summarize_episode.py
  run_corpus_episode_intake.py
  generate_corpus_index.py
  generate_corpus_remediation_plan.py
  run_corpus_audio_download.py
  run_corpus_remediation.py
  run_corpus_local_transcription.py
  run_corpus_episode_workflow.py
  run_corpus_semantic_remediation.py
  run_corpus_episode_completion_workflow.py
  run_corpus_latest_episode_deterministic_workflow.py
  run_latest_episode_verified_research_report_workflow.py
  run_episode_verified_research_report_workflow.py
  query_verified_research_report_catalog.py
  revalidate_verified_research_report_sources.py
  query_verified_research_report_coverage.py
  suggest_historical_verified_report_next_step.py
  list_verified_report_gap_backlog.py
  extract_mentions.py
  rebuild_cache.py
  search_transcripts.py
  search_mentions.py
  validate_mcp_setup.py
  validate_hermes_integration.py
  manage_hermes_integration.py
  run_mcp_server.py
  run_mcp_http_server.py
deploy/
  hermes/
src/
  podcast_ingest_core/
tests/

Core Functions

list_episodes(podcast_id, limit)
get_episode(podcast_id, episode_ref)
download_audio(podcast_id, episode_ref)
transcribe_episode(
    podcast_id,
    episode_ref,
    model=None,
    device="cpu",
    compute_type="int8",
    vad_filter=False,
    force=False,
    audio_path=None,
    progress_callback=None,
)
validate_transcript(podcast_id, episode_ref)
summarize_episode(
    podcast_id,
    episode_ref,
    force=False,
    max_quotes=10,
    window_seconds=300,
    allow_partial=False,
)
semantic_summarize_episode(
    podcast_id,
    episode_ref,
    provider="openai-compatible",
    model=None,
    base_url=None,
    api_key_env="OPENAI_API_KEY",
    force=False,
    chunk_seconds=600,
    max_segments_per_chunk=120,
    allow_partial=False,
)
extract_mentions(
    podcast_id,
    episode_ref,
    force=False,
    allow_partial=False,
    max_evidence_per_mention=5,
)
generate_episode_intelligence_report(
    podcast_id,
    episode_ref,
    force=False,
    allow_partial=False,
    window_seconds=300,
    max_evidence_per_section=5,
)
generate_industry_chain_mapping(
    podcast_id,
    episode_ref,
    force=False,
    allow_partial=False,
    max_candidates_per_node=5,
    max_evidence_per_candidate=5,
)
generate_external_data_boundary(
    podcast_id,
    episode_ref,
    force=False,
    allow_partial=False,
)
verify_external_data_boundary(
    podcast_id,
    episode_ref,
    confirm=False,
    force=False,
    allow_partial=False,
    provider="fixture",
    fixture_path=DEFAULT_EXTERNAL_MARKET_DATA_FIXTURE_PATH,
)
load_gooaye_lens_model(path=DEFAULT_GOOAYE_LENS_CONFIG_PATH)
generate_stock_lens_report(
    podcast_id,
    stock_query,
    force=False,
    allow_partial=False,
    max_evidence_items=10,
)
generate_stock_lens_synthesis_report(
    podcast_id,
    stock_query,
    confirm=False,
    force=False,
    allow_partial=False,
    api_cost_ack="",
    provider="openai-compatible",
    model=None,
    base_url=None,
    api_key_env="OPENAI_API_KEY",
    max_prompt_chars=24000,
)
run_research_workflow(
    podcast_id,
    episode_ref,
    stock_query=None,
    confirm=False,
    force=False,
    allow_partial=False,
    include_semantic_summary=False,
    include_stock_lens_synthesis=False,
    include_external_data_verification=False,
    api_cost_ack="",
    semantic_provider="openai-compatible",
    semantic_model=None,
    semantic_base_url=None,
    semantic_api_key_env="OPENAI_API_KEY",
    semantic_chunk_seconds=600,
    semantic_max_segments_per_chunk=120,
    synthesis_provider="openai-compatible",
    synthesis_model=None,
    synthesis_base_url=None,
    synthesis_api_key_env="OPENAI_API_KEY",
    synthesis_max_prompt_chars=24000,
    external_data_provider="fixture",
    external_fixture_path=DEFAULT_EXTERNAL_MARKET_DATA_FIXTURE_PATH,
    max_evidence_per_mention=5,
    report_window_seconds=300,
    max_evidence_per_section=5,
    max_candidates_per_node=5,
    max_evidence_per_candidate=5,
    max_stock_evidence_items=10,
)
initialize_cache(db_path=None)
index_episode(podcast_id, episode_ref, force=False, db_path=None)
rebuild_cache(podcast_id=None, force=False, db_path=None)
search_transcripts(query, podcast_id=None, limit=20, db_path=None, search_mode="auto", context_segments=0, case_sensitive=False)
search_mentions(query, podcast_id=None, mention_type=None, limit=20, db_path=None, case_sensitive=False)
run_corpus_episode_intake(podcast_id, episode_ref="latest", confirm=False)
generate_corpus_index(podcast_id)
generate_corpus_remediation_plan(podcast_id)
run_corpus_audio_download(podcast_id, episode_ref=None, confirm=False)
run_corpus_remediation(
    podcast_id,
    confirm=False,
    episode_ref=None,
    action_family=None,
    max_actions=None,
    force=False,
    allow_partial=False,
)
run_corpus_local_transcription(
    podcast_id,
    episode_ref=None,
    confirm=False,
    model=None,
    device="cpu",
    compute_type="int8",
    vad_filter=False,
)
run_corpus_episode_workflow(
    podcast_id,
    episode_ref="latest",
    stage="next",
    confirm=False,
    model=None,
    device="cpu",
    compute_type="int8",
    vad_filter=False,
    force=False,
    allow_partial=False,
    max_actions=None,
)
run_corpus_semantic_remediation(
    podcast_id,
    episode_ref,
    action="next",
    confirm=False,
    api_cost_ack="",
    provider="openai-compatible",
    model=None,
    base_url=None,
    api_key_env="OPENAI_API_KEY",
    chunk_seconds=600,
    max_segments_per_chunk=120,
    progress_callback=None,
)
run_corpus_episode_completion_workflow(
    podcast_id,
    episode_ref="latest",
    action="next",
    confirm=False,
    api_cost_ack="",
    transcription_model=None,
    transcription_device="cpu",
    transcription_compute_type="int8",
    transcription_vad_filter=False,
    semantic_provider="openai-compatible",
    semantic_model=None,
    semantic_base_url=None,
    semantic_api_key_env="OPENAI_API_KEY",
    semantic_chunk_seconds=600,
    semantic_max_segments_per_chunk=120,
    progress_callback=None,
)
run_corpus_latest_episode_deterministic_workflow(
    podcast_id,
    confirm=False,
    transcription_model=None,
    transcription_device="cpu",
    transcription_compute_type="int8",
    transcription_vad_filter=False,
)
run_latest_episode_verified_research_report_workflow(
    podcast_id,
    confirm=False,
    expected_episode_ref=None,
    api_cost_ack="",
    stock_query=None,
    include_fixture_verification=False,
)
run_episode_verified_research_report_workflow(
    podcast_id,
    episode_ref,
    confirm=False,
    stock_query=None,
    include_fixture_verification=False,
)

summarize_episode는 결정적/추출형 템플릿이며, 외부 LLM API를 호출하지 않고 의미론적 추론을 생성하지 않습니다. semantic_summarize_episode는 OpenAI 호환 API를 사용해 의미론적 요약을 생성하며, 중요한 판단에는 가능한 한 timestamp evidence를 첨부해야 하고 투자 조언을 구성하지 않습니다. extract_mentions는 결정적 규칙을 사용해 transcript segments에서 mentions를 추출하며, 각 mention은 timestamp evidence를 유지합니다. generate_episode_intelligence_report는 결정적 규칙을 사용해 기존 transcript와 mentions artifact에서 단일 에피소드 intelligence report를 생성하며, LLM을 호출하지 않고 외부 시장 데이터를 조회하지 않으며 주식 매핑이나 투자 조언을 생성하지 않습니다. generate_industry_chain_mapping은 로컬 결정적 mapping config를 사용해 기존 episode intelligence report에서 산업 체인 노드와 주식 후보를 생성하며, podcast의 명시적 evidence와 inferred / needs-verification 연구 단서를 명확히 구분합니다. generate_external_data_boundary는 로컬 boundary config를 사용해 기존 industry mapping에서 외부 데이터 검증 경계 scaffold를 생성하며, 외부 provider를 호출하지 않고 API key를 읽지 않으며 시장 현황 사실을 생성하지 않습니다. verify_external_data_boundary는 Phase 6M fixture provider scaffold입니다. dry-run 우선이며, confirm=True일 때만 로컬 fixture를 사용해 기존 external boundary를 업데이트하려 시도합니다. confirm guard가 있고, live market API가 없으며, MCP tool 변경이 없고, 투자 조언을 제공하지 않습니다. load_gooaye_lens_model은 로컬 Gooaye Lens 분석 프레임워크만 로드하고 검증하며, 주식 보고서를 생성하지 않고 LLM을 호출하지 않으며 외부 시장 데이터를 조회하지 않습니다. generate_stock_lens_report는 podcast 전체 로컬 artifacts와 Gooaye Lens를 사용해 주식/회사 연구 프레임워크를 생성하며, LLM을 호출하지 않고 외부 시장 데이터를 조회하지 않으며 매수/매도 조언, 목표가 또는 보장 수익을 제공하지 않습니다. generate_stock_lens_synthesis_report는 Phase 6J Stock Lens LLM Synthesis입니다. dry-run 우선이며, 기본 LLM input boundary는 6F stock lens JSON 전용이고, confirmed execution은 정확한 api_cost_ack를 제공해야 합니다. Phase 6V에서는 검토된 semantic summary context를 명시적으로 opt in할 수 있지만, 여전히 raw transcript를 읽지 않고 외부 시장 데이터를 조회하지 않으며 MCP tool 변경이 없고 매수/매도 조언을 제공하지 않습니다. run_research_workflow는 dry-run 우선의 로컬 research workflow runner로, mentions, episode intelligence, industry mapping, external boundary 및 선택적 stock lens를 연결합니다. Phase 6I는 research workflow 내부에서 선택적 semantic summary 실행을 지원하고, Phase 6K는 workflow opt-in synthesis를 지원하며, include_stock_lens_synthesis=True를 사용해 Phase 6J synthesis를 stock lens report 뒤에 연결할 수 있습니다. Phase 6N은 선택적 workflow fixture verification을 지원하며, include_external_data_verification=True를 사용해 external boundary 뒤에 로컬 fixture provider로 외부 검증 상태를 업데이트할 수 있습니다. 이 단계는 live market API가 없고, API key가 없고, MCP tool 변경이 없고, 자동 cache rebuild가 없으며, 투자 조언을 제공하지 않습니다. generate_corpus_index는 로컬 per-episode artifacts와 semantic review metadata만 스캔하여 결정적 corpus status JSON/Markdown을 작성합니다. RSS를 읽지 않고 SQLite cache를 읽지 않으며 LLM을 호출하지 않고 .env를 읽지 않으며 MCP tool을 추가하지 않고 raw transcript/evidence/semantic body를 출력하지 않습니다. generate_corpus_remediation_plan은 먼저 corpus index를 새로 고친 다음, 로컬 status metadata에서 full-ladder 격차, blockers, warnings 및 manual-only action 텍스트를 도출하여 결정적 remediation JSON/Markdown을 작성합니다. 다운로드, 전사, 요약, workflow, LLM, MCP 또는 cache rebuild를 실행하지 않으며 raw transcript/evidence/semantic body/prompt/raw LLM output을 출력하지 않습니다. run_corpus_audio_download는 먼저 remediation plan을 새로 고치고, dry-run은 audio missing이고 action ready인 후보 metadata만 반환하며 RSS를 읽지 않고 network/downloader를 호출하지 않으며 run report를 작성하지 않습니다. confirmed execution은 단일 에피소드를 지정해야 하며, 그때만 기존 download_audio()를 호출하고 최신 결정적 audio download run report를 작성합니다. 이 report에는 source URL, query string, secret 또는 traceback이 포함되지 않습니다. run_corpus_remediation은 먼저 remediation plan을 새로 고치고, dry-run은 selected/skipped/blocked/excluded metadata만 반환합니다. confirmed execution은 에피소드 또는 action family를 지정해야 하며, transcript-ready 결정적 families(extractive summary, mentions, episode intelligence, industry mapping, external boundary)만 실행하고 최신 결정적 run report를 작성합니다. run_corpus_local_transcription은 먼저 remediation plan을 새로 고치고, dry-run은 로컬 audio available이고 transcript missing인 후보 metadata만 반환합니다. confirmed execution은 단일 에피소드를 지정해야 하며, 명시적 로컬 audio_path만 사용해 기존 전사 코어를 호출하고 오디오를 다운로드하지 않으며 corrupt/partial transcript를 수리하지 않고 LLM/MCP/cache rebuild를 건드리지 않으며 최신 결정적 local transcription run report를 작성합니다. run_corpus_episode_workflow는 새 에피소드를 위한 dry-run-first 안전 진입점입니다. intake, audio download, local transcription, deterministic remediation의 다음 safe stage를 순서대로 판단합니다. dry-run은 workflow report를 작성하지 않고 stage를 실행하지 않으며, confirmed execution은 stage="next"를 사용해야 하고 단 하나의 stage만 실행하며 최신 결정적 workflow run report를 작성합니다. LLM 단계는 모두 confirm=True이고 정확한 api_cost_ack를 제공해야 외부 LLM을 호출합니다. 이 workflow는 여전히 외부 시장 데이터를 조회하지 않고, stock lens synthesis에 raw transcript를 사용하지 않으며, MCP tool 변경이 없고, cache를 자동으로 rebuild하지 않습니다. rebuild_cache는 기존 artifacts만 인덱싱하며, 자동으로 다운로드, 전사, 요약, mentions 추출, 연구 보고서 생성, mapping 생성, external boundary 생성 또는 stock lens report 생성을 하지 않습니다.

014 안정화의 정확한 계약: confirm=False는 strict zero-file이며, 구성된 podcast RSS feed와 로컬 artifacts를 읽는 것 외에는 어떤 파일도 생성, 수정 또는 삭제하지 않습니다. seeded selection은 메모리 내 index/plan snapshot 하나만 만들고 012/011/010을 순서대로 preview합니다. 이는 standalone 010/011/012 dry-run이 의도적으로 유지하는 fresh 008/009 persistence 동작과 다릅니다.

run_corpus_semantic_remediation(...)은 standalone, single-episode 015 semantic remediation Core입니다. 각 유효한 요청은 정확히 하나의 fresh in-memory 008/009 snapshot만 만들고, 먼저 명시적 canonical episode를 격리한 다음 semantic_summary, semantic_review, completed 또는 blocked/manual-only를 선택합니다. 010이나 014를 호출하지 않습니다. Dry-run은 strict zero-file이며 profile, .env, credential 또는 provider를 해석하지 않습니다. Confirmed semantic_summary는 명시적 action이어야 하고 before profile / .env / provider construction에서 정확한 api_cost_ack를 검증해야 합니다. confirmed semantic_review는 결정적이며 LLM 설정을 전혀 읽지 않습니다. 각 confirmed run은 최대 하나의 executor를 호출하고 confirmed-only 최신 JSON/Markdown report(no generated_at)를 작성하며 index, plan 또는 SQLite cache를 rebuild하지 않고 MCP tool을 추가하지 않습니다. 당시 registry는 정확히 12개 tools를 유지합니다.

run_corpus_episode_completion_workflow(...)은 016의 single-episode completion Core입니다. dry-run은 strict zero-file로 intake부터 semantic review까지의 다음 action을 판단합니다. 인간 확인 후에만 canonical episode에 대해 명시적으로 일치하는 action 하나를 실행하고 중지합니다. stdio MCP의 동일한 이름 run_corpus_episode_completion_workflow tool은 이 preview → human approval → one action 경계를 유지하며, .env를 읽지 않고 cache를 자동으로 rebuild하지 않으며 투자 조언을 제공하지 않습니다.

run_corpus_latest_episode_deterministic_workflow(...)은 017의 one-request latest-episode Core입니다. dry-run은 현재 latest만 해석하고 strict-zero-file 결정적 처리 계획을 반환합니다. SPEC 017은 구현되었습니다. 2026-07-17의 seeded/downloaded child-outcome 매핑 문제는 해결된 과거 blocker입니다. 기록된 metadata-only confirmed EP679 evidence는 outcome=ready_for_semantic_summary, ready_count=1, blocked_count=0, failed_count=0으로 끝납니다. 계약은 시작 시 하나의 canonical episode를 고정하고, intake, 다운로드, 로컬 전사 및 필요한 결정적 remediation을 처리하며, 실패/차단된 stage에서 fail closed하고 .env, provider, semantic summary/review, retry 또는 cache rebuild 없이 ready_for_semantic_summary에서 중지합니다.

run_latest_episode_verified_research_report_workflow(...)은 SPEC 018의 latest-episode verified research report Core입니다. 기본 confirm=False는 latest를 한 번만 해석하고 strict-zero-file preview를 반환하며 checkpoint, staging 또는 report bundle을 만들지 않습니다. confirmed request는 RSS, 환경/provider, writer 및 child stage 전에 preview에서 얻은 정확한 expected_episode_ref와 완전히 동일한 api_cost_ack를 제공해야 합니다. 고정된 017 결정적 ladder를 재사용하고, semantic summary/review의 정확한 passed gate 이후 고정된 안전한 research options로 결정적 JSON, Markdown 및 manifest bundle을 만듭니다. bundle은 content digest version, atomic directory publish, identical-content reuse 및 conflict fail-closed를 사용합니다. cache를 자동으로 rebuild하지 않고 live market API를 조회하지 않으며 투자 조언을 구성하지 않습니다.

run_episode_verified_research_report_workflow(...)은 SPEC 019의 explicit-episode verified research report Core입니다. 명시적 episode_ref(과거 에피소드 가능, latest/next 거부)를 요구하며, preview는 로컬 readiness만 확인하고 파일을 전혀 쓰지 않습니다. confirm은 lineage와 review가 통과된 경우에만 018과 동등한 digest bundle을 assemble/publish하며, api_cost_ack가 필요 없고 LLM/RSS/download를 호출하지 않으며 015–017을 연결하지 않습니다. 누락된 항목이 있으면 blocked를 반환하고 missing/stale roles를 나열합니다.

SPEC 020은 list_verified_research_reports(...), search_verified_research_reports(...)inspect_verified_research_report(...)의 오프라인 읽기 전용 manifest-first catalog seams를 제공합니다. 안전한 manifest 파생 metadata를 나열, 검색하거나 정확한 bundle의 로컬 self-consistency를 검사합니다. body search를 하지 않고 raw manifest나 absolute paths를 반환하지 않으며 내보내지 않고 DB/FTS/vector/cache를 사용하지 않으며 network/LLM을 사용하지 않고 source latest/currentness를 주장하지 않습니다. Inspect는 항상 source_currentness_status=not_evaluated를 반환합니다.

SPEC 022는 list_verified_research_report_coverage(podcast_id, *, has_bundle=None, limit=50)을 제공합니다. 정확한 podcast로 로컬 inventory × verified-report bundle의 episode 중심 coverage join을 수행하며, 선택적으로 bundle이 없거나 이미 있는 에피소드만 나열할 수 있습니다. offline / zero-write / report body를 읽지 않으며 source revalidation이나 currentness 주장을 하지 않습니다.

validate_transcript는 전사본이 완전한지, 비어 있는지, 부분 완료인지, 누락되었는지 또는 손상되었는지 확인하는 데 사용할 수 있습니다.

run_corpus_episode_intake는 dry-run first RSS episode bootstrap runner입니다. dry-run은 latest 또는 단일 명시적 episode selector를 해석할 수 있지만 파일을 쓰지 않고 다운로드하지 않으며 전사하지 않고 LLM/MCP/cache를 건드리지 않습니다. confirmed execution은 안전한 seed metadata와 최신 결정적 intake report만 작성하여 008/009/012가 이어서 발견, 계획 및 오디오 다운로드를 할 수 있게 합니다.

출력 경로 규칙

모든 산출물은 data/에 있습니다.

  • 오디오: data/audio/{podcast_id}/{episode_ref}__{safe_title_slug}.{ext}

  • 트랜스크립트: data/transcripts/{podcast_id}/{episode_ref}__{safe_title_slug}.txt

  • 자막: data/transcripts/{podcast_id}/{episode_ref}__{safe_title_slug}.srt

  • 트랜스크립트 metadata: data/transcripts/{podcast_id}/{episode_ref}__{safe_title_slug}.json

  • 요약: data/summaries/{podcast_id}/{episode_ref}__{safe_title_slug}.md

  • 의미론적 요약: data/summaries/{podcast_id}/{episode_ref}__{safe_title_slug}.semantic.md

  • Mentions JSON: data/mentions/{podcast_id}/{episode_ref}__{safe_title_slug}.mentions.json

  • Mentions Markdown: data/mentions/{podcast_id}/{episode_ref}__{safe_title_slug}.mentions.md

  • Episode intelligence JSON: data/reports/{podcast_id}/{episode_ref}__{safe_title_slug}.intelligence.json

  • Episode intelligence Markdown: data/reports/{podcast_id}/{episode_ref}__{safe_title_slug}.intelligence.md

  • Industry mapping JSON: data/mappings/{podcast_id}/{episode_ref}__{safe_title_slug}.industry-map.json

  • Industry mapping Markdown: data/mappings/{podcast_id}/{episode_ref}__{safe_title_slug}.industry-map.md

  • External data boundary JSON: data/external/{podcast_id}/{episode_ref}__{safe_title_slug}.external-boundary.json

  • External data boundary Markdown: data/external/{podcast_id}/{episode_ref}__{safe_title_slug}.external-boundary.md

  • Stock lens JSON: data/stock-lens/{podcast_id}/{safe_stock_query}.stock-lens.json

  • Stock lens Markdown: data/stock-lens/{podcast_id}/{safe_stock_query}.stock-lens.md

  • Stock lens synthesis JSON: data/stock-lens/{podcast_id}/{safe_stock_query}.stock-lens-synthesis.json

  • Stock lens synthesis Markdown: data/stock-lens/{podcast_id}/{safe_stock_query}.stock-lens-synthesis.md

  • Corpus index JSON: data/corpus/{podcast_id}/corpus-index.json

  • Corpus index Markdown: data/corpus/{podcast_id}/corpus-index.md

  • Corpus episode seed JSON: data/corpus/{podcast_id}/episode-seeds/{episode_ref}.episode-seed.json

  • Corpus episode intake run JSON: data/corpus/{podcast_id}/corpus-episode-intake-run.json

  • Corpus episode intake run Markdown: data/corpus/{podcast_id}/corpus-episode-intake-run.md

  • Corpus remediation plan JSON: data/corpus/{podcast_id}/corpus-remediation-plan.json

  • Corpus remediation plan Markdown: data/corpus/{podcast_id}/corpus-remediation-plan.md

  • Corpus remediation run JSON: data/corpus/{podcast_id}/corpus-remediation-run.json

  • Corpus remediation run Markdown: data/corpus/{podcast_id}/corpus-remediation-run.md

  • Corpus local transcription run JSON: data/corpus/{podcast_id}/corpus-local-transcription-run.json

  • Corpus local transcription run Markdown: data/corpus/{podcast_id}/corpus-local-transcription-run.md

  • Corpus audio download run JSON: data/corpus/{podcast_id}/corpus-audio-download-run.json

  • Corpus audio download run Markdown: data/corpus/{podcast_id}/corpus-audio-download-run.md

  • Corpus episode workflow run JSON: data/corpus/{podcast_id}/corpus-episode-workflow-run.json

  • Corpus episode workflow run Markdown: data/corpus/{podcast_id}/corpus-episode-workflow-run.md

  • Corpus semantic remediation run JSON: data/corpus/{podcast_id}/corpus-semantic-remediation-run.json

  • Corpus semantic remediation run Markdown: data/corpus/{podcast_id}/corpus-semantic-remediation-run.md

  • Corpus episode completion workflow run JSON: data/corpus/{podcast_id}/corpus-episode-completion-workflow-run.json

  • Corpus episode completion workflow run Markdown: data/corpus/{podcast_id}/corpus-episode-completion-workflow-run.md

  • Corpus latest deterministic workflow run JSON: data/corpus/{podcast_id}/corpus-latest-episode-deterministic-workflow-run.json

  • Corpus latest deterministic workflow run Markdown: data/corpus/{podcast_id}/corpus-latest-episode-deterministic-workflow-run.md

  • Verified research checkpoint: data/corpus/{podcast_id}/verified-research/{episode_ref}.checkpoint.json

  • Verified research report bundle: data/research-reports/{podcast_id}/{episode_ref}/v1-{source_digest}/report.json, report.md, manifest.json

  • SQLite metadata cache: data/cache/podcast_ingest.sqlite3

  • Episode cache: data/cache/{podcast_id}/episodes.json

podcast_id는 소문자 slug여야 합니다. Episode ref는 RSS title과 podcast profile의 default_episode_prefix로 해석됩니다(예: EP672). 파일명 title slug는 Windows에서 허용되지 않는 문자, 제어 문자, emoji 및 고위험 기호를 제거합니다.

CLI 예시

podcast-level corpus status index 생성:

python scripts/generate_corpus_index.py --podcast gooaye

이 CLI는 로컬 per-episode artifacts만 읽고 data/corpus/{podcast_id}/corpus-index.json.md를 다시 씁니다. stdout은 출력 경로, episode count, warning count 및 artifact family counts를 포함하는 metadata-only JSON입니다. transcript 원문, evidence snippet, semantic summary body, prompt, raw LLM output, API key 또는 provider secret은 포함하지 않습니다.

podcast-level corpus remediation plan 생성:

python scripts/generate_corpus_remediation_plan.py --podcast gooaye

이 CLI는 먼저 corpus index를 새로 고친 다음 data/corpus/{podcast_id}/corpus-remediation-plan.json.md를 다시 씁니다. stdout은 출력 경로, episode count, warning count, action count, blocked/optional/gated action counts를 포함하는 metadata-only JSON입니다. remediation action을 실행하지 않으며, RSS/SQLite cache/.env를 읽지 않고, network/LLM/MCP를 호출하지 않으며, transcript/evidence/semantic body/prompt/raw LLM output 또는 secret을 출력하지 않습니다.

Preview 또는 confirmed 단일 에피소드 audio download 실행:

python scripts/run_corpus_audio_download.py --podcast gooaye
python scripts/run_corpus_audio_download.py --podcast gooaye --episode EP672 --confirm

이 CLI는 먼저 corpus remediation plan을 새로 고칩니다. 따라서 standalone dry-run도 fresh corpus index와 remediation plan을 영속화합니다. 기본 dry-run은 stdout에 metadata-only JSON만 반환하며, RSS를 읽지 않고, network/downloader를 호출하지 않으며, corpus-audio-download-run.json/.md를 쓰지 않고, audio를 쓰지 않습니다. --confirm은 단일 --episode와 함께 사용해야 하며, audio status가 missing이고 audio action이 ready인 경우에만 기존 download_audio()를 호출합니다. Confirmed run은 최신 data/corpus/{podcast_id}/corpus-audio-download-run.json.md를 씁니다. 내용에는 timestamp, source URL/query string/secret/traceback이 없으며 투자 조언을 제공하지 않습니다. audio를 쓰거나 재사용한 후에는 transcription, downstream remediation 및 cache rebuild가 여전히 수동으로 실행되어야 한다는 점만 안내합니다.

Preview 또는 confirmed deterministic corpus remediation 실행:

python scripts/run_corpus_remediation.py --podcast gooaye
python scripts/run_corpus_remediation.py --podcast gooaye --action-family mentions --confirm
python scripts/run_corpus_remediation.py --podcast gooaye --episode EP672 --confirm

이 CLI는 먼저 corpus remediation plan을 새로 고칩니다. 따라서 standalone dry-run도 fresh corpus index와 remediation plan을 영속화합니다. 기본 dry-run은 stdout에 metadata-only JSON만 반환하며, corpus-remediation-run.json/.md를 쓰지 않고 artifact generator를 실행하지 않습니다. --confirm--episode 또는 --action-family와 함께 사용해야 하며, 기존 deterministic core functions만 호출하고 scripts로 shell out하지 않습니다. v1은 download, transcribe, semantic summary/review, stock-lens, LLM, RSS/network, SQLite cache rebuild, .env 또는 MCP를 실행하지 않습니다. Confirmed run은 최신 data/corpus/{podcast_id}/corpus-remediation-run.json.md를 씁니다. 내용에는 timestamp, raw transcript/evidence/semantic body/prompt/raw LLM output/secret이 없으며 투자 조언을 제공하지 않습니다.

Preview 또는 confirmed 단일 에피소드 로컬 transcription 실행:

python scripts/run_corpus_local_transcription.py --podcast gooaye
python scripts/run_corpus_local_transcription.py --podcast gooaye --episode EP672 --confirm
python scripts/run_corpus_local_transcription.py --podcast gooaye --episode EP672 --confirm --model small --device cuda --compute-type float16

이 CLI는 먼저 corpus remediation plan을 새로 고칩니다. 따라서 standalone dry-run도 fresh corpus index와 remediation plan을 영속화합니다. 기본 dry-run은 stdout에 metadata-only JSON만 반환하며, corpus-local-transcription-run.json/.md를 쓰지 않고, transcript를 쓰지 않고, Whisper model을 로드하지 않고, audio 파일을 다운로드하지 않습니다. --confirm은 단일 --episode와 함께 사용해야 하며, 로컬 audio path가 존재하고 transcript status가 missing인 경우에만 기존 transcribe_episode()를 호출하고 audio_pathforce=False를 명시적으로 전달합니다. Confirmed run은 최신 data/corpus/{podcast_id}/corpus-local-transcription-run.json.md를 씁니다. 내용에는 timestamp, raw transcript/prompt/raw LLM output/secret/traceback이 없으며 투자 조언을 제공하지 않습니다. transcript를 쓴 후에는 cache가 stale일 수 있다는 점만 안내하고 cache를 자동으로 rebuild하지 않습니다.

Preview 또는 confirmed fresh episode workflow의 다음 safe stage 실행:

python scripts/run_corpus_episode_workflow.py --podcast gooaye --episode latest
python scripts/run_corpus_episode_workflow.py --podcast gooaye --episode latest --stage next --confirm
python scripts/run_corpus_episode_workflow.py --podcast gooaye --episode EP677 --stage next --confirm --model small --device cuda --compute-type float16

이 CLI의 014 dry-run은 strict zero-file입니다. 013은 configured RSS parsing selector를 읽을 수 있습니다. seed가 있으면 fresh in-memory corpus index/plan snapshot을 한 번만 만들고 동일한 snapshot으로 012/011/010을 preview합니다. seed, audio, transcript, index, plan, 010-014 reports, downstream artifacts 또는 .part를 생성, 수정 또는 삭제하지 않습니다. planned reads에는 안전한 로컬 dependency paths가 포함될 수 있으며, non-path 값은 두 개의 exact labels만 허용됩니다. Confirmed execution은 반드시 --stage next --confirm을 명시해야 하며, 매번 기존 public runner 하나만 dispatch합니다. 해당 runner는 원래 계약에 따라 index/plan을 새로 고치고 selected-stage artifacts를 쓸 수 있으며, 014는 결과를 기록한 후 중지하고 최신 workflow report를 씁니다. semantic/LLM/stock-lens/MCP/cache rebuild/batch 작업은 여전히 manual follow-up으로만 나열되며 자동으로 실행되지 않습니다.

Preview 또는 confirmed 단일 에피소드 semantic remediation 실행:

python scripts/run_corpus_semantic_remediation.py --podcast gooaye --episode EP700
python scripts/run_corpus_semantic_remediation.py --podcast gooaye --episode EP700 --action semantic_summary --confirm --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs."
python scripts/run_corpus_semantic_remediation.py --podcast gooaye --episode EP700 --action semantic_review --confirm

015는 latest를 허용하지 않습니다. dry-run action=next는 metadata만 반환하고 strict zero-file입니다. Confirmed summary의 exact api_cost_ack은 profile, .env, credential 및 provider construction보다 먼저 이루어져야 합니다. review는 acknowledgement가 필요 없으며 profile/.env를 resolve하거나 LLM을 호출하지 않습니다. Validated confirmed attempt는 corpus-semantic-remediation-run.json/.md를 씁니다. 내용에는 generated_at, transcript/semantic/prompt/raw response/base URL/secret/traceback이 없습니다. index, plan 및 cache는 stale일 수 있으므로 수동으로 새로 고쳐야 합니다.

Preview 또는 사용자의 명시적 확인 후 단일 에피소드 completion workflow 실행:

python scripts/run_corpus_episode_completion_workflow.py --podcast gooaye
python scripts/run_corpus_episode_completion_workflow.py --podcast gooaye --episode EP677 --action audio_download --confirm
python scripts/run_corpus_episode_completion_workflow.py --podcast gooaye --episode EP677 --action semantic_summary --confirm --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs."

016 dry-run은 strict zero-file입니다. seed가 있으면 메모리에 fresh 008/009 snapshot을 하나만 만들고 순서대로 intake, audio download, local transcription, deterministic remediation, semantic summary 또는 semantic review의 다음 safe action을 선택합니다. confirmed는 dry-run이 반환한 canonical episode와 동일한 explicit action을 사용해야 합니다. next, latest 또는 stale action은 거부되며, 매번 기존 runner 하나만 dispatch한 후 중지합니다. semantic summary의 exact ack은 profile/.env/provider 작업 전에 완료되어야 합니다. semantic review는 LLM 설정을 읽지 않습니다. 유효한 confirmed attempt만 data/corpus/{podcast_id}/corpus-episode-completion-workflow-run.json.md를 원자적으로 쓰며, index, plan 또는 SQLite cache를 자동으로 새로 고치지 않습니다.

Agent가 조작하는 경우 동일한 이름의 MCP tool run_corpus_episode_completion_workflow와 repository의 portable corpus-episode-completion Skill을 사용합니다. 먼저 preview하고, 위험을 설명하고, canonical action에 대한 인간의 명시적 동의를 기다린 다음, action 하나를 실행하고 중지합니다. MCP가 없으면 CLI, terminal, scheduler 또는 자동 재시도를 사용해서는 안 됩니다.

Preview 또는 controlled confirmed 최신 deterministic workflow 실행:

python scripts/run_corpus_latest_episode_deterministic_workflow.py --podcast gooaye
python scripts/run_corpus_latest_episode_deterministic_workflow.py --podcast gooaye --confirm

SPEC 017은 구현되었습니다. Agent가 "Gooaye 최신 에피소드 처리해줘"와 같은 명시적 요청을 받으면 corpus-latest-episode-processing Skill은 해당 explicit natural-language request를 한 번의 execution authorization으로 간주합니다. 한 번 acknowledge하고, confirm=true로 dedicated run_corpus_latest_episode_deterministic_workflow MCP tool을 한 번만 호출하고, metadata-only result를 한 번 보고한 후 중지합니다. MCP tool 자체는 여전히 기본적으로 confirm=false dry-run입니다. Skill은 preview하지 말고, second call도 하지 말며, CLI/terminal fallback, scheduling, batch, retry, cache rebuild 또는 semantic summary/review를 사용해서는 안 됩니다.

Preview 최신 verified research report workflow:

python scripts/run_latest_episode_verified_research_report_workflow.py --podcast gooaye

SPEC 018의 preview는 strict zero-write이며 canonical episode reference와 exact required acknowledgement를 반환합니다. 사용자가 해당 previewed episode에 명시적으로 동의한 경우에만 동일한 --expected-episode-ref와 exact --api-cost-ack으로 --confirm을 한 번 실행합니다. 확인은 RSS, environment/provider, writer 또는 child stage 이전에 이루어져야 합니다. workflow는 pinned deterministic ladder를 재사용하고 semantic review exact passed를 요구한 다음 고정된 안전한 options로 deterministic research를 완료합니다. 완료 후 source digest version의 report.json, report.mdmanifest.json을 원자적으로 게시하고, identical bundle reuse, conflict fail-closed를 적용합니다. retry, scheduler, live market API 또는 cache rebuild를 하지 않으며 투자 조언을 구성하지 않습니다.

offline read-only verified research report catalog 조회(SPEC 020):

python scripts/query_verified_research_report_catalog.py list --podcast-id gooaye --limit 50
python scripts/query_verified_research_report_catalog.py search "EP672" --podcast-id gooaye
python scripts/query_verified_research_report_catalog.py inspect gooaye EP672 <lowercase-64-hex-source-digest>

이 세 개의 subcommands는 canonical 로컬 data/research-reports manifest-first bundles만 읽습니다. list는 exact filters를 사용할 수 있고, search는 safe metadata만 검색하며, inspect는 하나의 exact bundle의 로컬 self-consistency만 검증합니다. report/transcript body를 검색하지 않고, raw manifest/absolute paths를 반환하지 않으며, export를 제공하지 않고, DB/FTS/vector/cache, RSS/HTTP/network, LLM, .env, download, transcription 또는 remediation을 사용하지 않습니다. latest selector를 허용하지 않으며 source latest/currentness claim을 하지 않습니다. inspectsource_currentness_status=not_evaluated로 고정합니다. 경계 약어: no raw manifest; no DB/FTS/vector/cache; no RSS/HTTP/LLM/.env/download/transcription/remediation; no latest selector.

episode-centric verified research report coverage 조회(SPEC 022):

python scripts/query_verified_research_report_coverage.py gooaye
python scripts/query_verified_research_report_coverage.py gooaye --has-bundle false --limit 20

로컬 inventory와 canonical bundles를 join합니다. report가 없는 에피소드 또는 이미 digest가 있는 에피소드를 찾습니다. offline / zero-write / report body를 읽지 않습니다. 021 revalidation을 다시 실행하지 않으며 source currentness를 주장하지 않습니다.

최신 에피소드 나열:

python scripts/list_episodes.py --podcast gooaye --limit 10
python scripts/list_episodes.py --podcast gooaye --episode latest

오디오 파일 다운로드:

python scripts/download_episode.py --podcast gooaye --episode latest

CPU transcription은 먼저 tiny 또는 base 모델로 흐름을 검증하는 것이 좋습니다:

python scripts/transcribe_episode.py --podcast gooaye --episode latest --model tiny --device cpu --compute-type int8

전체 길이 에피소드는 CPU에서 오래 걸릴 수 있습니다. faster-whisper, ffmpeg/PyAV 및 출력 흐름이 작동하는지만 먼저 확인하려면 짧은 오디오 파일로 smoke test를 할 수 있습니다:

python scripts/transcribe_episode.py --audio-path path\to\sample.mp3 --podcast gooaye --episode smoke-test --model tiny --device cpu --compute-type int8 --force

NVIDIA GPU가 있고 환경이 CUDA를 지원하면 시도할 수 있습니다:

python scripts/transcribe_episode.py --podcast gooaye --episode latest --model small --device cuda --compute-type float16

긴 오디오 파일 권장 흐름:

python scripts/transcribe_episode.py --podcast gooaye --episode latest --model tiny --device cpu --compute-type int8
python scripts/validate_transcript.py --podcast gooaye --episode latest
python scripts/summarize_episode.py --podcast gooaye --episode latest --force

CPU에서 50분 오디오 파일은 매우 느릴 수 있습니다. tiny / base는 흐름 검증에 적합하고, small / medium은 품질 향상에 사용할 수 있습니다. NVIDIA GPU가 있으면 --device cuda --compute-type float16을 시도할 수 있습니다. timeout 후 높은 CPU Python process가 남아 있으면 해당 process를 수동으로 중지한 후 다시 실행하세요.

deterministic Markdown 요약 생성:

python scripts/summarize_episode.py --podcast gooaye --episode smoke-test --mode extractive --force
python scripts/summarize_episode.py --podcast gooaye --episode EP672 --mode extractive --max-quotes 5 --window-seconds 300

요약은 기존 transcript만 읽으며 자동으로 다운로드하거나 transcribe하지 않습니다. 지정된 에피소드에 transcript가 없으면 CLI는 transcript missing을 보고합니다. transcript가 partial이면 summary는 기본적으로 거부합니다. 그래도 생성하려면 --allow-partial을 추가할 수 있습니다.

LLM semantic summary를 생성하려면 API key와 model이 필요합니다. 수동 테스트에는 로컬 .env를 권장합니다. 이 파일은 .gitignore에 의해 무시되며 commit할 수 없습니다:

API_KEY=your-api-key
MODEL=your-model
BASE_URL=https://api.openai.com/v1
python scripts/summarize_episode.py --podcast gooaye --episode EP672 --mode semantic --force --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs."

CLI로 설정을 직접 덮어쓸 수도 있습니다:

python scripts/summarize_episode.py --podcast gooaye --episode EP672 --mode semantic --model your-model --base-url https://api.openai.com/v1 --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs."

semantic 모드는 먼저 transcript validation을 실행하고, transcript를 기본 600초와 chunk당 120 segments 단위로 나누어 provider에 전송합니다. LLM 지향 CLI는 기본적으로 .env를 로드하며, --env-file path\to\.env로 다른 파일을 지정하거나 --no-env-file로 비활성화할 수 있습니다. .env와 PowerShell 세션에 동일한 이름의 변수가 있으면 PowerShell 세션이 우선합니다. MODEL / BASE_URL이 현재 권장되는 이름이며, 설정되지 않은 경우 기존의 OPENAI_MODEL / OPENAI_BASE_URL도 계속 읽어들여 호환됩니다. API key나 model이 없으면 CLI가 설정 오류를 명확히 보고합니다. extractive 모드에는 API key가 필요 없습니다. 의미 요약은 투자 조언을 구성하지 않으며, 모든 중요한 시장 관점, 기업, 인물, 이벤트는 가능한 한 timestamp evidence로 되돌아가야 합니다.

Phase 6U는 semantic summary smoke validation을 보강합니다. 이 경로는 confirmed execution에서 transcript text를 이 머신 외부로 전송하며, dry-run은 planned reads/writes, transcript 전송 위험, 비용 위험, 필수 확인 사항만 나열하고 LLM을 호출하지 않으며, artifact를 쓰지 않고, 대본 내용을 출력하지 않습니다. Confirmed semantic summary smoke와 직접 --mode semantic CLI 모두 정확한 api_cost_ack를 제공해야 합니다. CLI stdout은 raw transcript를 출력하지 않으며 secret 값을 표시하지 않습니다. 이 단계에서는 MCP tool 변경, 라이브 시장 API, 자동 캐시 재구축, 투자 조언이 없습니다.

Phase 6U.1은 semantic review guard 오탐지를 수정합니다. semantic summary review는 팟캐스트 콘텐츠에서 화자가 과거에 매수/보유했다는 transcript 파생 설명은 허용하지만, 직접적인 매수/매도/보유, 매수 권고, 목표가, 수익 보장은 계속 거부합니다. Confirmed semantic smoke에도 stderr 진행률이 추가되며, stdout은 계속 JSON을 유지하고, 진행률에 raw transcript, 프롬프트, API key, LLM 응답을 출력하지 않습니다. Phase 6V는 stock lens 합성에 선택적 검토 semantic 컨텍스트를 추가합니다. 기본 합성은 phase-6f-stock-lens-json-only로 유지되며 .semantic.md를 읽지 않습니다. --include-semantic-context로 명시적으로 활성화하면, 합성에는 최신 통과 검토 보고서가 있는 일치하는 에피소드 semantic 요약만 포함될 수 있으며, 입력 경계는 phase-6f-stock-lens-json-plus-reviewed-semantic-summary가 됩니다. 이 컨텍스트는 ## Chunk Summaries를 제외하고, raw transcript 텍스트를 읽지 않으며, .env를 읽지 않고, 라이브 시장 데이터를 가져오지 않으며, MCP tool 변경도 없습니다. 검토된 semantic summary 컨텍스트는 LLM 중간 artifact이지 팟캐스트 원본 증거나 외부 시장 사실이 아닙니다. Phase 6V.1은 결정적 검토 게이트를 경계/컨텍스트 일관성에 맞춥니다. JSON 전용 합성에는 semantic 컨텍스트가 없어야 하며, 검토된 semantic 합성에는 비어 있지 않고 검토를 통과한 semantic 컨텍스트가 포함되어야 합니다.

python scripts/run_research_llm_smoke.py --podcast gooaye --episode EP672 --stock 台積電 --llm-profile pro4500 --confirm --force --include-semantic-context --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs."

LLM provider profile은 config/llm_profiles.yaml에 저장할 수 있으며, provider, model, base URL, API key 환경 변수 이름만 저장하고 API key 값은 저장하지 않습니다. 작업 중인 pro4500 profile은 api_key_env=API_KEY를 사용하므로 .envAPI_KEY=...와 함께 사용할 수 있습니다. 커밋된 gb10 profile은 unavailable로 표시되어 있으며, 로드 시 실패하고 pro4500 사용을 안내합니다. YAML에 API key, token, secret을 쓰지 마십시오.

결정적 멘션 추출:

python scripts/extract_mentions.py --podcast gooaye --episode EP672 --force
python scripts/extract_mentions.py --podcast gooaye --episode EP672 --max-evidence-per-mention 3

Mention 추출은 LLM을 사용하지 않으며 완전한 의미 이해를 의미하지 않고, 결정적 규칙에 따라 transcript segments에서 회사, 티커, 산업, 매크로 주제, 암호화폐, 장소 등의 멘션을 스캔합니다. 각 멘션에는 timestamp evidence가 첨부되며 투자 조언을 구성하지 않습니다. Phase 3 캐시는 멘션을 SQLite로 가져와 기본적인 에피소드 간 쿼리를 제공할 수 있습니다. 향후 MCP 도구가 이러한 핵심 함수를 직접 래핑할 수 있습니다.

결정적 에피소드 인텔리전스 리포트 생성:

python scripts/generate_episode_intelligence_report.py --podcast gooaye --episode EP672 --force
python scripts/generate_episode_intelligence_report.py --podcast gooaye --episode EP672 --window-seconds 600 --max-evidence-per-section 3

에피소드 인텔리전스 리포트는 기존 transcript와 mentions artifact만 읽으며, 자동 다운로드, 전사, 요약, 멘션 추출, LLM 호출, 외부 시장 데이터 조회를 하지 않습니다. mentions artifact가 없어도 리포트는 생성되지만 source warning이 표시되고 mention 파생 섹션은 비어 있습니다. 부분 transcript는 기본적으로 거부되며, 초안을 생성하려면 --allow-partial을 추가해야 합니다.

결정적 산업 사슬/종목 후보 매핑 생성:

python scripts/generate_industry_chain_mapping.py --podcast gooaye --episode EP672 --force
python scripts/generate_industry_chain_mapping.py --podcast gooaye --episode EP672 --max-candidates-per-node 3 --max-evidence-per-candidate 2

산업 매핑은 기존 에피소드 인텔리전스 리포트와 config/industry_chain_mappings.yaml만 읽으며 LLM을 호출하거나 외부 시장 데이터를 조회하지 않습니다. podcast_explicit은 팟캐스트 증거에 명시적으로 언급되었음을 의미하고, inferred_from_industry는 로컬 매핑 설정에서 추론된 미검증 연구 단서일 뿐이며 기본적으로 needs_verification으로 표시되며, 주식 고밤(Gooaye)이 명시적으로 언급했음을 의미하지 않으며 투자 조언을 구성하지 않습니다.

외부 시장 데이터 경계 스캐폴드 생성:

python scripts/generate_external_data_boundary.py --podcast gooaye --episode EP672 --force
python scripts/generate_external_data_boundary.py --podcast gooaye --episode EP672 --allow-partial

외부 데이터 경계는 기존 산업 매핑과 config/external_data_boundary.yaml만 읽으며, 외부 시장 데이터 제공자를 호출하지 않고, API key를 읽지 않으며, 가격, 시가총액, 재무제표, 뉴스, 회사 현황 사실을 생성하지 않습니다. 각 후보에는 external_verification_status=not_requested, source_status=not_fetched, data_date=null이 표시되고 이후 검증이 필요한 외부 데이터 유형이 나열됩니다.

로컬 fixture provider로 외부 경계 검증:

python scripts/verify_external_data_boundary.py --podcast gooaye --episode EP672
python scripts/verify_external_data_boundary.py --podcast gooaye --episode EP672 --confirm --force
python scripts/verify_external_data_boundary.py --podcast gooaye --episode EP672 --confirm --fixture-path config/external_market_data_fixtures.yaml

Phase 6M은 fixture provider 스캐폴드만 제공합니다. 기본 dry-run은 artifacts를 쓰지 않습니다. --confirm은 confirm guard이며, 확인 후 로컬 config/external_market_data_fixtures.yaml 또는 지정된 fixture 경로만 읽고 company_name / ticker를 정확히 일치시켜 기존 .external-boundary.json/.md를 업데이트합니다. 이 단계에서는 라이브 시장 API가 없고, API key를 읽지 않으며, MCP 도구를 추가하지 않고, 리서치 워크플로우에 연결하지 않으며, no investment advice 외의 어떤 시장 조언도 제공하지 않습니다.

Gooaye Lens 모델 확인:

python scripts/inspect_gooaye_lens.py
python scripts/inspect_gooaye_lens.py --path config/gooaye_lens.yaml

Gooaye Lens 모델은 Phase 6F stock lens 리포트의 결정적 분석 프레임워크 소스로, 산업 사슬 위치, 수급 및 재고, 경기 사이클, 금리 및 밸류에이션 민감도, 자본 지출 및 생산 능력, 지정학 및 불확실성 등의 차원을 정의합니다. Phase 6E는 로컬 설정만 로드하고 검증하며, 주식 입력을 받지 않고, artifacts를 쓰지 않으며, LLM을 호출하지 않고, 외부 시장 데이터를 조회하지 않으며, 매매 조언, 목표가, 수익 보장을 생성하지 않습니다.

팟캐스트 전반의 결정적 stock lens 리포트 생성:

python scripts/generate_stock_lens_report.py --podcast gooaye --stock 台積電 --force
python scripts/generate_stock_lens_report.py --podcast gooaye --stock NVDA --max-evidence-items 5

Stock lens 리포트는 해당 팟캐스트의 기존 data/mappings/data/external/ artifacts를 스캔하여 후보의 company_nametickers를 보수적으로 비교합니다. podcast_explicit은 직접 팟캐스트 증거로 나열되고, inferred_from_industry는 검증 필요 연구 단서로만 나열되며 팟캐스트가 명시적으로 언급했음을 의미하지 않습니다. 직접 팟캐스트 증거가 없어도 리포트는 생성되며 no-direct-podcast-evidence로 명확히 표시됩니다. 이 단계에서는 LLM을 호출하지 않고, 외부 시장 데이터를 조회하지 않으며, API key를 읽지 않고, MCP 도구를 추가하지 않으며, 매매 조언, 목표가, 수익 보장을 제공하지 않습니다.

Phase 6J Stock Lens LLM 합성 생성:

python scripts/generate_stock_lens_synthesis_report.py --podcast gooaye --stock 台積電
python scripts/generate_stock_lens_synthesis_report.py --podcast gooaye --stock 台積電 --confirm --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs." --model your-model
python scripts/generate_stock_lens_synthesis_report.py --podcast gooaye --stock 台積電 --llm-profile pro4500 --confirm --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs."

Stock lens 합성은 기본적으로 dry-run이며 planned reads/writes, LLM API/비용 위험, 필수 확인 사항만 나열하고 API key를 읽지 않고, LLM을 호출하지 않으며, artifacts를 쓰지 않습니다. Confirmed execution은 6F stock lens JSON 전용의 간결한 증거, lens 차원, 외부 경계 상태, 경고만 LLM에 전달합니다. raw transcript, .semantic.md 입력, 외부 시장 데이터 조회, MCP 도구 변경, run_research_workflow 연결이 없습니다. LLM 출력에 buy/sell/hold, 목표가, 수익 보장 등의 투자 조언 문구가 포함되면 synthesis artifact 쓰기를 거부합니다.

Phase 6O LLM research smoke 실행:

python scripts/run_research_llm_smoke.py --podcast gooaye --episode EP672 --stock 台積電 --model your-model
python scripts/run_research_llm_smoke.py --podcast gooaye --episode EP672 --stock 台積電 --confirm --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs." --model your-model --force
python scripts/run_research_llm_smoke.py --podcast gooaye --episode EP672 --stock 台積電 --llm-profile pro4500 --confirm --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs." --force --debug-llm-output
python scripts/run_research_llm_smoke.py --podcast gooaye --episode EP672 --stock 台積電 --confirm --include-semantic-summary --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs." --model your-model --force

Phase 6O는 OpenAI 호환 smoke 및 Codex 수동 검토 하네스입니다. 실제 LLM 호출은 여전히 OpenAI 호환 /chat/completions를 사용합니다. 현재 직접적인 Codex-session 백엔드는 없으며 Codex는 수동 검토자가 artifacts, 프롬프트 경계, 품질을 검사하는 데만 사용됩니다. Smoke는 기본적으로 stock lens 합성을 실행하고 fixture 외부 검증을 활성화합니다. semantic summary는 transcript 텍스트를 전송하므로 명시적으로 --include-semantic-summary를 추가해야 합니다. 이 단계에서는 라이브 시장 데이터가 없고, MCP 도구를 추가하지 않으며, 투자 조언 경계를 변경하지 않고, no investment advice를 유지합니다. Phase 6Q는 LLM profile 구성을 추가하며, 수동 테스트는 --llm-profile pro4500으로 config/llm_profiles.yaml을 읽을 수 있습니다. CLI에서 명시적으로 전달한 --model, --base-url, --api-key-env는 profile을 덮어씁니다. YAML에는 API key, token, secret 값이 포함되어서는 안 됩니다. Phase 6R은 로컬 .env 로더를 추가하며, LLM 지향 CLI는 기본적으로 .envAPI_KEY, MODEL, BASE_URL을 읽고 JSON 메타데이터에 로드된 env var 이름만 표시하고 값을 표시하지 않습니다. 공급자 응답을 진단하려면 --debug-llm-output를 추가할 수 있으며, raw LLM 출력은 .gitignore에 의해 무시되는 evals/research-llm-smoke/raw/에만 기록되며 공식 artifact가 되지 않습니다. Phase 6T는 결정적 검토 리포트/품질 게이트를 추가합니다. Confirmed smoke 후 다음 명령으로 타임스탬프가 있는 검토 리포트를 생성할 수 있습니다. 기존 artifacts만 읽으며 LLM 호출, .env 읽기, 외부 시장 데이터가 없고 synthesis artifacts를 다시 쓰지 않습니다.

python scripts/review_research_llm_smoke.py --podcast gooaye --episode EP672 --stock 台積電

LLM smoke 문서 및 검토 템플릿:

Phase 6U semantic summary smoke 검증:

python scripts/run_semantic_summary_smoke.py --podcast gooaye --episode EP672 --llm-profile pro4500
python scripts/run_semantic_summary_smoke.py --podcast gooaye --episode EP672 --llm-profile pro4500 --confirm --force --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs."
python scripts/review_semantic_summary_smoke.py --podcast gooaye --episode EP672

로컬 결정적 리서치 워크플로우 dry-run 또는 실행:

python scripts/run_research_workflow.py --podcast gooaye --episode EP672
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --confirm
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --confirm --stock 台積電
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --include-semantic-summary
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --confirm --include-semantic-summary --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs." --semantic-model your-model
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --include-external-data-verification
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --confirm --include-external-data-verification --external-fixture-path config/external_market_data_fixtures.yaml
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --stock 台積電 --include-stock-lens-synthesis
python scripts/run_research_workflow.py --podcast gooaye --episode EP672 --confirm --stock 台積電 --include-stock-lens-synthesis --api-cost-ack "I understand this may call an external LLM API, send transcript text outside this machine, and incur costs." --synthesis-model your-model

리서치 워크플로우는 먼저 dry-run을 수행하여 planned reads/writes, 단계 순서, semantic LLM 외부 API 위험, 캐시 오래됨 위험, 확인 상태를 나열합니다. 기본적으로 extract_mentions, generate_episode_intelligence_report, generate_industry_chain_mapping, generate_external_data_boundary의 로컬 결정적 단계만 실행하며 --stock이 제공되면 stock lens 리포트를 생성합니다. Phase 6I는 --include-semantic-summary로 옵트인할 수 있고, Phase 6K는 --include-stock-lens-synthesis로 옵트인하여 stock lens 리포트 뒤에 stock lens 합성을 배치할 수 있습니다. Phase 6N은 --include-external-data-verification으로 옵트인하여 external boundary 뒤, stock lens 리포트 앞에 fixture 검증을 배치할 수 있습니다. 이 단계는 --external-data-provider fixture만 지원하며 로컬 fixture만 읽고 라이브 시장 API를 조회하지 않으며 API key를 읽지 않습니다. Dry-run은 semantic/synthesis/fixture 계획과 필수 확인 사항만 나열하며, confirmed execution에서 LLM 단계만 정확한 --api-cost-ack를 제공해야 합니다. Stock lens 합성에는 --stock이 필요하며 기본적으로 6F stock lens JSON만 사용합니다. Phase 6V는 --include-semantic-context / --include-semantic-context-in-synthesis로 검토된 semantic 컨텍스트를 옵트인할 수 있으며, 여전히 raw transcript를 읽지 않고 외부 시장 데이터를 조회하지 않습니다. 이 워크플로우는 캐시를 자동으로 재구축하지 않고, MCP 도구를 추가하지 않으며, 투자 조언을 제공하지 않습니다.

SQLite 메타데이터 캐시 재구축 및 검색:

python scripts/rebuild_cache.py --podcast gooaye --force
python scripts/search_transcripts.py --podcast gooaye --query 台積電 --limit 10 --search-mode auto
python scripts/search_transcripts.py --podcast gooaye --query 台積電 --limit 10 --search-mode like --context-segments 1
python scripts/search_mentions.py --podcast gooaye --query 台積電
python scripts/search_mentions.py --podcast gooaye --query 台積電 --type company

SQLite 캐시는 파생 데이터이므로 삭제 후 재구축할 수 있습니다. 원본 source of truth는 여전히 data/transcripts/, data/summaries/, data/mentions/입니다. Phase 3B는 선택적 SQLite FTS5를 지원합니다. 로컬 SQLite가 FTS5를 지원하지 않거나 쿼리가 중국어 정확한 부분 문자열인 경우 search_transcripts()는 LIKE 폴백을 사용합니다. 검색 결과에는 highlighted_text, 실제 search_mode가 포함되며 --context-segments로 히트 세그먼트 주변 컨텍스트를 가져올 수 있습니다. 이 단계에서는 여전히 embedding, vector search, LLM 검색을 수행하지 않습니다.

로컬 MCP 서버 시작:

python scripts/rebuild_cache.py --podcast gooaye --force
python scripts/search_transcripts.py --podcast gooaye --query 台積電 --limit 5 --search-mode auto
python scripts/run_mcp_server.py

MCP 서버는 공식 Python MCP SDK의 단일 FastMCP 인스턴스를 사용합니다. 로컬 Codex/Claude 클라이언트는 계속 stdio를 사용합니다. Spec 026 승인을 받은 Hermes sidecar는 동일한 레지스트리에서 127.0.0.1:8767/mcp에만 바인딩된 Streamable HTTP를 제공하며 레거시 SSE를 사용하지 않고 포트를 공개하지 않습니다. 읽기/쿼리 도구는 다음과 같습니다:

  • list_episodes

  • get_episode

  • validate_transcript

  • search_transcripts

  • search_mentions

  • rebuild_cache

  • query_verified_research_report_catalog(도구 17, 오프라인 읽기 전용 manifest 우선 목록/검색/검사)

  • revalidate_verified_research_report_sources(도구 18, 정확한 로케이터 오프라인 소스 재검증)

  • query_verified_research_report_coverage(도구 19, 에피소드 중심 오프라인 적용 범위 조인)

  • suggest_historical_verified_report_next_step(도구 20, 과거 다음 단계 제안)

  • list_verified_report_gap_backlog(도구 21, 인벤토리 갭 백로그)

  • generate_stock_lens_report(도구 22, 결정적 stock lens 리포트, 부작용, dry-run 우선)

  • ingest_x_video(도구 23, X 비디오 수집, 미리보기는 쓰기 없음이지만 공개 메타데이터를 읽음)

  • ingest_youtube_video(도구 24, YouTube 비디오 수집, 미리보기는 쓰기 없음이지만 공개 메타데이터를 읽음)

부작용 도구는 다음과 같습니다:

  • download_audio

  • transcribe_episode

  • summarize_episode_extractive

  • extract_mentions

  • semantic_summarize_episode

  • run_research_workflow

  • run_corpus_episode_completion_workflow

  • run_corpus_latest_episode_deterministic_workflow

  • run_latest_episode_verified_research_report_workflow

  • run_episode_verified_research_report_workflow

  • generate_stock_lens_report

  • ingest_x_video

  • ingest_youtube_video

로컬 검토 stdio 레지스트리에는 총 24개의 도구가 있습니다. 도구 24 ingest_youtube_video는 추가 전용입니다. 도구 123의 계약/순서는 변경되지 않습니다. 도구 23 ingest_x_video는 여전히 X 수집입니다. 미리보기는 쓰기 없음이지만 공개 메타데이터를 읽으며 코퍼스 러너의 제로 네트워크 dry-run이 아닙니다. 도구 22 generate_stock_lens_report는 여전히 추가 전용 dry-run 우선 stock lens입니다. 부작용, dry-run 우선의 결정적 stock lens 리포트이며 로컬 매핑/경계 artifacts만 읽고 라이브 시장 API, 네트워크, LLM이 없으며 투자 조언을 제공하지 않습니다. 도구 21 list_verified_report_gap_backlog는 추가 전용입니다. 도구 120의 계약/순서는 변경되지 않습니다. 인벤토리 갭 백로그 읽기 쿼리입니다. 도구 20은 여전히 과거 다음 단계 제안입니다. 도구 19는 여전히 에피소드 중심 적용 범위입니다. 도구 18은 여전히 정확한 로케이터 오프라인 소스 재검증입니다. 도구 17은 카탈로그 목록/검색/검사 계약을 유지합니다. 위의 부작용 도구는 기본적으로 confirm=false이며 dry-run 작업 계획만 반환하고 다운로드, 전사, 파일 쓰기를 하지 않습니다. 작업 계획을 확인한 후에만 confirm=true를 사용하십시오. run_corpus_episode_completion_workflow는 미리보기 → 사람 승인 → 명시적 작업 하나를 유지하고, run_corpus_latest_episode_deterministic_workflow는 최신 에피소드의 로컬 결정적 단계만 처리하고 semantic summary 전에 중지합니다. run_latest_episode_verified_research_report_workflow는 먼저 미리보기를 수행해야 하며, 사용자가 동일한 정식 expected_episode_ref와 정확한 api_cost_ack를 제공한 후 confirmed로 한 번만 호출해야 합니다. run_episode_verified_research_report_workflow는 명시적 episode_ref(과거 에피소드 가능)로 준비 미리보기를 수행하고, 확인 후 동일한 다이제스트 번들을 조립/게시만 하며 api_cost_ack가 필요 없고 LLM을 호출하지 않습니다. 모든 부작용 도구는 완료 후 SQLite 캐시를 자동으로 재구축하지 않으며 투자 조언을 제공하지 않습니다. 예:

Call transcribe_episode with confirm=false first to review the action plan.
Call transcribe_episode again with confirm=true only if you accept the runtime and resource cost.

MCP 응답은 JSON 봉투를 사용합니다. 성공은 {"ok": true, "data": ...}, 오류는 {"ok": false, "error_type": "...", "message": "..."}입니다. Dry-run 작업 계획은 {"ok": true, "dry_run": true, "requires_confirmation": true, ...}를 반환합니다. 부작용 도구 완료 후 캐시가 자동으로 재구축되지 않습니다. 검색 메타데이터를 업데이트하려면 rebuild_cache를 수동으로 호출하십시오. MCP 검색, 멘션, 요약은 모두 투자 조언을 구성하지 않습니다.

semantic_summarize_episode는 더 엄격한 API 비용 도구입니다. transcript 텍스트를 외부 LLM 공급자에게 전송하므로 API 비용이 발생할 수 있습니다. 따라서 confirm=true 외에도 정확한 확인 문구를 제공해야 합니다:

I understand this may call an external LLM API, send transcript text outside this machine, and incur costs.

처음에는 confirm=false로 호출하여 dry-run 작업 계획, transcript 검증 미리보기, 청크 설정, 위험을 확인하십시오. 외부 API, 데이터 전송, 비용 위험을 수락하는 경우에만 confirm=true와 정확한 api_cost_ack로 실행하십시오. MCP 응답은 API key를 반환하지 않으며 dry-run에서 대본 원문도 반환하지 않습니다. 성공 후 캐시가 자동으로 재구축되지 않습니다. SQLite 캐시가 새 .semantic.md artifact를 인식하도록 하려면 rebuild_cache를 수동으로 실행하십시오.

Phase 6L은 run_research_workflow MCP 노출을 추가했습니다. 이 통합 워크플로우 도구는 dry-run 우선입니다. confirm=false는 계획된 읽기/쓰기, 단계 순서, 외부 API/비용 위험, 캐시 오래됨 경고 및 필수 확인 사항만 나열하며, 아티팩트를 쓰지 않고, LLM을 호출하지 않으며, 원시 대화록을 반환하지 않고, API 키 값을 읽지 않습니다. confirm=true는 기존 핵심 워크플로우를 호출하며, 의미론적 요약이나 주식 렌즈 합성이 포함된 경우에도 정확한 확인/api_cost_ack을 제공해야 합니다. 워크플로우 MCP 도구는 외부 시장 데이터를 조회하지 않고, 자동 캐시 재구축이 없으며, 매수/매도 추천, 목표 주가 또는 수익 보장을 추가하지 않습니다.

MCP 클라이언트 통합

Codex/Claude 계열 로컬 클라이언트는 기존 stdio 전송을 사용합니다:

python scripts/run_mcp_server.py

Hermes/OpenAB는 별도 사이드카와 동일한 정확한 21개 도구 레지스트리를 사용합니다:

wsl.exe -d UbuntuProd -u root bash scripts/build_hermes_sidecar.sh podcast-ingest-core-mcp:local
docker compose -f deploy/hermes/docker-compose.sidecar.yml config --quiet

배포, config/Skill plan→apply→rollback, direct-safe 검증기 및 이식 방법은 deploy/hermes/README.mdspecs/026-hermes-mcp-integration/quickstart.md를 참조하세요. Direct 전송은 검증되었습니다. C6의 boolean 전용 endpoint-equality 검증기는 targeted 테스트, POSIX 합성 검사, 검토자 2명 및 유일한 라이브 v2 실행을 통과했으며, 상태는 PASS-current이며 다시 실행해서는 안 됩니다. C7은 여전히 차단됨. Hermes v0.20.0 태그 v2026.8.3 훅은 설치되지 않았고 실기 검증되지 않은 후보 기능일 뿐입니다. 라이브 구성 값/세션 덤프를 읽거나, 원시 응답을 저장하거나, 훅을 업그레이드/활성화하여 증거를 보강하는 것은 금지됩니다. Spec 027 계약 계층은 완료되었으며(오프라인 보증 전용), 실제 Hermes 런타임 라우팅은 BLOCKED/not_evaluated이며 런타임 PASS가 아닙니다. Spec 028 기능 게이트는 완료되었으며 Hermes v0.20.0 태그 v2026.8.3에 대해 BLOCKED_CAPABILITY에서 올바르게 종료됩니다. 업그레이드, Skill 동기화, 훅, 수집기, 추론 또는 런타임 관찰은 수행되지 않았습니다. C6은 PASS-current로 유지되며 다시 실행되지 않았습니다. 실제 Hermes Skill 라우팅은 여전히 BLOCKED/not_run 상태입니다.

Codex/Claude 계열 MCP 클라이언트에 연결하기 전에 먼저 로컬 준비 상태 확인을 실행하는 것이 좋습니다:

python scripts/validate_mcp_setup.py --podcast gooaye --query 台積電

클라이언트 설정 문서:

이 문서들은 자리 표시자 경로만 사용합니다. 개인 .codex/config.toml, 개인 절대 경로가 포함된 설정, .env 또는 API 키를 커밋하지 마십시오.

MCP 도구 사용 평가

Codex/Claude 계열 MCP 클라이언트에 연결한 후 eval 프롬프트 모음을 사용하여 도구 사용이 기대에 부합하는지 확인할 수 있습니다. 시작하기 전에 다음을 실행하세요:

python scripts/validate_mcp_setup.py --podcast gooaye --query 台積電

작성 가능한 Codex MCP 세션 평가 보고서를 생성합니다:

python scripts/new_mcp_eval_report.py --name codex-session-001

평가 문서:

Phase 5B 평가는 실제 외부 LLM API 호출, 실제 다운로드/전사/요약/아티팩트 쓰기 실행을 요구하지 않습니다. 핵심은 도구 선택, dry-run, 확인 가드, 캐시 오래됨 설명, 투자 조언 미생성을 확인하는 것입니다. Phase 5C는 사용자가 실제 Codex MCP 세션 결과를 evals/에 기록할 수 있는 보고서 캡처 프로세스를 제공합니다.

연구 안전 평가

Phase 6H는 연구 계층과 향후 LLM 워크플로우가 환각을 일으키지 않고, api_cost_ack을 건너뛰지 않으며, 원시 대화록/API 키를 유출하지 않고, 외부 경계를 검증된 시장 데이터로 취급하지 않으며, 투자 조언을 생성하지 않도록 검증하는 LLM 사전 안전 게이트입니다.

연구 평가 문서:

Phase 6H는 LLM을 호출하지 않고, API 키를 읽지 않으며, 외부 시장 데이터를 조회하지 않고, MCP 도구를 추가하지 않으며, Phase 6G 워크플로우를 변경하지 않습니다. Phase 6I는 연구 워크플로우 내부에 선택적 의미론적 요약 실행을 추가했습니다. Phase 6J는 Stock Lens LLM 합성을 추가했으며, 입력 경계는 6F stock lens JSON 전용이고, 정확한 api_cost_ack이 필요하며, 원시 대화록, 외부 시장 데이터, MCP 도구 변경이 없습니다. Phase 6K는 워크플로우 옵트인 합성을 추가했습니다. include_stock_lens_synthesis는 워크플로우가 확인되고 정확한 확인 후에만 합성을 실행합니다. Phase 6L은 run_research_workflow MCP 노출을 추가했습니다. dry-run 우선이며, 확인된 실행만 핵심 워크플로우를 래핑하고, LLM 단계에는 여전히 정확한 확인이 필요하며 자동 캐시 재구축이 없습니다. Phase 6N은 include_external_data_verification 선택적 워크플로우 픽스처 검증을 추가했습니다. 로컬 픽스처 공급자만 지원하며, 라이브 마켓 API, API 키, MCP 도구 변경, 자동 캐시 재구축이 없고 투자 조언을 제공하지 않습니다. Phase 6O는 research-llm-smoke를 추가했습니다. 실제 OpenAI 호환 스모크 + Codex 수동 검토, 정확한 확인, 직접 Codex 세션 백엔드 없음, 라이브 시장 데이터 없음, 투자 조언 없음. Phase 6Q는 LLM 프로필 구성을 추가했습니다. --llm-profile pro4500은 공급자/모델/기본 URL/env var 이름을 재사용할 수 있지만 API 키 값은 저장하지 않습니다. Phase 6R은 로컬 .env 시크릿 로더를 추가했습니다. 수동 LLM 스모크는 API_KEY, MODEL, BASE_URL을 사용할 수 있으며, CLI 메타데이터는 env var 이름만 표시하고 시크릿 값은 표시하지 않습니다. Phase 6T는 연구 LLM 스모크 검토 보고서/품질 게이트를 추가했습니다. 확인된 스모크 후 결정적 검토 아티팩트를 생성할 수 있으며, LLM 호출, .env 읽기, 외부 시장 데이터가 없습니다. Phase 6V는 검토된 의미론적 컨텍스트 옵트인을 추가했습니다. 주식 렌즈 합성은 기본적으로 여전히 6F stock lens JSON 전용이며, 명시적으로 활성화한 경우에만 검토 통과 .semantic.md 컨텍스트를 사용하고, 원시 대화록, 라이브 시장 데이터, MCP 도구 변경, 투자 조언이 없습니다. Phase 6V.1은 검토 게이트 경계/컨텍스트 일관성을 정렬했습니다. JSON 전용 아티팩트는 의미론적 컨텍스트를 포함할 수 없으며, 검토된 의미론적 경계는 검토 통과 컨텍스트를 포함해야 합니다.

Spec Kit / 아키텍처

Phase 7A는 아키텍처/Spec Kit 안정화로, 범위는 docs/spec 전용입니다. 현재 Phase 6T 연구 시스템을 spec-kit 추적 가능 구조로 정리하며, 런타임을 변경하지 않고, MCP를 변경하지 않으며, LLM을 호출하지 않고, .env를 읽지 않으며, 외부 시장 데이터를 조회하지 않고, no investment advice 경계를 완화하지 않습니다. Phase 7A 이후 다음 기능 후보 단계는 Phase 6U 의미론적 요약 스모크 또는 소규모 LLM 출력 품질 튜닝입니다.

Phase 7B는 공식 Spec Kit 부트스트랩입니다. 프로젝트는 공식 specify init과 동등한 스캐폴드를 공식적으로 채택했습니다. .specify는 Spec Kit 메모리, 템플릿, 스크립트, 워크플로우 및 통합 메타데이터를 저장하고, .agents/skills는 Codex skills 모드의 $speckit-* 스킬을 저장하며, AGENTS.md는 저장소 수준 에이전트 규칙을 저장합니다. Phase 7B는 런타임을 변경하지 않고, MCP를 변경하지 않으며, LLM을 호출하지 않고, .env를 읽지 않고, 라이브 마켓 API를 조회하지 않으며, no investment advice 경계를 완화하지 않습니다.

Phase 7C는 Spec Kit 헌법 + 워크플로우 정렬입니다. 이 단계는 .specify/memory/constitution.md를 공식 자리 표시자에서 프로젝트화하고 .specify/templates/, AGENTS.md, 아키텍처, 로드맵 및 사양 계획을 동기화합니다. Phase 7C는 docs/spec/테스트 전용입니다. 런타임 동작 변경 없음, MCP 동작 변경 없음, LLM 호출 없음, .env 읽기 없음, 라이브 마켓 API 없음, 투자 조언 없음. Phase 7C 이후 새 기능은 전체 Spec Kit 흐름을 따라야 합니다: $speckit-constitution, $speckit-specify, $speckit-clarify, $speckit-plan, $speckit-checklist, $speckit-tasks, $speckit-analyze, $speckit-implement, $speckit-converge; $speckit-taskstoissues는 GitHub 이슈 핸드오프가 필요할 때만 사용합니다. Phase 6U 의미론적 요약 스모크는 여전히 향후 가능한 기능 단계입니다.

Phase 7D는 전체 워크플로우를 통한 Spec Kit 백필입니다. 이 단계는 전체 Spec Kit 흐름을 사용하여 개발된 기능을 기능 그룹별로 백필합니다. specs/README.md는 레지스트리이고, 001-gooaye-research-system은 포괄 제품 사양으로 유지되며, 002-ingestion-transcript-core부터 007-spec-kit-governance까지 as-built 기능 패키지를 기록하며, 006-llm-safety-synthesis-smoke-review는 선택적 LLM/스모크/검토 게이트를 다룹니다. Phase 7D는 docs/spec/테스트 전용입니다. 런타임 동작 변경 없음, MCP 동작 변경 없음, LLM 호출 없음, .env 읽기 없음, 라이브 마켓 API 없음, 투자 조언 없음, $speckit-clarify, $speckit-analyze, $speckit-converge의 백필 단계를 명시적으로 문서화합니다.

Phase 7D.1은 Spec Kit 활성 기능 지침입니다. 이 단계는 공식 Spec Kit 명령 사용성을 명확히 합니다. 기능 패키지의 올바른 위치는 specs/<feature>이고, .specify/는 스캐폴드/메모리/템플릿/스크립트 메타데이터입니다. 여러 백필된 패키지는 단일 활성 기능을 기본적으로 고정하지 않습니다. 특정 패키지에 대해 공식 스크립트/스킬을 실행하려면 먼저 SPECIFY_FEATURE_DIRECTORY를 설정하세요(예: $env:SPECIFY_FEATURE_DIRECTORY="specs/003-metadata-search-mcp-core"). 공식 스크립트는 .specify/feature.json에 저장될 수 있으므로 패키지를 전환할 때 다시 설정하면 됩니다. Phase 7D.1은 런타임을 변경하지 않고, MCP를 변경하지 않으며, LLM을 호출하지 않고, .env를 읽지 않고, 라이브 마켓 API를 조회하지 않으며, 투자 조언을 제공하지 않습니다. Phase 6U 의미론적 요약 스모크는 여전히 향후 가능한 기능 단계입니다.

Spec-kit 문서:

라이선스

이 저장소는 MIT 라이선스에 따라 라이선스가 부여됩니다. LICENSE를 참조하세요. 해당 저작권은 자체 저작물에만 적용됩니다. 두 개의 사양 패키지는 자체 MIT 라이선스를 보유한 타사 NousResearch/hermes-agent 저장소의 바이트 고정 스냅샷을 공급합니다. THIRD-PARTY-NOTICES.md를 참조하세요.

개발 명령어

python -m pytest
python -m compileall src scripts

개발 종속성을 설치하려면:

python -m pip install -e .[dev]

Spec034 작업 #82 v8 검토 수리 — 현재

startup/plugin 닫힘; credential_provider BLOCKED; 전체 BLOCKED. Spec034은 H1 SHA-256 90ba45ccf11bbcbf446f7d16904964073e84837a04aaaa0c6f4887d3ea75109d에서 정확히 20개의 업스트림 경로가 있는 H2로 오프라인/정적 전용으로 유지됩니다. 21번째 경로는 허용되지 않습니다. 격리된 하위 프로세스는 페이로드 cwd로 일반적인 no-link/reparse-free 프로젝트 스냅샷만 허용하며, sentinel/Pytest/제품 가져오기 전에 해당 디렉터리로 변경하고, 기능 스냅샷, 프로젝트 스냅샷, stdlib만 유지합니다. 결과적으로 C6의 세 가지 상대 구성 읽기는 스냅샷 이후 원래 작업 영역 구성이 변경되더라도 스냅샷 승인 바이트를 사용합니다. 공개 영수증 프로젝션에는 주입된 검증기가 없습니다. 비공개 발행은 현재 정식 사실을 다시 계산합니다. AST 증명은 소유자 로컬 패키지 사양/모듈/로더/반환/등록/컨텍스트 흐름을 따릅니다. 번들 이름 바꾸기 상위 fsync는 명시적 플랫폼 최선 노력 폴백과 함께 bundle_renamed 저널보다 먼저 수행되며, 정확한 nonce 바인딩 양쪽 누락 복구만 재시도에 안전합니다. 실행기/저널/신뢰 테스트는 여전히 최종이 아닙니다. 이전의 모든 루트는 승인 증거가 아닙니다. 새로운 코드 및 아키텍처 재검토가 여전히 필요합니다. Main만 두 PASS 후 문서화된 일회성 명령을 실행할 수 있으며 여기서는 실행되지 않습니다.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A dual-transport MCP server that exposes your API as tools to LLM clients, supporting both stdio transport for local clients like Claude Desktop and HTTP/SSE transport for remote clients like OpenAI's Responses API.

View all related MCP servers

Related MCP Connectors

  • Podcast Index MCP — wraps the Podcast Index API (podcastindex.org)

  • Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.

  • MCP server for Clipkit — gives AI agents a video toolbox via the Clipkit schema.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/norton77930/corpus-ingest-core'

If you have feedback or need assistance with the MCP directory API, please join our Discord server