Skip to content
Skillv1.0.0

swing-daily

Run the end-to-end daily swing-trading analysis loop. Executes `copilot-daily` for the deterministic pipeline, fans out news/filings/screening interpretation to parallel expert subagents, reconciles t

by tomada1114(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from tomada1114/swing-copilot (.claude/skills/swing-daily/SKILL.md). Install upstream with npx skills add tomada1114/swing-copilot --skill swing-daily. Copyright stays with the author.

日次分析ワークフロー(統括)

機械処理は Python、定性判断はこのスキル、最終判断は人間。 決定論的な出力(スコア・ランキング・リスク制約)は絶対に書き換えない

実行前提(GitHub Actions のみ)

このスキルの起動経路は .github/workflows/swing-daily.yml の GitHub Actions job だけである。ローカルの対話セッションから swing-daily を実行する運用は 採らない。copilot-daily はローカルで決定論的なレポート入力を作れるが、 ニュース・開示・スクリーニングの定性分析と ingest は CI の job が担当する。

入力スライスなどの作業用ファイルは、checkout 直下の <REPO_ROOT>/.swing-daily-scratch/(以下 <SCRATCHDIR>)にだけ置く。 このディレクトリは .gitignore 対象で、reports/<WORKDIR> とは別の場所である。

作業前に必ず読む:

  • references/analysis-conventions.md — AC1〜AC16 の共通規約(CON-03・provenance・叙述・数値整合)
  • references/output-schema.md — 入出力 JSON スキーマと analysis_work/ 断片の形式
  • src/swing_copilot/analysis/schemas.pyスキーマの最終正本。JSON を組み立てる前に必ず読む

Inputs

analysis_input.json があるディレクトリを <WORKDIR> と呼ぶ(当日のレポート出力先)。

  • <WORKDIR>/analysis_input.json — 必須。copilot-daily が生成。読み取り専用
  • <WORKDIR>/analysis_work/news-<SYMBOL>.json — 任意。専門家の出力断片。Step 3 でマージ
  • <WORKDIR>/analysis_work/filings-<SYMBOL>.json — 任意。同上
  • <WORKDIR>/analysis_work/screening-<SYMBOL>.json — 任意。同上
  • <WORKDIR>/analysis_result.json — 任意。存在すれば再入とみなす(Step 0)
  • references/analysis-conventions.md, references/output-schema.md, src/swing_copilot/analysis/schemas.py

Outputs

  • <WORKDIR>/analysis_result.json — このスキルが直接書く唯一の成果物
  • 当日の Markdown レポート — copilot-ingest-analysis 経由で再描画される(間接出力)
  • <WORKDIR>/analysis_work/** — 専門家サブエージェントが書く。統括は読み取りのみ行い、 内容を書き換えない。陳腐化した断片は削除せず、上書き・無視で処理する(Step 0)。 唯一の例外は前営業日の開示断片の持ち越しで、これは逐語コピーであり内容を 1 文字も変えない(Step 0「開示断片の日跨ぎ流用」)
  • <WORKDIR>/headless_note.md — 無人実行時のみの人間向けメモ(「無人実行(headless) 時の方針」を参照)。契約されたアーティファクトではなく、ingest は読まない

一時ファイルと後始末(統括・全サブエージェント共通)

このワークフローは平日定時に GitHub Actions 上で無人起動される。rm は許可 リストに無いため、1 回でも実行しようとすると承認待ちで実行全体が停止する (実測で 44 分停止した例がある)。したがって次を全員が守る。

  • 作業用の一時ファイル(入力スライス、抽出テキスト等)は <SCRATCHDIR> 配下にだけ作る。<WORKDIR> 直下や analysis_work/ には置かない
  • 契約検証のスクリプトは統括もサブエージェントも書かない。 断片と analysis_result.json の検証は uv run copilot-verify-analysis が担う (Step 3 / Step 5)。同じ検査を各自が実装し直すと、実装のばらつきがそのまま 検査水準のばらつきになる(Issue #132)
  • 一時ファイルを削除しない。rm を実行しない。 GitHub-hosted runner は job 終了時に checkout 全体を破棄するため、<SCRATCHDIR> の掃除は runner に任せる
  • job の途中で <SCRATCHDIR> を掃除する手順は設けない。job の再実行は新しい checkout から始まるため、前回のスライスを流用する必要もない

サブエージェントの実行上限と打ち切り(統括・全サブエージェント共通)

このワークフローは平日定時に無人起動されるため、1 体でも居残るとその日の実行全体が 終わらない(実測で開示分析 1 体が単独 52 分居残った日、analysis_result.json 未生成の まま夜まで伸びて終了した日がある)。問題は中央値ではなく裾なので、次の上限を Step 2 の専門家・Step 3 と Step 3.5 の再分析/追加分析・Step 3.6 の反証・Step 3.7 の 対称のすべてに一律で適用する。

1 体あたりの上限(サブエージェント側が守る)

上限 到達したときの振る舞い
壁時計 15 分 サブエージェント自身が必ず打ち切る(超過に気づいた時点で終了する)。親の TaskStop(下記「親(統括セッション)の待ち方」)は、それが効かなかった場合の保険
ツール呼び出し回数 40 回 自分で打ち切り、未完了分を要約に書いて終了する
copilot-verify-analysis が FAIL した後の再試行 2 回まで(検証の実行は最大 3 回) 3 回目も FAIL なら断片を残置したまま終了し、FAIL 理由を要約に書く
  • 1 体あたりの上限は、親に何も起きなくても効く唯一の機構である。 親側の締切 ウォッチャと TaskStop は「親のセッションが生きていて、背景タスクの完了通知を 受け取れる」ことを前提にしている。無人実行ではこの前提が崩れることがあるため (「無人実行(headless)時の方針」)、上限の自己適用は「してよい」ではなく 「必ずする」。1 体が単独でセッションのターン/時間予算を食い潰さないことを、 親の介入に頼らずサブエージェント側で保証する
  • 自ら打ち切った場合の断片の扱いは、親に打ち切られた場合とまったく同じである (下記「打ち切った組の扱い(fail-closed withhold)」)。上限に達したことは、 書きかけの断片を出してよい理由にならない
  • 割り当てられた入力スライスは通し 1 回で読む。 長い本文を先頭から順にチャンクへ 分けて読むのは「1 回」に含まれる(開示分析の分割読みはこれに当たる)。禁止するのは 読み終えた範囲を後から読み直すことで、必要な値は最初の読み取りで控える
  • 元の analysis_input.json の全件を読まない。 開いてよいのは run_id / as_of / input_digest の照合に必要なメタデータ投影だけで、 担当外銘柄の本文には触れない(Step 2「サブエージェントへ渡す入力範囲」と同じ規律)
  • 上限に達した時点で未完了の銘柄のファイルを書かない。 書きかけの断片、担当 ソースの一部しか見ていない断片を出さない。完了した銘柄のファイルだけを残し、 どの銘柄が未完了かを親への要約に明記する
  • 上限に達しても rm は実行しない(「一時ファイルと後始末」)

親(統括セッション)の待ち方

  1. 波を起動する直前に、その波の締切を測るウォッチャを 1 本だけ背景実行する。 Step 2 の最初の波では、これに加えて全体(45 分)のウォッチャも 1 本背景実行する。

    # 1 波あたりの締切(15 分)。全体ウォッチャは 900 を 2700 に置き換える
    ./scripts/timebox.sh 900

    リポジトリルートを作業ディレクトリとして run_in_background で起動し、完了通知 (TIMEBOX_REACHED)をその波の締切とみなす。この呼び出しの形をそのまま使う。 .claude/settings.json と headless 起動時の CLI allowlist には、この形と定性分析で 必要な5つの専用 copilot-* コマンドだけが登録されている。同じ処理を bash の ワンライナーへ展開すると無人実行中に承認待ちで止まり、打ち切り機構そのものが 居残りの原因になる。起動した各エージェントの ID/名前は TaskStop に渡すため 必ず控える

    起動できたことを確認してから波へ進む。 この形は相対パスなので、シェルの 作業ディレクトリがリポジトリルート以外にあると exit 127No such file or directory)で即座に落ちる。2026-08-19 の dry-run (run 32305475841)の headless_note.md にこの exit 127 が記録されており、 待つための唯一のブロッキング手段が無いまま 4 の代替規則へ落ちていた。 背景プロセスが TIMEBOX_REACHED を出さずに終了していたら、リポジトリルートの 絶対パス1 回だけ起動し直す。<REPO_ROOT>このスキルファイル自身の 絶対パス<REPO_ROOT>/.claude/skills/swing-daily/SKILL.md)から .claude/ の 直前までを取る。<WORKDIR> から数えないこと — live は reports/<as_of>/<run_id>/、dry-run は reports/dry_run/<as_of>/<run_id>/ で 階層が 1 つ違い、階層を決め打ちすると dry-run で存在しないパスを叩いて もう一度 127 になり、1 回だけの再起動を使い切る:

    <REPO_ROOT>/scripts/timebox.sh 900

    この復旧は、この節で起動するすべてのウォッチャに等しく適用する — 1 波あたりの 900 だけでなく、Step 2 の最初の波で起動する全体(45 分・2700)のウォッチャにも 同じ手順で当てる。全体ウォッチャは 6 の最終防波堤そのものなので、これを取りこぼすと 45 分の上限が黙って消える。

    絶対パスは allowlist の前方一致から外れる。GitHub Actions の無人実行では承認待ちに できないため、起動できなかった場合の終了コードとメッセージを、4 の代替規則へ 切り替えた根拠として headless_note.md と Step 7 にそのまま残す(GitHub Actions のログには残らないため、ここが唯一の記録になる)

  2. 締切より前に全エージェントが完了したら、そのまま次のステップへ進む

  3. 締切の通知が届いた時点で未完了のエージェントが残っていれば、待ちを延長せず TaskStoptask_id に当該エージェントの ID または名前)で 1 体ずつ止める。 「あと少しで終わりそう」は延長の理由にならない

  4. ウォッチャを起動できない場合(承認待ちになる、スクリプトが無い/実行できない、 引数エラーで即座に終了する。1 の絶対パスでの 1 回を含めてなお起動できない場合を 指す)は再試行せず、時計に頼らない代替規則へ 切り替える: その波の過半が完了した時点で、残っている エージェント(1 体とは限らない)を打ち切り候補とみなす。親は待機に入らず、揃って いる断片の読み取りと Step 3 の機械検証を先に進め、それを終えてもまだ完了していない 候補を TaskStop する。1 体も完了しないまま親が進められる作業を使い切った場合も 同じで、待ち続けずにその波を打ち切り、揃っている断片だけで Step 3 へ進む。

    ただし起動直後の波を打ち切らない。 この代替規則は「時計が無い状態で待ちすぎ ない」ためのものであって、fan-out した直後に全滅させるためのものではない (それでは 30 断片中 2 断片の日が 0 断片の日になるだけである)。過半の完了も、 親が進められる作業の枯渇も観測できていないなら、無人実行では前景ウォッチャ (「無人実行(headless)時の方針」)で 1 体あたりの上限(15 分)ぶんを刻んで待つ。 打ち切ってよいのは、過半が完了したか、その 15 分に達したか、のいずれかである

  5. 打ち切りに伴う再起動は、同じ「銘柄 × 専門家」の組につき通算 1 回まで (Step 3 の「欠けている組があれば再起動する」もこの上限の下で行う)。再起動した 1 体にも同じ 1 体あたりの上限が適用される。2 回目も打ち切りになった組は、 以降は再起動せず withhold で確定させる

  6. Step 2 の最初の波を起動してから Step 3 のマージを終えるまでの合計が 45 分を 超えたら、未完了の組をすべて打ち切り、その時点で揃っている断片だけで Step 3 を 確定させる。1 体あたりの上限をすり抜けた波の積み上がりに対する最終防波堤であり、 到達した事実は Step 7 で報告する

打ち切った組の扱い(fail-closed withhold)

打ち切りは「その組は分析されなかった」ことを意味する。部分的な断片を「分析済み」 として扱わない。

  • 打ち切り時点で断片ファイルが存在し、Step 3 の copilot-verify-analysisPASS するものは、1 銘柄 1 ファイルで完結する成果物なので通常どおりマージしてよい。 ファイルが無い/FAIL する/JSON として壊れているものは存在しないものとして扱う (rm はしない。Step 0・Step 3 のとおり残置して読み飛ばす)
  • 以下でいう打ち切られた組とは、この「存在しないもの」として扱った組を指す。 打ち切りに巻き込まれても断片が PASS した組は分析済みであり、これに含めない
  • 打ち切りに巻き込まれた銘柄は、断片が PASS していても「担当ソースの一部しか 見ていない」可能性を機械検査では排除できない。Step 3.5 では AC9(複数ソースの 取りこぼし)を重点的に見る
  • 存在しないものとして扱った組は、その銘柄の該当セクションを空のまま確定させる (ニュース → news_summary: null、開示 → filing_analyses: [])。統括が内容を 代筆しない
  • screening_assessment は全銘柄必須(Step 5)なので、スクリーニング断片が無いまま 確定させる場合に限り、統括は定性的な読みを一切含まない最小限の screening_assessment を書く。summary には「定性評価は実行上限による打ち切りで 未完了」という事実だけを書き、strengths / concerns は空にする。決定論的スコアの 引き写しや、入力に無い情報の補完をしない(AC1・AC8・AC14)
  • 打ち切られた組を持つ銘柄の verdict.recommendationskip に固定する。 定性材料が欠けたまま proceed を出さない(無人実行時の方針と同じ保守側)。 reasons の少なくとも 1 件に、この skip が「実行上限による打ち切りで当該分析が 未完了であることに基づく見送りであり、特定されたリスクに基づくものではない」旨を 書く。この理由はテキスト由来ではないので source_ids: [] とし、basis は 該当する値が無いため付けない(AC10b)
  • 打ち切りによる skip は Step 3.7 の材料不在型 skip の判定から除外する。 不足しているのは入力ではなく分析であり、対称エージェントに供給できる材料そのものが 欠けているため、追加の 1 段を当てても判断材料が増えない
  • 打ち切りは Step 0 の再入判定と矛盾しない。断片を rm せず残すため、同じ run_id / as_of / input_digest で再実行した場合は、PASS する断片が流用され、 無い断片・FAIL する断片だけが再分析対象になる(Step 0 の 2 と Step 3 の 「断片の機械検証」がそのまま働く)。ただしこの再実行は自動では起きない。 analysis_result.json を書いて終了した以上、Step 0 の 1 のとおり再実行には ユーザーの明示指示(と copilot-daily --allow-same-day-rerun)が要る。 無人実行では翌営業日に自動回復しないため、打ち切りで withhold した銘柄は Step 7 の報告と headless_note.md に必ず残す

Step 0: 既存アーティファクト確認(Phase 0・冪等な再入)

<WORKDIR> が既に分かっている場合(同一セッションでの再実行、ユーザーがパスを 指定した場合)はここで確認する。分からない場合は Step 1 の直後に同じ確認を行う。

  1. 次のいずれかが存在する場合、既存アーティファクトとみなす:
    • <WORKDIR>/analysis_result.json
    • reports/<as_of>/*/analysis_result.json(glob。<WORKDIR> が未確定でも 対象日 as_of さえ分かれば確認できる。#118 の同日重複起動ガードが run_id 発行前に判定するrun_date単位の重複と同じ粒度で見るための追加確認)
    • ユーザーが明示的に再実行・やり直しを求めていなければ 上書きしない。 既存の verdict を要約して報告し、再実行するか確認する
    • 再実行を求められている場合のみ、以降のステップで上書きしてよい(Step 1 の uv run copilot-daily--allow-same-day-rerun を付けて実行する)
  2. <WORKDIR>/analysis_work/ が存在する場合、各断片が流用できるかを判定する。 判定は uv run copilot-verify-analysis <WORKDIR>/analysis_work が機械的に 行う。自前の照合スクリプトを書かない(Step 3 の「断片の機械検証」参照):
    • PASS → その銘柄 × 専門家は 再分析せず流用する
    • FAIL(別 run の残骸、JSON として壊れている、ペイロードキーが無い、 symbol がファイル名と食い違う、provenance / evidence_quote / CON-03 違反) → 流用せず再分析対象にし、担当専門家に同じパスを上書きさせる
    • 陳腐化した断片を rm で消さない。 上書きで同じ結果になり、削除は 「一時ファイルと後始末」の禁止事項に当たる
  3. 流用の鍵は断片の種類で違う(Issue #261。正本は references/output-schema.md の「断片の流用可否」):
    • news-<SYMBOL>.json / screening-<SYMBOL>.jsonrun_id / as_of / input_digest3値一致が鍵。当日のニュース・当日の 決定論的スコアを読むので真に as_of 依存であり、日跨ぎでは流用できない。 開示本文が変わっていなくても毎回作り直す
    • filings-<SYMBOL>.jsonfiling_body_digests が、その日の入力が export する開示本文の digest 集合と完全一致することが鍵。開示の読みは開示本文の 関数なので、run_id が変わっても本文が同じなら流用できる(次の「開示断片の 日跨ぎ流用」)
  4. analysis_input.jsoncandidates[].symbol に無い銘柄の断片は、削除せず 無視する(Step 3 のマージ対象から外す)。
  5. 流用した断片は Step 3 でそのままマージ対象に含める(要約は断片内の ac_check と本文から統括が読み取る)。copilot-verify-analysis が PASS した ことが流用の根拠であり、統括が内容を読んで判断し直さない。逆に、facts[].evidence_quote を欠く/引用元本文と一致しない古い断片は同コマンドが FAIL させるので、 自動的に再分析対象になる。

開示断片の日跨ぎ流用(本文ハッシュ・Issue #261)

連続 2 営業日の入力で、共通 5 銘柄の開示 accession が 14/14 一致していた。同じ 10-Q/8-K を毎日ゼロから読み直すのが定性フェーズ最大の構造的無駄なので、開示断片 だけは前営業日の読みを持ち越す。この持ち越しは開示断片に限る。

持ち越しは <WORKDIR>/analysis_input.json が揃ってから(= Step 1 の直後)、Step 2 の 起動より前に行う。当日の候補銘柄と as_of が分からないと対象を選べないためである。

  1. 過去の run ディレクトリを reports/*/*/analysis_work/filings-*.json の glob で 探し、as_of より前の日付のうち新しい順に最大 2 日分だけ見る。今日の候補 銘柄に該当するファイルが対象で、それ以外は開かない
  2. 該当ファイルを読み、1 文字も変えずに <WORKDIR>/analysis_work/filings-<SYMBOL>.json へ書く。内容の書き換え・要約・整形をしない(Outputs の「統括は内容を書き換えない」 はここでも変わらない)。cp などのシェルコマンドは使わない(許可リストに無く、 無人実行が承認待ちで止まる)
  3. 書いたら Step 0 の 2 と同じく copilot-verify-analysis に掛ける。PASS した ものだけが流用で、FAIL したものは Step 2 で開示担当を起動して同じパスを 上書きさせる。転記ミスも本文の変化も、この 1 本の検査が同じように落とす
  4. 流用しても provenance は緩まない。流用した断片も、その日の analysis_input.json に対して provenance・evidence_quote の逐語一致・CON-03 を改めて通る。本文が 変わった開示の古い読みは、たとえ digest 判定をすり抜けても evidence_quote が 現在の本文に存在しないため FAIL する(fail-closed の網)
  5. 流用した断片も Step 3.5 以降の点検対象から外さない。マージ後の扱いは当日書かれた 断片とまったく同じである
  6. 過去 run が見つからない、filing_body_digests を持たない古い断片しかない、 digest が一致しない、のいずれでも単に流用しないだけで、通常どおり Step 2 で 再分析する。持ち越しの失敗は run を止める理由にならない

Step 1: パイプライン実行

uv run copilot-daily <ユーザー指定の引>

引数(対象日、dry-run/live 等)はユーザーの指示に従う。指定が無ければ引数なしで実行。

data/ の同期はワークフローが担当する。 正本は R2 にあり、GitHub Actions の job がこのスキルの前に pull し、成功時に push する。分析セッションには R2 の資格情報を 渡していないため、スキルから data-pull / data-push は実行しない

終了コード 2(preflight abort)は stderr の機械可読プレフィックスで判定する。 stderr の先頭行は PREFLIGHT_ABORT[<reason>]: <メッセージ> の形式。 プレフィックスを読まずに「分析済み」と決め打ちしてはならない。

PREFLIGHT_ABORT[same_day_rerun] — 同一 run_date に対して成功済みの run が 既にあることを意味する(同日重複起動ガード #118。run_date は最新 bar 由来で プリフェッチ後にしか確定しないため、Step 0 の事前確認をすり抜けることがある)。 この場合:

  1. stderr のメッセージから既存の run_id とレポートパスを読み取る
  2. 既存レポート(reports/<as_of>/<run_id>.md)または uv run copilot-history run --run-id <run_id> を読み、既存 verdict を要約する
  3. 「本日は既に分析済み」として上記要約とともに正常終了する。 analysis_result.json は書かない。Step 2 以降に進まない
  4. ユーザーが明示的に再実行を求めている場合のみ、--allow-same-day-rerun を 付けて Step 1 を再実行し、通常どおり続行する

PREFLIGHT_ABORT[no_trading_day] — 取得できた価格データの中に、引けた (米国東部時間 16:00 を過ぎた)取引日が一つも無かったことを意味する(Issue #372)。プリフェッチがエラーを伴わずに空だった・最新の bar がまだ引けていない セッションのものだった、のいずれか。取得そのものが失敗した場合はこれではなく 下の price_fetch_failed になる。この場合:

  1. 「本日は分析すべき取引日が無い」として正常終了する。analysis_result.json は書かない。Step 2 以降に進まない
  2. 自動リトライはしない。翌営業日の定時実行が改めて解決する。ユーザーから 明示的に再実行を求められた場合のみ、状況を確認したうえで再実行を検討する

PREFLIGHT_ABORT[price_fetch_failed] — 価格データの取得そのものが失敗し (例外、または全銘柄が取得エラーで空応答)、引けた取引日を判定できなかった ことを意味する(Issue #372)。上記 no_trading_day とは異なり、これは失敗であって正常な日ではない。 データプロバイダの障害等が原因であり、「本日は分析対象なし」「取引日なし」 と要約してはならない。この場合:

  1. stderr のメッセージ(元の例外の内容を含む)とともに失敗を報告し、 セッションを停止する
  2. analysis_result.json は書かない。Step 2 以降に進まない
  3. 自動リトライはしない。翌営業日の定時実行が改めて価格取得を試みる。 ユーザーへの報告では「取引日が無かった」ではなく「価格データの取得に 失敗した」ことを明示する

プレフィックスが読み取れない終了コード 2 は、いずれとも断定せず stderr 全文を そのまま報告して終了する。終了コード 0/1 は従来どおり続行する。

ANALYSIS_GAP[missing_analysis_result]中断理由ではない。上記の PREFLIGHT_ABORT とは異なり終了コード 0/1(通常続行)の run でも stderr に 出ることがある機械可読タグで、run_date=... run_id=... run_directory=... の形で前営業日以前の run を指す。見つけても run 自体は正常に進んでいるため、 本日の分析は Step 2 以降へ通常どおり進める。タグに含まれる run_date を 控えておき、最終報告と headless_note.md の両方に「run_date の 定性分析が欠落している」旨と、再実行の選択肢(--allow-same-day-rerun を 付けてその run_date 分の run を再実行すれば再取得できる)を明記する。

ターミナル出力から analysis_input.json の絶対パスを拾う。

  • 候補ゼロ、または analysis_input.json がエクスポートされなかった場合は、 そこで終了し「本日は分析対象なし」とパイプラインの要約を報告する。Step 2 以降に進まない。

analysis_input.json から、本文を除いたメタデータ投影だけを読み、run_idas_ofstrategy_keyinput_digestcandidates[].symbol、各sourceの文字数と filings[].coverageを控える。親セッションのツール出力へnews[].summaryfilings[].textを表示してはならない。4値は後段で result に逐語転記する (不一致は hard fail)。

<WORKDIR> が Step 0 の時点で不明だった場合は、ここで Step 0 の確認を実施する。

Step 2: 専門家サブエージェントの並列起動(1 段目)

Step 0 で流用が決まった組を除いた、残りの「銘柄 × 専門家」の組を洗い出す。

専門家 参照スキル 担当 対象銘柄
ニュース分析 .claude/skills/analyze-news/SKILL.md candidates[].news news が非空の銘柄
開示分析 .claude/skills/analyze-filings/SKILL.md candidates[].filings filings が非空の銘柄
スクリーニング定性評価 .claude/skills/interpret-screening/SKILL.md score_breakdown(生値の参考情報を含む)/ risk_constraints / prior_verdicts / context 全銘柄

実行手段: Agent ツール並列が標準

標準経路は Agent ツール(model: sonnet)の並列起動である。 平日定時の無人実行 (CLAUDE.md の "Scheduled Daily Run")を含む headless 実行では Workflow ツールの 利用が明示的に許可されないため、組の数にかかわらず常に Agent 経路を使う。 実行のたびに手段を選び直さない。 候補数は candidate_limit に律速されて日々 似た規模になるため、毎回トリアージし直しても結論は変わらず、判断と説明のコストだけが 積み上がる。

残った組の数を N とし、次の方針で N 組をエージェントへ割り当てる。

  • 1 エージェント = 1 専門家 × 数銘柄。 同じ専門家を銘柄で分割して複数エージェントに 割り当ててよい。逆に、1 銘柄 × 1 専門家という 1 組を複数エージェントへ分割して 結果をマージすることはしない
  • 開示分析は既定で 1 銘柄 1 エージェント。 filings[].text は長く、1 エージェント あたりの合計文字数上限(下記「サブエージェントへ渡す入力範囲」)にすぐ届くため。 まとめてよいのは、合計がその上限に十分収まる短い銘柄同士に限る
  • ニュース分析・スクリーニング定性評価は 1 エージェントあたり 3 銘柄程度を目安に まとめる。担当テキストが短ければ増やしてよい
  • 起動は 同一メッセージ内で並列に行う。並列枠に収まらない場合は波に分け、 波をまたいでも各エージェントへの指示内容は変えない

Workflow ツールは使わない。 GitHub Actions の無人実行では利用を明示的に許可 していないため、組の数にかかわらず Agent 経路で fan-out する。手段の違いが分析内容の 違いにならないよう、各エージェントへ渡す指示内容と銘柄割り当て方針は常に同じにする。

サブエージェントへ渡す入力範囲

analysis_input.json の全件をサブエージェントのメッセージに貼り付けない。担当する 専門家と銘柄に必要な入力だけを含む読み取り専用の入力スライスの絶対パスを渡す。 スライスは手で切り出さない。 次のコマンドが決定論的に生成する(Issue #260。 手切りは 2026-08-13 の実走で 21 件・5.2 分かかり、欠落・重複ミスの温床でもあった)。

uv run copilot-export-slices <WORKDIR>/analysis_input.json \
  --out-dir <REPO_ROOT>/.swing-daily-scratch/slices
  • <REPO_ROOT>/.swing-daily-scratch/slices が CI 専用の固定出力先である。<WORKDIR> と同じパス・その配下・その上位を --out-dir に渡した場合はコマンドが拒否して終了 する(exit 1)。別のパスへ切り替えず、この固定出力先を使う
  • 生成物は slice-<kind>-<SYMBOL>.json<kind>news / filings / screening)で、1 スライス = 1 専門家 × 1 銘柄。news が空の銘柄には news スライスを、filings が空の銘柄には filings スライスを作らず、screening は 全銘柄に作る。run 単位の context(market_regime / calendar_events)は screening スライスにだけ入る。上表の担当割り当てと同じ規則である
  • filings スライスの candidate.filings[].text_chunks は、元の filings[].text を順序どおり分割した輸送用配列である。Read の1物理行上限を 避けるため各 JSON 文字列行は最大 8,000 文字に制限されている。開示担当は チャンクを区切り文字なしで連結して本文を再構成し、境界に改行や空白を足さない
  • news が空でも news_supply を持つ銘柄に news スライスを作らないのは、 analyze-news と AC14 が「news が空なら news_summary: null を書く」ことを 求めているためである。今のままエージェントを立てても null が返るだけで、 供給量の申告(Issue #130)はレポートへ届かない。届かせるには専門家側の規約変更が 要り、それはスライス生成とは別のイシューで追う
  • 標準出力に「絶対パス / kind / 銘柄 / source_chars(そのスライスが載せている本文の 文字数)」がタブ区切りで 1 行ずつ出る。この一覧が正本で、親はここから各 エージェントへ渡すパスを選ぶ。スライス本体を親が読む必要はない
  • source_id と本文、run_id / as_of / input_digest は元入力からの逐語コピーで、 filings の本文は text_chunks を連結した値が逐語一致し、strict スキーマ (extra="forbid")検証を通ってから書かれる。形式・不変条件は references/output-schema.md の「サブエージェント入力スライス」 に従う
  • filings スライスにだけ filing_body_digestssource_id → 開示本文の SHA-256)が 付く。これはスライス内で唯一の計算値で、開示担当が断片へ逐語コピーする値である。 翌営業日の流用可否がこの値で決まる(Issue #261)
  • 自前の切り出しスクリプトを書かない。 同じ入力からは常にバイト同一のスライスが 出るので、失敗しても同じコマンドを再実行すればよい。スライス群は集合単位で 書かれるため、失敗した実行は 1 件も書き残さない(部分的なスライス集合を拾って しまう心配は要らない)。Step 0 で流用が決まった組のスライスが生成されても、 渡さなければよい
  • 元の analysis_input.json の絶対パスも併記するが、サブエージェントは metadata の 照合以外で全件を読み込まない。これにより、長大な開示本文を担当外銘柄ごとに 重複してコンテキストへ載せない
  • 開示担当は1エージェントあたりの担当銘柄について、出力された source_chars (= filings[].text の文字数)の合計を 240,000文字以下にする。240,000文字に 近い銘柄は単独担当とし、複数銘柄を詰め込まない。並列枠を超える場合は波に分ける。 1銘柄を複数エージェントへ分割してマージしない
  • この240,000文字はモデルのコンテキスト上限ではなく、安全余白を残す運用上限である。 スキル規約・決定論的文脈・出力・追加レビューの余白を確保し、モデルの公称上限まで 本文で埋めない

各エージェントへの指示に必ず含めるもの

  1. .claude/skills/<name>/SKILL.md を読み、それに従うこと
  2. analysis_input.json と、担当銘柄ごとの入力スライス (copilot-export-slices が出力した slice-<kind>-<SYMBOL>.json)の絶対パス、 担当する銘柄シンボルの列挙。スライスを分析に使い、元入力の run_id / as_of / input_digest と一致することを確認すること
  3. 出力は <WORKDIR>/analysis_work/<kind>-<SYMBOL>.json へのファイル書き出し<kind>news / filings / screening、1 銘柄 1 ファイル)。開示担当には スライスの filing_body_digests を断片へ全件逐語コピーさせること (何も書かなかった開示の分も残す。自分でハッシュを計算させない。Issue #261)
  4. 親に返すのは 銘柄ごと 1〜2 行の要約 + 特記事項 + AC 自己点検結果だけ。 JSON 全文・生の入力テキストをメッセージに載せないこと
  5. 作業用の一時ファイルは <SCRATCHDIR> 配下にだけ作り、削除しないこと (rm を実行しないこと)。無人実行では rm の承認待ちでワークフロー全体が 停止する(「一時ファイルと後始末」参照)
  6. 書き出した断片を uv run copilot-verify-analysis <断片の絶対パス> で検証し、 契約検証のスクリプトを自作しないこと。合否と FAIL 理由を親への要約に含めること。 FAIL したときの修正・再検証は 2 回まで(検証の実行は最大 3 回)。3 回目も FAIL なら 断片を残置したまま終了し、FAIL 理由を要約に書くこと(rm はしない)
  7. 実行上限(「サブエージェントの実行上限と打ち切り」参照): 壁時計 15 分・ ツール呼び出し 40 回を上限とすること。上限に達したら未完了銘柄のファイルを 書かずに、完了した銘柄のファイルだけを残して終了し、未完了の銘柄名を要約に 明記すること。書きかけ・一部ソースだけの断片を出さないこと
  8. 渡された入力スライスは 通し 1 回で読み、読み終えた範囲を読み直さないこと (長い本文を先頭から順にチャンクへ分けて読むのは 1 回に含まれる)。元の analysis_input.jsonrun_id / as_of / input_digest の照合に必要な メタデータ投影だけを読み、担当外銘柄の本文を開かないこと

Step 3: 断片のマージ

<WORKDIR>/analysis_work/ を列挙し、Step 0 の判定で流用可となった断片をすべて読む (当日書かれたものと、前営業日から持ち越した開示断片の両方)。流用可の判定は copilot-verify-analysis の PASS であり、統括が 3 値を目で突き合わせるのではない。

  • 期待する組がすべて揃っているか確認する。欠けている組があれば、その専門家を 再起動する(メッセージで結果を送り直させない。必ずファイルに書かせる)。 再起動は同じ組につき通算 1 回までで、2 回目も揃わなければ withhold で確定させる (「サブエージェントの実行上限と打ち切り」)
  • FAIL した断片、および candidates[].symbol に無い銘柄の断片は読み飛ばす (Step 0 で削除していないため、ディレクトリには残っている前提で扱う)
  • 各断片からペイロードキーだけを取り出し、銘柄ごとに news_summary / filing_analyses / screening_assessment を組み立てる
  • as_of / ac_check / filing_body_digests は作業用メタデータなので捨てる (strict 検証で hard fail する)。 一方 facts[].evidence_quote は作業用メタデータではなく契約フィールドなので、 断片の値をそのまま逐語で運ぶ(落とすと ingest でその銘柄が fail-closed になる)
  • 断片の本文は書き換えない。問題があれば Step 3.5 で再分析を依頼する
  • news が空の銘柄は news_summary: null、filings が空の銘柄は filing_analyses: []screening_assessment は全銘柄必須

断片の機械検証(自前実装しない)

断片を読んだら、マージ内容を確定する前に、まとめて機械検証する。

uv run copilot-verify-analysis <WORKDIR>/analysis_work
  • ingest(copilot-ingest-analysis)と同一の関数で、断片の strict schema、 流用の鍵(news / screening は run_id / as_of / input_digest の一致、 filings は filing_body_digests と当日の開示本文の一致)、ファイル名とペイロードの 一致、provenance、evidence_quote の逐語一致、CON-03 を検査する。契約と終了コードは references/output-schema.md の「断片の契約検証」参照
  • 同じ検査を自前のスクリプトで書き直さない。 逐語一致と CON-03 は Unicode NFKC 正規化を経て判定されるため、grep ベースの自己検査は ingest より弱くなる(Issue #132)
  • FAIL した断片は、統括が本文を書き換えるのではなく Step 3.5 の手順で該当専門家に 再分析を依頼して同じパスを上書きさせる(AC15)
  • 流用の鍵が合わない断片(別 run の news / screening、開示本文が変わった filings)と、 入力に無い銘柄の断片も FAIL として出るが、扱いは Step 0 のとおりに分かれる。前者は 流用せず再分析対象にし、後者はマージ対象から外して無視する。どちらも rm で消さない

Step 3.5: 統合レビュー(2〜3 段目、セッション本体で実施)

マージした内容を突き合わせ、以下を点検する。括弧内は references/analysis-conventions.md の AC 番号。

  • 矛盾: ニュースの示唆と開示の示唆が食い違っていないか
  • 見落とし: スクリーニングの強みが、ニュース/開示の懸念で打ち消されていないか
  • provenance 破れ: facts[].source_ids が非空か(AC6・AC10)、入力の該当銘柄に 実在する ID の部分集合か(AC6)、逐語コピーか(AC7)、複数ソースを取りこぼして いないか(AC9)、facts[].evidence_quote がその source_ids の本文(ニュースは 見出し+要約、開示は入力の text、カレンダーイベントはタイトル+要約)からの 逐語引用になっているか(AC6)。ID の部分集合性と引用の逐語一致は Step 3 の copilot-verify-analysisanalysis/validate.py の関数で照合済みなので、 統括はこの照合を書き直さない。ここで見るのは機械が見られない部分—— 複数ソースの取りこぼし(AC9)と、正しい ID を申告しつつ内容が別銘柄の 取り違えになっていないかの見立て——に絞る
  • 数値の桁: facts[].text の数値が evidence_quote の数値と桁まで整合しているか (AC16)。開示の表は多くが (in thousands) で、3,495,296 は 34億9,530万ドルである。 引用が正しくても変換だけを誤った fact は逐語一致の検査を素通りするため、単位変換を 跨ぐ数値は 1 件ずつ引用と突き合わせる。前年同期・前四半期を並べた fact は各行を 個別に確認する(1 行だけ誤る事故が実際に起きている)。ingest 側の機械検査は単位・ 通貨の付いた数値だけを対象にした警告であり、fail-closed ではない。警告が出て いないことは正しさの証明にならない
  • 入力外情報: 入力に無い企業情報・株価・決算数値が混ざっていないか(AC8)、 決定論的スコアを書き換えていないか(AC1・AC2)
  • CON-03: 断定的売買指示(AC3)・命令形(AC4)・根拠なき心理診断(AC5)
  • 叙述規約: facts に評価語や推論が混ざっていないか(AC11)、hedge があるか(AC12)、 非網羅である旨が書かれているか(AC13)、空入力を無理に埋めていないか(AC14)
  • 各専門家が返した ac_check に懸念 AC 番号が挙がっていれば、その項目を優先的に見る

深掘りが要る点があれば、該当専門家に追加分析を依頼する(2 段目、必要なら 3 段目)。 追加分析には model: opus を指定してよい。追加依頼では「違反または矛盾している AC 番号」と 「入力のどの source_id を見直すか」を具体的に書き、同じ断片ファイルを上書きさせる。 追加分析のエージェントにも 1 体あたりの上限(壁時計 15 分・ツール呼び出し 40 回)が 適用され、同じ断片への追加依頼は通算 2 回まで(既存の 2 段目・3 段目に対応する。 これは Step 3 の「欠けている組の再起動は 1 回まで」とは別枠で、内容の深掘りに対する 上限である)。打ち切られた場合、または 3 段目でも解消しない場合は、その銘柄の verdict を 保守側の skip に倒す。既にマージ済みで copilot-verify-analysis に PASS している 断片の内容はそのまま残す(この場合に落とすのは verdict であって断片ではない。断片が 無い/FAIL する場合の扱いは「サブエージェントの実行上限と打ち切り」の withhold に従う)。

統合レビュー自体はセッション本体で行う(サブエージェントに丸投げしない)。 文言を自分で書き換えて検査を通そうとしない(AC15)。

Step 3.6 / Step 3.7 の先行起動(部分並列化)

Step 3.5 → Step 3.6 → Step 3.7 を銘柄横断で直列に回すと、1 銘柄の点検が全銘柄の 追加パスを待たせる。Step 3.5 の点検(矛盾・見落とし・provenance・数値の桁・叙述規約)は 銘柄ごとに独立しており、銘柄をまたぐ判断は Step 4 の no_trade まで現れない。 そこで次の範囲に限って先行起動してよい。

  • Step 3.6 は銘柄単位でパイプライン化してよい。 全銘柄の Step 3.5 を終えるのを 待たず、暫定的に proceed に傾いた銘柄から反証エージェントを起動する。複数銘柄が 同時に確定したら同一メッセージ内でまとめて並列起動する
  • Step 3.5 に対する完全先行はできない。 Step 3.6 の対象は暫定 proceed であり、 その銘柄の Step 3.5 を終えなければ決まらない。暫定判定が付く前に起動しない
  • Step 3.7 は銘柄単位で先行できない。 対象が「材料不在型 skip のうち総合スコア 上位 3 銘柄」であり、全銘柄の暫定判定が出そろうまで上位 3 銘柄が確定しないため、 起動は暫定判定が全銘柄分そろってから行う。ただしその時点で Step 3.6 のエージェントが まだ走っていてよく、完了を待たずに起動する(既存の「両パスを同一メッセージ内で 並列起動してよい」規定を、時間差での同時進行にも広げたもの)
  • 先行起動してよいのは入力が確定した銘柄だけ。 その銘柄の断片が Step 3 の copilot-verify-analysis に PASS しており、かつ Step 3.5 の点検で再分析(断片の 上書き)を依頼しないと決まっていること。再分析を依頼した銘柄は、上書き後の断片で Step 3.5 をやり直してから起動する(古い断片で反証・対称を組ませない)
  • 同一銘柄に Step 3.6 と Step 3.7 を同時に当てない。 両パスの対象は排他であり、 対称パスへの応答の結果 proceed が妥当になった銘柄だけが、その後で Step 3.6 を 通る(Step 3.7 の応答義務)
  • スライスを作り直さない。 Step 2 で作った入力スライスがその銘柄単独で 構成されていれば Step 3.6 / Step 3.7 でもそのまま再利用する。複数銘柄をまとめた スライスは他銘柄の混入禁止に触れるため再利用せず、当該銘柄だけのスライスを作る
  • Step 3.6 / Step 3.7 のエージェントにも「サブエージェントの実行上限と打ち切り」の 1 体あたりの上限(壁時計 15 分・ツール呼び出し 40 回)を適用し、超えたら TaskStop で打ち切る。打ち切られた銘柄は保守側に倒す — 反証を通せなかった暫定 proceedskip にし、対称検査を通せなかった暫定 skip はそのまま skip を維持する
  • 先行起動は順序の前倒しであって検査の省略ではない。 Step 4 の verdict 確定前に、 対象銘柄すべてについて Step 3.6 / Step 3.7 の応答義務を果たす

Step 3.6: 反証パス(adversarial review)

Step 3.5 を終えた時点で 暫定的に proceed に傾いている銘柄だけを対象に、 反証(bear case)を立てさせる。

  • 暫定 proceed 候補がゼロなら、このパスは丸ごとスキップする(コストガード)。 スキップした旨は Step 7 で報告する
  • 対象銘柄ごとに Agent ツール(model: opus)で 1 体を起動する。 同一メッセージ内で並列起動してよい。全銘柄の Step 3.5 完了を待たず、暫定判定が 付いた銘柄から先行起動してよい(Step 3.5 の「Step 3.6 / Step 3.7 の先行起動」)

反証エージェントへ渡す入力

  • 当該銘柄の <WORKDIR>/analysis_work/news-<SYMBOL>.json / filings-<SYMBOL>.json / screening-<SYMBOL>.json絶対パス(存在するものだけ)
  • analysis_input.json の当該銘柄スライス(score_breakdown / risk_constraints / prior_verdicts / news / filings と run-wide context)の絶対パス。スライスの作り方と 不変条件は Step 2 と同じ(逐語コピー・他銘柄の混入禁止)。Step 2 のスライスが当該銘柄 単独で構成されていれば作り直さず再利用する
  • 供給されたデータのみから結論を出すこと。新規のデータ取得・Web 検索・ 事前知識による補完をしないこと」(AC8)
  • 「作業用の一時ファイルは <SCRATCHDIR> 配下にだけ作り、削除しないこと (rm を実行しないこと)」(「一時ファイルと後始末」参照)
  • 「壁時計 15 分・ツール呼び出し 40 回を上限とし、渡されたスライスは通し 1 回で読み (読み終えた範囲を読み直さない)、元の analysis_input.json 全件を読まないこと」 (「サブエージェントの実行上限と打ち切り」参照)

反証エージェントのタスク

供給データの範囲で最も強い bear case を組み立て、次の 3 点を返す。

  1. proceed を支えるポジティブ材料のうち、出典が弱いもの・単一ソースにしか 支えられていないものの指摘(該当する source_id を明示する)
  2. 見落とされているリスクの指摘(断片間の矛盾、開示本文に記載されたリスク、 直近に控えるイベント、リスク制約との緊張など)
  3. この反証を覆すには何が必要か」の明示(入力のどこを見直せば、 何が確認できれば反証が弱まるのか)

リスク要因(Item 1A)の新規性は論点として立てない(Issue #127)。10-Q の Item 1A は 前回提出から重要な変更が無ければ 10-K への参照援用だけで済ませてよく、比較対象となる 10-K 本文は入力に含まれない。よって新規性は現在の入力範囲では判定不能として扱い、 反証側でも判定しない。「新規記載があるか」「文言が強まったか」を検査項目にせず、 「判定不能」「比較対象が無い」といった文言も反証ポイントとして書かない。開示に実質本文が あれば、新規性ではなくそこに書かれているリスクの内容そのものを bear case の材料にする。 いずれの場合も「新規リスクなし」「リスクは変化していない」とは書かない(AC8)。

  • 返答は要約のみ。ファイルを書かせない。反証パスの出力は analysis_work/ の 断片契約に含めず、analysis_work/ にも analysis_result.json にも置かない
  • 反証側も CON-03 の言語規律に従う(断定的売買指示・命令形を使わない。AC3〜AC5)

セッション本体の応答義務

返ってきた反証ポイントに、1 件ずつ明示的に応答してから Step 4 の verdict を確定する。

  • 各ポイントについて「棄却(その理由)」か「受容(verdict へどう反映したか)」の どちらかを決める。黙って無視しない
  • 実質的な矛盾が解消できない場合は保守側(skip)に倒す
  • 反証を受けて断片そのものに修正が要ると判明した場合は、統括が本文を書き換えず、 Step 3.5 の手順で該当専門家に再分析を依頼して断片を上書きさせる

Step 3.7: 対称レビュー(材料不在型 skip の検査)

Step 3.6 の反証パスは暫定的に proceed に傾いている銘柄だけを追加検査する。 skip はこの検査を一度も受けず、「実質的な矛盾が解消できない場合は保守側(skip)に 倒す」規範(Step 3.6・Step 4)と重なって、proceed だけが追加の1段をくぐらなければ 生き残れない非対称なラチェット構造になる。このステップは保守側に倒す基本方針は 変えずskip の理由が「材料があること」ではなく「材料が見当たらないこと」で 構成されている銘柄に限り、対称の検査を当てる。

材料不在型 skip の判定規則

暫定 verdict.reasons のうち、次の (a) または (b) に該当する reason が**過半(半数超)**を 占める銘柄が対象になる。ちょうど半数(例: 4件中2件)は過半ではないため対象外。 reasonsが1件のみでそれが(a)か(b)なら、1/1は過半として対象になる。

  • (a) 当該事実を確認するための本文・章・フォームが入力に存在しないことを述べる reason: 章が入力に無い、coverage が partial で中間が未分析、当該フォーム自体が 入力に含まれない、固有材料が限定的で確認できない、判定不能。 含めないもの: 入力に存在する事実に対する解釈上の注意喚起(例: 「+75.6%は 買収の連結効果を含む可能性があり区別して読む必要がある」は、買収完了日が入力から 読み取れるため (a) ではない)
  • (b) source_ids が空で、決定論的制約だけを述べる定型 reason: not_calculable / stop_distance_pct 不明 / Exposure Ceiling: REDUCE_ONLY

実行上限による打ち切りで withhold した銘柄は対象外(「サブエージェントの実行上限と 打ち切り」)。不足しているのは入力ではなく分析であり、対称エージェントへ供給できる 材料そのものが欠けているため、追加の 1 段を当てても判断材料が増えない。

対象は該当銘柄のうち**score_breakdown の総合スコア上位3銘柄まで**。0件ならこの パスは丸ごとスキップする(Step 3.6 と同じコストガード)。スキップした旨は Step 7 で報告する。4件以上該当する場合は上位3銘柄だけを対象にし、見送った銘柄と その件数を Step 7 で報告する。

対称エージェントへ渡す入力

Step 3.6 の反証エージェントと同一の入力契約を使う: 当該銘柄の <WORKDIR>/analysis_work/news-<SYMBOL>.json / filings-<SYMBOL>.json / screening-<SYMBOL>.json の絶対パス(存在するものだけ)、analysis_input.json の 当該銘柄スライスの絶対パス(逐語コピー・他銘柄の混入禁止)、「供給されたデータのみ から結論を出すこと。新規のデータ取得・Web検索・事前知識による補完をしないこと」 (AC8)、一時ファイルは <SCRATCHDIR> 配下にのみ作り rm しないこと、壁時計 15 分・ ツール呼び出し 40 回の上限と、スライスを通し 1 回で読み読み終えた範囲を読み直さない規律 (「サブエージェントの実行上限と打ち切り」)。

  • 対象銘柄ごとに Agent ツール(model: opus)で1体を起動する。暫定 proceed 候補が 同時に存在し Step 3.6 も実施する場合、同一メッセージ内で両パスを並列起動して よい(Boundary: 両方ある場合、既存の各パスの上限枠内で同時に走らせる)。先行起動した Step 3.6 のエージェントがまだ走っていても、その完了を待たずに起動してよい (Step 3.5 の「Step 3.6 / Step 3.7 の先行起動」)

対称エージェントのタスク

供給データの範囲で最も強い bull case を組み立て、次の3点を返す。

  1. その skip 理由のうち「材料の不在」に依存している箇所の特定
  2. 供給データ内に存在するが暫定判断に反映されていない肯定材料の指摘(該当する source_id を明示する)
  3. この skip を維持するには何が確認できれば足りるか」の明示
  • 返答は要約のみ。ファイルを書かせない。対称パスの出力は Step 3.6 の反証パスと 同じく analysis_work/ の断片契約に含めず、analysis_work/ にも analysis_result.json にも置かない
  • 対称エージェントも CON-03 の言語規律に従う(断定的売買指示・命令形を使わない。AC3〜AC5)

セッション本体の応答義務

返ってきた3点に、1件ずつ明示的に応答してから Step 4 の verdict を確定する (Step 3.6 と同じ形式)。

  • 各点について「棄却(その理由)」か「受容(verdict へどう反映したか)」のどちらかを 決める。黙って無視しない
  • 実質的な矛盾が解消できない場合は保守側(skip)に倒す(Step 3.6・Step 4・ 無人実行時の方針と同じ規範。判断が割れても skip を維持する)
  • 応答の結果 proceed が妥当と判断された場合は、確定前に Step 3.6 の反証パスを 通す(対称パスを通過しただけで反証を免除しない)
  • skip を維持する場合、reasons[].text の少なくとも1件に、この skip が 「確認できる材料が入力に無いことに基づく見送りであり、特定されたリスクに基づく ものではない」旨を明記する

Step 4: verdict 決定

銘柄ごとに proceed / skip を決める。Step 3.6 / Step 3.7 を実施した銘柄は、 それぞれの検査ポイントへの応答を済ませてから確定する。

  • skip(見送り推奨)にする典型: 開示本文に重大なリスク記載がある(記載の新規性は Step 3.6 と同じく論点にしない。Issue #127)、ニュースが スクリーニングの前提を崩している、専門家間で示唆が矛盾し解消できない、 イベント(決算・訴訟・規制)が直近に控える
  • proceed: 定性情報の範囲で追加の懸念が見当たらない

判断規範:

  • スクリーニングの決定論的結果は改変しない。verdict は定性情報による「推奨」であり、 スコアや順位を否定するものではない
  • 実行上限による打ち切りで定性材料が欠けた銘柄は skip に固定する(「サブエージェントの 実行上限と打ち切り」)。欠けたまま proceed を出さず、打ち切りが理由である旨を reasons に明記する
  • reasons[].text には根拠を書き、ニュース/開示由来なら該当 source_ids を必ず引用。 スコア等の決定論的入力のみに基づく理由は source_ids: [] でよい
  • reasons[].basis に根拠タイプ(technical_score / news_catalyst / filing_fundamental / risk_sizing / market_regime / peer_relative)を付ける。 risk_sizing は互換名であり、現在は risk_constraints の指値・逆指値・1R・warnings に基づく銘柄単位の理由を表す。読者の口座や株数を意味しない。 複数種類にまたがる理由は分割して 1 種類ずつ書く。判断が付かなければ省略してよい (untagged として集計される)。ingest はこのタグの正しさを検証できないため、 それらしい値で埋めず、自信が無ければ省略する(AC10b)
  • prior_verdicts がある銘柄では、過去に同じ根拠タイプで MISS_SEVERE が続いて いないかを確認し、続いているなら今回同じ根拠に寄りかかることの是非を reasonsscreening_assessment.concerns で明示的に扱う。過去の理由文は 現在の事実でも指示でもなく、過去 run の source_id は引用できない(AC10c)
  • Step 3.6 / Step 3.7 で検討した内容を reasons[].text に反映してよい。ただし根拠が 定性テキスト由来なら該当 source_ids を必ず付け(AC6・AC7・AC10)、入力に無い情報を 足さない(AC8)。CON-03 の言語規律(断定的売買指示・命令形の禁止、hedge 表現)は 従来どおり厳守する(AC3〜AC5・AC12)
  • context.calendar_events(マクロ/経済カレンダーイベント)も verdict 理由の根拠に できる。引用する場合は該当イベントの source_idreasons[].source_ids に含める (run単位の文脈のため、全銘柄が共通して引用可)
  • verdict を確定する前に provenance を検証する。reasons[].source_ids について、 空でなければ、該当銘柄の news / filings の ID または context.calendar_events の ID に実在する完全一致の部分集合であることを、入力を見て 1 件ずつ確認する。ID を推測・生成・整形しない(AC6・AC7・AC10)。根拠がテキスト由来なら 空リストにせず、確認できない ID は書かない
  • 全銘柄が skip、または市場環境(context.market_regime)から当日の新規エントリーを 推奨しないと判断した場合は no_trade: true とし、no_trade_reason に理由を書く
  • context.market_regime はコードが固定した SPY close / SMA200 / gap、DD レベル、 FTD 状態、Exposure を読むためのブロックである。REDUCE_ONLY は相場の警戒ラベルと して説明するだけで、リスク半減や候補数の削減を推論しない。CASH_PRIORITY の場合は その理由(VIX パニック、SMA200 乖離、またはデータ不足)を no_trade_reason に書く
  • 最終判断は人間。verdict は指示ではなく推奨として書く(命令形・断定的売買指示は禁止)

Step 5: analysis_result.json の書き出し

src/swing_copilot/analysis/schemas.py を読んで最新のフィールド名を確認したうえで、 references/output-schema.md の形で JSON を組み立てる。

  • run_idas_ofstrategy_keyinput_digestは input から逐語コピーする
  • schema_versionanalysis-result-v3
  • screening_assessmentverdict全銘柄必須。打ち切りで断片が無い銘柄も symbol 集合から落とさず、「サブエージェントの実行上限と打ち切り」の withhold の 書き方(最小限の screening_assessmentskip 固定)に従う
  • symbols[].symbol は重複させず、input の candidates[].symbol完全一致させる
  • no_trade: true なら非空白の no_trade_reason を書き、false なら必ず null にする
  • 出力先は <WORKDIR>/analysis_result.jsonanalysis_input.json と同じディレクトリ)
  • input に無い symbol を追加しない。input にある symbol を落とさない
  • analysis_work/ 由来のrun_id / as_of / input_digest / ac_checkを result へ持ち込まない(未知フィールドは hard fail)
  • 書き出し直前に、全 verdict.reasons[].source_ids をもう一度走査する。空でない各 ID は、 その symbol の入力 news / filings または run-wide context.calendar_events に 実在する完全一致の ID でなければならない。テキスト由来の理由に空リストを使わず、 決定論的入力だけの理由に限り空リストを許可する

書き出したら、ingest を走らせる前に dry-run で検証する(自前の検証スクリプトを 書かない)。

uv run copilot-verify-analysis <analysis_result.json の絶対パ>
  • JSON の妥当性、strict schema、input との identity 一致(run_id / as_of / strategy_key / input_digest)、symbol 集合の完全一致、provenance、 evidence_quote の逐語一致、CON-03 を、ingest と同一の関数で検査する。 レポートは書かない
  • 終了コード 0 なら Step 6 へ進む。1 の場合、FAIL 行が縮退または hard fail の 理由を示す。文言を書き換えて検査を通そうとしない(AC15)。 断片に修正が要るなら Step 3.5 の手順で該当専門家に再分析させ、Step 3 からやり直す
  • マージ時のフィールド名の取り違え(ac_check の混入、evidence_quote の落とし)は ここで hard fail として出る。これは内容の書き換えではないので直して再実行してよい

Step 6: ingest 実行

uv run copilot-ingest-analysis <analysis_result.json の絶対パ>
# 例: uv run copilot-ingest-analysis /path/to/<WORKDIR>/analysis_result.json

<result.json|dir> を第1引数に取り、--input / --context / --log-level を 任意で指定できる(省略時は analysis_input.json / report_context.json を result ファイルと同じディレクトリから解決する)。hard fail 時は exit code 1。 正確な引数は uv run copilot-ingest-analysis --help で確認する。

検証で縮退(degraded)や error が出た場合:

  • リトライで検証を通そうとしない。 fail-closed が仕様であり、 文言を書き換えて再投入するのは規約違反にあたる(AC15)
  • 縮退した銘柄と、ログに出た違反理由(CON-03 違反か provenance 違反か スキーマ不一致か)をそのまま報告する
  • スキーマ不一致による hard fail のみ、schemas.py を読み直して フィールド名の誤りを修正して再実行してよい(内容の書き換えではないため)

Step 7: 報告

ユーザーに簡潔に報告する。

  • パイプラインの結果(候補数、対象日)
  • 銘柄ごとの verdict(proceed / skip と一行理由)
  • no_trade の有無と理由
  • ingest の検証結果(全件通過 / 縮退した銘柄と理由)
  • 最終レポートのパス
  • Step 0 で既存断片を流用した場合はその旨(流用した銘柄 × 専門家の組)
  • Step 3.6 の反証パスを実施した銘柄と、反証ポイントを棄却/受容した結論。 暫定 proceed がゼロでパスをスキップした場合はその旨
  • Step 3.7 の対称パスの対象数と、そのうち何件の verdict が変わったか。材料不在型 skip が0件でパスをスキップした場合はその旨。該当が3件を超えて上限により 見送った銘柄がある場合はその件数
  • 実行上限で打ち切ったエージェントと、その組(銘柄 × 専門家、または反証/対称)。 打ち切りにより withhold して skip を固定した銘柄。全体上限(45 分)に到達して 打ち切った場合はその旨

最終判断は人間である旨を添える。

無人実行(headless)時の方針

このスキルは平日の定時に GitHub Actions から 無人起動される運用だけを持つ (ワークフローの構成は CLAUDE.md の "Scheduled Daily Run" を参照。スケジュール 自体はこのスキルの外で管理される)。ローカルの対話セッションでこのスキルを 起動する経路は設けず、以下をすべての実行に適用する。

  • Bash の許可境界を自分で広げない。 無人起動で Bash を使える形は、 uv run copilot-dailyuv run copilot-verify-analysisuv run copilot-ingest-analysisuv run copilot-historyuv run copilot-export-slices./scripts/timebox.sh のいずれかで始まる コマンドだけである。作業ディレクトリはリポジトリルートなので、cdenvexportbashshgitpythoncatlsfindsedrmcpmvmkdirsleepdateecho や、シェル演算子・リダイレクトを 付けない。入力や設定の読み取りには Read / Glob / Grep、ファイルの作成・更新には Write / Edit を使い、許可済み Bash コマンドも前置きなしで直接呼び出す。

  • ユーザーに質問できない前提で動く。 AskUserQuestion は使えない。判断が割れる 分岐(既存 analysis_result.json の上書き可否、断片の流用可否、proceed か skip か)は 常に保守側を選ぶ — skip / withhold / 中断

  • 既存の analysis_result.json があり、再実行の明示指示が無い場合は Step 0 のルール どおり上書きしない。既存 verdict を要約して終了する

  • degraded・fail-closed 検疫・断片欠落は、既存ルールどおりリトライで検証を通そうと しない(AC15)。状況をそのまま最終報告に書いて終了する

  • 居残りサブエージェントは必ず打ち切る。無人実行では待ち続けることが最も高い コストであり(実測で 1 体が 52 分居残り、analysis_result.json 未生成のまま 終わった日がある)、打ち切って withhold で先へ進むことがここでの保守側の選択に あたる(「サブエージェントの実行上限と打ち切り」)

  • 起動中のサブエージェントが残っている間は、ツール呼び出しを含まないターンを 返さない。 SDK 起動(GitHub Actions)では最終応答がそのままセッションの終わりになる。 テキストだけのターンを返した時点で、まだ走っているサブエージェントごと実行が 終了する。2026-08-19 の live run がこれに該当し、30 断片中 2 断片・ analysis_result.json 未生成・headless_note.md 未生成のまま job は success で 終わった。したがって待つ必要があるときは、待つこと自体をツール呼び出しにする。 背景実行のウォッチャ(run_in_background)は即座に戻るので、これは待ちにならない。 headless で待ちを保証する形は次の 1 つだけである:

    # 前景実行(run_in_background を付けない)。Bash ツールの timeout を明示する
    ./scripts/timebox.sh 300

    Bash ツールの timeout 上限は 600 秒(既定 120 秒)なので、1 波の締切(15 分)は この前景呼び出しを複数回に刻んで満たす。呼び出しが返るたびに未完了エージェントを 確認し、締切に達していれば TaskStop、達していなければもう 1 回刻む。ツール呼び出しの 最中にセッションが終わることはないので、これが「テキストだけのターンを返さない」の 実体になる。背景ウォッチャは締切の通知を得る手段であって、待ちの保証ではない

  • headless_note.md は Step 2 の最初の波を起動する前に一度書き、以降は更新して いく。 最後にまとめて書く運用では、途中でセッションが終わったときに何も残らない (上記 live run では 1 行も残らなかった)。最初の版は、実行日時・run_id / as_of<WORKDIR>・起動した組の一覧・ウォッチャを起動できたか(できなければ 終了コードとメッセージ)だけでよい

  • 上記のメモは最終的に、どこまで進んだか、縮退・欠落・打ち切りの理由、次に人間が 確認すべき点まで含める。これは人間向けのメモであり、analysis_work/ の断片契約にも analysis_result.json にも含めない。 ユーザーは翌朝 reports/latest.md とログ、必要ならこのメモを確認する

  • 中断して終了する場合も、Step 7 の報告項目は分かる範囲で必ず出力する

禁止事項

  • スクリーニングのスコア・ランキング・リスク制約の再計算や書き換え(AC1)
  • 入力に無い情報の補完(事前知識による企業情報・株価・決算数値の追加)(AC8)
  • 検証を通すための文言の書き換え・再投入(AC15)
  • 断定的売買指示、命令形、根拠なき心理・行動診断(AC3〜AC5)
  • 専門家が書いた analysis_work/ 断片の本文を統括が直接書き換えること (修正が要るなら該当専門家に再分析を依頼し、断片を上書きさせる)
  • 反証パス(Step 3.6)・対称パス(Step 3.7)の出力をファイル化して analysis_work/analysis_result.json に混ぜること(いずれも verdict の材料であり出力契約ではない)
  • ユーザーが再実行を求めていないのに既存の analysis_result.json を上書きすること
  • 一時ファイルの掃除目的で rm を実行すること(統括・サブエージェントとも。 「一時ファイルと後始末」参照)
  • <WORKDIR><SCRATCHDIR> 以外のリポジトリ配下に作業用の一時ファイル (スライス、抽出テキスト等)を作ること
  • 断片や analysis_result.json の契約検証を自前のスクリプトで実装すること (copilot-verify-analysis を使う。Issue #132)
  • 実行上限に達したサブエージェントを待ち続けること、および「あと少しで終わりそう」を 理由に打ち切りを先送りすること(「サブエージェントの実行上限と打ち切り」)
  • 起動中のサブエージェントが残っている状態で、ツール呼び出しを含まないターンを 返すこと(無人実行ではそこでセッションごと終了する。「無人実行(headless)時の方針」)
  • 打ち切り・上限超過で未完了になった組を「分析済み」として扱うこと(書きかけ断片の マージ、統括による本文の代筆、欠けたままの proceed
  • src/, tests/, docs/ の編集(このスキルは分析実行であり実装変更ではない)

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/tomada1114-swing-copilot-swing-daily/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

tomada1114-swing-copilot-swing-daily.ocm.jsonjson
{
  "ocm": "1",
  "id": "tomada1114-swing-copilot-swing-daily",
  "kind": "skill",
  "name": "swing-daily",
  "description": "Run the end-to-end daily swing-trading analysis loop. Executes `copilot-daily` for the deterministic pipeline, fans out news/filings/screening interpretation to parallel expert subagents, reconciles their findings, decides a per-symbol proceed/skip verdict, writes analysis_result.json, and re-renders the final report via `copilot-ingest-analysis`. This skill is invoked only by the GitHub Actions `swing-daily.yml` workflow; the qualitative daily phase is not a local or interactive execution path.",
  "publisher": "tomada1114",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "github"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Run the end-to-end daily swing-trading analysis loop. Executes `copilot-daily` for the deterministic pipeline, fans out news/filings/screening interpretation to parallel expert subagents, reconciles their findings, decides a per-symbol proceed/skip verdict, writes analysis_result.json, and re-renders the final report via `copilot-ingest-analysis`. This skill is invoked only by the GitHub Actions `swing-daily.yml` workflow; the qualitative daily phase is not a local or interactive execution path."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "github",
      "repository": "https://github.com/tomada1114/swing-copilot",
      "path": ".claude/skills/swing-daily/SKILL.md",
      "ref": "84ad92d57825f6bd1b6c2be987443844f32efd00",
      "url": "https://github.com/tomada1114/swing-copilot/blob/84ad92d57825f6bd1b6c2be987443844f32efd00/.claude/skills/swing-daily/SKILL.md",
      "key": "tomada1114/swing-copilot/.claude/skills/swing-daily/SKILL.md"
    }
  },
  "instructions": "# 日次分析ワークフロー(統括)\n\n機械処理は Python、定性判断はこのスキル、最終判断は人間。\n決定論的な出力(スコア・ランキング・リスク制約)は**絶対に書き換えない**。\n\n## 実行前提(GitHub Actions のみ)\n\nこのスキルの起動経路は `.github/workflows/swing-daily.yml` の GitHub Actions\njob だけである。ローカルの対話セッションから `swing-daily` を実行する運用は\n採らない。`copilot-daily` はローカルで決定論的なレポート入力を作れるが、\nニュース・開示・スクリーニングの定性分析と ingest は CI の job が担当する。\n\n入力スライスなどの作業用ファイルは、checkout 直下の\n`<REPO_ROOT>/.swing-daily-scratch/`(以下 `<SCRATCHDIR>`)にだけ置く。\nこのディレクトリは `.gitignore` 対象で、`reports/` の `<WORKDIR>` とは別の場所である。\n\n作業前に必ず読む:\n\n- [references/analysis-conventions.md](references/analysis-conventions.md) — AC1〜AC16 の共通規約(CON-03・provenan",
  "cost": {
    "context_tokens": 9249
  }
}

Fetch it by URL: GET /api/v1/registry/tomada1114-swing-copilot-swing-daily/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.