Changelog

NexusCore のプロジェクト固有変更履歴。 形式は Keep a Changelog に準拠。


[2026-10-08] - Multi-LLM consensus review を開発サイクルへ配線(L143)+ SKILL.md乖離検知(L141=A)

バックログL143(ふくけい指示・2026-09-23起票)。設計判断はふくけい承認済み (L141=A乖離検知のみ / 配線=案1初回レビュー差し替え・2機構成 glm:glm-5.3+minimax:MiniMax-M3)。 本番適用(同日追記): NEXUS_REVIEW_MODE 未設定時の default を single→multi へ切替 (rollback: NEXUS_REVIEW_MODE=single・.env.template に記載)。注意: 夜間harness (harness_cli)はエージェントループで run_review_phase を通らないため、multi が効くのは Orchestrator パイプライン(main_cli 等)の実行経路。

Added

  • NEXUS_REVIEW_MODE=multi 環境変数で初回レビューを Multi-LLM consensus へ差し替え(defaultはsingle=現行互換)
    • phase_runner_mixin.py: _run_multi_llm_review()(consensus実行・失敗過半/import失敗/例外時は guardian へ fallback)+ _consensus_to_review_data()(変換規則: max_severity=high→REJECT・それ以外 APPROVE)
    • consensus の初回 REJECT 後の再レビューループ・policy ゲートは従来 guardian を維持
    • NEXUS_MULTI_REVIEW_MODELS でモデル上書き可(default glm:glm-5.3,minimax:MiniMax-M3)
  • ConsensusResult.max_severity 追加(_merge_consensus が ok レビューの最大深刻度を集約)
  • nexuscore.scripts.check_skill_drift: SKILL.md 乖離検知チェッカー(検知のみ・同期しない・drift時 exit 1・--update-baseline で再記録)。baseline: ~/.claude/state/nexuscore-skill-baseline/multi_llm_review_SKILL.md.sha256
  • テスト: tests/core/test_review_phase_multi_llm.py(13件)+ tests/scripts/test_check_skill_drift.py(7件)

[2026-09-28] - check_gate_slo.py 誤投入防止フィルタ(旧データROLLBACK誤判定の解消)

09-27 SLO判定セッションで発見された脆弱性(旧300秒データ投入→fail条件hit→ROLLBACK誤判定)のP2対応(L1086)。

Changed(nexuscore-bench側・aa5fe08)

  • scripts/check_gate_slo.py: filter_runs() 新設 — レコード内 timeout_sec(実適用ゲート値)と ts(実行時刻)で「復帰後600秒ゲートrun」のみ機械受付(旧ゲート/復帰前600秒/判定不能を除外+件数報告・欠落はfail-safe除外)
  • test_gate_slo.py 新規 — TDD 8テスト(旧データ混入でもROLLBACK誤判定が出ない回帰込み)
  • 検証: pytest 8+15 passed・実機3シナリオ(旧300秒データ→EXIT=2 INSUFFICIENT_DATA〔修正前 EXIT=1〕・ ワイルドカード全投入→旧44+復帰前26を機械除外・--seed モード正常)

[2026-09-26] - nexuscore-bench easy タイムアウトを600秒へ復帰(カナリアSLO監視付き)

プラン①′検証合格(timed_out 0/12・最長579.4秒)とMLR 5機一致の条件付き推奨により、 09-24の暫定措置(900秒)を解消して600秒ゲートへ復帰。

Changed(nexuscore-bench側・47301f8)

  • runner.py TIMEOUTS: easy 900→600秒(改訂履歴300→600→900→600復帰をコメント明記)
  • scripts/check_gate_slo.py 新規 — カナリアSLO監視(窓30run・ロールバック条件〔580秒超率≥5% or timeout率≥3%〕+fail条件事前固定〔累積50runでtimed_out≥1 or 580秒超≥3件〕)
    • 動作確認: 正常12run→INSUFFICIENT_DATA/EXIT=2・旧e900データ→ROLLBACK/EXIT=1
  • spec §3に改訂履歴と復帰条件を追記(test_runner 15 passed)

[2026-09-26] - プラン①′ベンチ検証: fail条件合格(timed_out 0/12・最長579秒)

nexuscore-bench easy tier 12run(phase1_easy_n10_p1prime_r1-r4.jsonl)で検証。

検証結果

  • fail条件①②合格: 完走率100%(timed_out 0/12・旧900秒ゲートでは8/12=67% kill)・遅延run 0件(最長579.4秒≤700秒)
  • 新機構の発動実測: read=1で失敗チェーンを240.4-242.3秒で打ち切り(旧設計360秒超・v3.1仮置き245秒を実測一致)・Run予算fail-fast 11/12run発動でもkill 0
  • 品質10/12(2件はfailure_kind=task・予算因果はn不足で判定不能)・timeout_type=unknown分類改善余地

[2026-09-26] - 方向1v3.1 プラン①′実装: ReadTimeout戦略再設計+Run全体タイムアウト予算

背景: Step 0計測(57run解析・2026-09-25/26)で timeoutはtest_generate/debugging呼出に集中 (独立型・連鎖しない)と確定。per-call retry短縮とrun予算の組合せを実装。

Added

  • llm/run_budget.py 新規 — Run全体の I/O タイムアウト予算(既定450秒・env NEXUS_RUN_IO_BUDGET_SEC)・消費>=80%で新規呼出を fail-fast(RunBudgetExhausted)。 orchestratorのrun開始時(orchestrator.py)に reset_run_budget() を配線
  • 構造化タイムアウトログ(mm#8): event=llm_timeout timeout_type=... elapsed_sec=... budget_remaining_sec=... provider=... model=...

Changed

  • http_client.py の urllib3 Retry再設計: read=1(ReadTimeoutは2試行でfail-fast・ 最悪約245秒=旧3試行の360秒超から圧縮)・backoff_factor 1→2(上限30秒)・ 429はRetry-After尊重・429以外の4xxはretry対象外(即raise)
  • openai_compat.py(GLM/MiniMax/DeepSeek/Moonshot共通基底): executeと _call_http_tool(tool呼出経路・self-inspectで発見した配線漏れ)の両方で 予算チェック+消費を配線・RunBudgetExhausted は stub fallbackに置き換えない契約

Tests

  • tests/llm/test_run_budget.py 16件・tests/llm/test_openai_compat_budget.py 4件・ http_client再設計分3件を追加。全スイート 5352 passed(+35)・mypy Success

[2026-09-26] - nexuscore-bench Step 0計測 MLR 2ラウンド完了: 連鎖判定が「独立型寄り」へ確定

背景: 09-25のStep 0計測成果物を5機×2ラウンドのマルチLLMレビュー(計57指摘・採用23)で検証。

Fixed(nexuscore-bench側・8cc642e+82275d4)

  • retry帰属試行が連鎖判定の系列から除外されていた自己矛盾を修復(agent retryは「Selecting model」行を 再出力しないため帰属先を失っていた)→ 判定が「連鎖型寄り」→「独立型寄り」へ反転確定 (P(after)=1/15=6.7% vs base 7.2%・二項p=0.659・timeoutは連鎖しない)
  • output_tokens×duration相関を正式実装(r=0.517)・rt_incl二重カウント分岐バグ修復
  • 二項検定+Wilson CI+閾値感度分析を追加・base分母を確定/未決着込みで併記

主な発見(最終)

  • timeout hotspotは不変: test_generate fail率72.7%(未決着込み51.6%)・debugging 20.5%
  • v3.1のtimeout短縮撤回は維持・連鎖性を根拠にしたretry設計は不採用確定

[2026-09-25] - nexuscore-bench Step 0計測: ReadTimeout連鎖の性質を57run解析で特定

背景: 方向1(retry戦略)v3.1の実装前に、or#9のStep 0計測(連鎖型/独立型判定・prompt長bin別・Pearson相関)を nexuscore-bench 側の既存57runログ(n≥30達成)で実施。

Added(nexuscore-bench側・55c4aa6+819bcd1)

  • nexuscore-bench/scripts/step0_readtimeout_analysis.py — NPE AUDIT LOG+urllib3ログ行の解析スクリプト (パーサ検証: grep突合57run不一致0)
  • nexuscore-bench/results/step0_readtimeout_analysis.{json,md} — 計測成果物

主な発見

  • timeoutはtest_generate(fail率84.2%)とdebugging(25.8%)に集中 — 他の13 task_type はfail 0
  • 連鎖型寄り: P(timeout 直前timeout)=13.3% vs base 6.5%・同一call再試行限定22.2%(n=15・予備的)
  • prompt長は無相関(r=-0.092)・output生成長が支配(r=0.480)→ timeout 120→60秒短縮撤回のv3.1判断を補強
  • v3.1の「prompt長bin別」指標は失敗callのtokens非観測により推定アーチファクト → task_type別fail率へ実質置換を提案

[2026-09-24] - Planning phase 早期失敗(MiniMax JSON+余分テキスト応答)の是正

背景: nexuscore-bench n≥10検証 round2 で easy-01/02 が 70-108秒で exit=1。 ログ精読の結果、plan_generate(MiniMax-M3)が「JSON本体+前置き/後続テキスト」を 返すと base_agent の厳格 json.loads 事前検査が InvalidModelOutputError を投げ、 3リトライ全滅→Planning phase 中断→run 全体失敗していた(当日の fixverify run1 も同型)。

Fixed

  • base_agent.py: as_json=True の事前検査を抽出許容に変更。厳格パース失敗時も sanitize_json_like(既存ユーティリティ・最長 {…}/[…] 抽出)で dict/list が取れれば 有効とみなし生文字列を下流へ渡す。フェンス囲みJSONも許容。
  • planner_agent.py: JSONデコード失敗時の except 句で sanitizer 復元を試行し、 計画検証を通れば fallback(ヒューリスティック計画)でなく LLM の実プランを採用。

Tests

  • tests/agents/test_base_agent.py に2件(後続テキスト許容・フェンス囲み許容)、 tests/agents/test_planner_agent.py に1件(後続テキストからの復元)追加。 全スイート 5317 passed(+3)。

[2026-09-23] - CoderAgent の「書けるが、分けられない」を是正

背景: nexuscore-bench easy tier の実測で、お題全文(テスト作成指示を含む)を task_description に含める実装のため、指示に忠実なモデル(glm-5.3)が 実装ファイル内にテストコードを同居させ、隠しテストが全滅した。

Fixed

  • CoderAgent に実装スコープ検査 _validate_impl_scope を追加(機械防御・B案)。 def test_* 定義・import pytest / from pytest import ...・自モジュール self-import を AST で検出し不合格→既存 RETRY 経路で再生成させる。 _validate_code / implement_code にオプション引数 module_name を追加 (後方互換・未指定時は self-import チェックのみスキップ)。
  • _generate_one_file の task_description に「テストを書かない」指示を追記 (プロンプト層防御・A案)。生成対象ファイルの stem を module_name として coder へ渡すよう変更。

Tests

  • tests/agents/test_coder_agent_ast.py に7件追加(test関数/pytest import/self-import/ 偽陽性ガード/RETRY経路統合)・tests/core/test_orchestrator_comprehensive.py に2件追加 (「テストを書かない」指示注入・module_name 引渡)。全スイート 5314 passed。

[2026-09-23] - LLM APIキー5本の失効を是正 + 外部ベンチマーク初実測

背景: nexuscore-bench Phase 1 の初実測で Planning が必ず落ちた。真因は .env の GEMINI_API_KEY が失効(400 API_KEY_INVALID)していたこと。 調べると .env は ~/.secrets.env(正典)から全面的にドリフトしていた。

Fixed

  • LLM APIキー5本を ~/.secrets.env から同期(値は記録に残さずsha256先頭8桁で照合)。 GEMINI_API_KEY(400 INVALID → 200・50モデル取得)/ GLM_API_KEY(401 → 200)/ MINIMAX_API_KEY / OPENAI_API_KEY / DEEPSEEK_API_KEY。 plan_generate / requirement / code_review の primary が Gemini のため、 Gemini 失効だけで Planning が必ず失敗する構造だった。
  • GLM_MODEL を glm-5.2 → glm-5.3-flash へ更新(両方とも実在は確認済み・200)。 バックアップ: .env.bak.20260923-073056 / .env.bak.20260923-074142。 ※ 2026-07-30 の「デッドキー是正」に続く2回目の同型事故。

Changed — LLM構成を2LLM(GLM + MiniMax)へ再編

方針: 契約中のプロバイダは GLM と MiniMax のみ。実測で OpenAI は credit_balance_exhausted(HTTP 429)、Gemini/DeepSeek は応答するが対象外。

  • Gemini を全経路から除去(llm/task_model_map.py): code_review / plan_generate / requirement の primary を gemini_secondary → minimax_analytical、test_generate の secondary からも削除。 実測: 全33タスクで primary 方針外=0件 / fallbacks 方針外=0件。
  • GLM 内でモデルを使い分け(llm/llm_profiles.py): glm_strict → glm-5.3(重要: 生成・リファクタ・デバッグ・自己修復・設計)/ glm_default → glm-5.3-flash(軽量: 説明・テスト雛形・分類)。 従来は両プロファイルとも glm-5.2 で使い分けが成立していなかった。
  • code_generate / code_refactor を glm_default → glm_strict へ昇格。
  • .env の GLM_MODEL を無効化(コメントアウト)。 providers/openai_compat.py:36 の os.getenv(f"{provider_name.upper()}_MODEL") は profile より優先されるため、設定されていると全GLMタスクが同一モデルへ潰れ、 上記の使い分けが一切効かなくなる。

Changed — テスト契約の更新(旧構成をアサートしていた6件)

  • test_gemini_primary_restricted_to_3_core_tasks(Gemini を3タスクに制限)を test_no_offpolicy_provider_anywhere(primary/secondary/fallback のどこにも 契約外プロバイダが現れない)へ置換。制限から全面禁止へ契約を強化した。
  • 新設: test_glm_split_strict_vs_default(GLM使い分けの固定)/ test_generation_and_review_use_different_providers(生成とレビューの別LLM維持)。
  • 回帰: llm 646 passed / workflows 53 / core+agents 1,948 / ruff 0 / mypy 274 files OK。

Measured(コード変更なし・実測のみ)

  • nexuscore-bench easy tier: 隠しテスト 3/3 通過(成果物は正しい)だが 3/3 が exit=124 で自力終了できず(read timeout 120秒×3回が難度別上限300秒と非両立)。
  • Terminal-Bench 4.0(Harbor 0.23.0): oracle 2/2 Mean 1.000 → NexusCore harness で 本番1タスク Exceptions 0 / Mean 0.000。

[2026-09-19] - Phase 5 dogfooding: cron計測パイプラインの機能不全3件を修復

背景: Go/No-Go判定書(2026-09-09)後のcron実運用9run(09-09〜09-18)を実測したところ、 有効な計測データは1件のみ(8件がトークン上限超過で「無効扱い」記録)。 通知も7日連続で届かず、無人運用の異常検知が成立していなかった。

Fixed

  • 題庫のセクション分離が機能しておらず、無人cronが書く系お題を実行していた(最も影響が大きい不具合)。 実ファイルの見出しは ## 手動用(書く系・ask承認込み・ふくけい付き添いで消化) だが、 _SECTIONS の判定キーが閉じ括弧込みの 手動用(書く系) だったためマッチせず、 書く系お題4件が全て auto へ混入していた(実測: parse_pool の manual が0件)。 無人モードは読む系registryのみ・ask無しのため「実装する」「修正する」お題は原理的に完遂不能で、 LLMが手段を探し続けてトークンを消費していた(09-11 テスト作成=456,755 / 09-12 docs修正=477,694 / 09-18 docs修正=458,502・いずれも abort: limits)。判定キーを閉じ括弧を含まない前方部分へ変更
    • 検知できなかった理由: テスト側fixture POOL が実ファイルと異なる短縮見出し ## 手動用(書く系) を 使っていた(fixture乖離)。回帰テストは修飾語付き見出しの分離検証に加え、 実題庫ファイルそのものをパースして混入ゼロを確認する方式を追加
  • Discord通知が7日連続403で全滅していた(artifacts/harness/.notify.fail に09-11〜09-18の7行)。 原因はurllib既定の Python-urllib/3.x User-AgentがDiscord/Cloudflareに弾かれていたこと (実測: 既定UA=403 / 明示UA=200・webhook URL自体は有効でドメイン新旧は無関係)。 notify_failure に明示User-Agentを付与

Changed

  • トークン上限をラッパー→CLI→loopへ結線。scripts/run_harness_task.py の HARD_TOKEN_LIMIT=200_000 は事後の「無効扱い」警告にすぎず、実際の停止点は loop.py の Limits.max_tokens=500_000 の90%=450,000だった(両者が無関係に併存)。 harness_cli に --max-tokens を新設し、ラッパーが HARD_TOKEN_LIMIT を渡すよう変更。 既定値は Limits().max_tokens と同値に固定(二重管理防止・テストで突合)
  • harness_cli.main から build_arg_parser() を抽出(既定値をテストから突合可能にするため)

Added

  • docs/harness_題庫.md に無人用(読む系)お題9題を補充(残1題・pool_low 警告発火のため)。 トークン消費抑制として対象ファイルを明示し探索範囲を限定する書き方に統一
  • テスト5件: --max-tokens の実効性(fail条件ケース)/ 既定値突合 / ラッパーからの受け渡し / 通知User-Agent / 題庫セクション分離(fixture + 実ファイル)

検証

  • pytest tests/harness/: 244 passed(PYTEST_EXIT=0)
  • pytest tests/(全体): 5279 passed, 178 skipped, 26 xfailed(FULL_PYTEST_EXIT=0・146.17s)
  • ruff check: RUFF_EXIT=0 / mypy src/nexuscore/cli/harness_cli.py: MYPY_EXIT=0
  • Discord実投稿1件で疎通確認(.notify.fail が7行のまま増えず=送信成功)
  • ラッパーdry-run: 修正後は読む系お題を選定・pool_low 警告解消

未了(本修正のスコープ外)

  • ask履歴べき等記録(store結線・plan §122スコープ)

[2026-09-19] - harness メッセージ履歴の圧縮導入(送信量の二次増加を線形化)+リミット整合

Added

  • AgentHarness._compact_history() — LLM送信直前に古い tool_result の本文を1行インデックスへ畳む。 Limits.keep_recent_tool_results(既定3)件を超えた分が対象
    • 残すもの: tool名・引数・元の本文長([omitted: read_file({"path":"x.py"}) → 4,200 chars])。 本文を丸ごと捨てるとLLMが同じ道具を再実行してステップがかえって増えるため
    • 消さないもの: tool_result メッセージ自体(assistantの tool_calls と1対1対応が必要なOpenAI契約の維持)
    • 冪等: 毎ステップ呼ばれるため既に畳んだものは再処理しない(OMITTED_PREFIX で判定)
  • テスト11件(圧縮の基本動作/tool identity保持/id対応の維持/線形化の効果測定/後方互換/ 冪等/resume経路/tool_call_id欠損フォールバック/巨大引数の切り詰め/system・user不変/ リミット整合の機械検査)

Changed

  • Limits.max_tokens を 500,000 → 200,000 へ。500,000 は履歴圧縮なしの前提値で、 同じ spec が定める「ステップ25回」と両立していなかった(圧縮なしでは25stepに753,750トークン必要)
  • OPERATIONAL_MAX_TOKENS を Limits().max_tokens の参照へ変更し、上限の定義箇所を減らした (宣言する側と実際に効く側が別の数字を持つ二重管理の解消・2026-09-19の事故と同型の再発防止)
  • spec 2026-08-30-nexuscore-agent-harness-design.md §5 を改訂 (トークン500k→200k・メッセージ履歴圧縮をMVP層に追加・リミット整合の機械検査を規定)

実測(要因分離の確定)

  • 前回「構造は二次・実測は線形で差が未解明」としていた件は、実データの右側打ち切りが原因と判明。 9run中7runが上限450,000に到達して停止しており増加曲線の推定に使えなかった。 打ち切られていない2runだけで見ると線形モデルの係数は3.08倍ばらつくのに対し 二次モデルは1.10倍(1,150 / 1,263)で、実測も二次と整合する
  • 圧縮の効果(mock計装・tool_result 8,000文字): 20step時点の累計送信量 1,562,605 → 482,249 文字(3.2倍削減)、 増加次数が二次(R²=0.9994)から線形(R²=0.9697)へ転換。 25step完走の推定消費は約172,000トークンで abort閾値180,000 に収まる

検証

  • pytest tests/harness/: 267 passed(PYTEST_EXIT=0)
  • pytest tests/(全体): 5298 passed, 0 failed(FULL_PYTEST_EXIT=0)
  • mypy src/: Success 274 files(MYPY_EXIT=0)/ 変更ファイル ruff: RUFF_EXIT=0

未了

  • 圧縮の副作用(古い結果を畳んだことでLLMが再実行しステップが増えないか)は実runでの検証待ち。 mock計装では確認できない

[2026-09-19] - Phase 5 判定書Go項目 G-2 / G-3 の実装+トークン爆発の要因分離

Added

  • G-2 ask応答時間の計装。AskSession.durations に prompt() 1回ごとの所要秒を記録 (例外時も finally で記録=timeout/中断の所要も計測対象)。AgentHarness.run() の戻り値に ask_durations を載せ、CLI出力JSON経由で collect_harness_metrics が p95 を算出する。 RunStateのschemaは据え置き(schema_version を上げると既存stateがquarantineされるため)
    • ask_response_time_p95_sec が常にNone・ask_instrumentation="not_implemented" 固定だった 状態を解消。サンプル0件は no_samples として「計装が無い」と「計測したがサンプル不足」を区別
  • G-3 ask実行標準手順のスクリプト化。run_harness(..., ask=True) で script -q 疑似TTY + 10秒間隔の継続yフィーダを組み立てる。 Task 24実測ではパイプ一括投下がask初期消費で全滅(run1 aborted)し、継続フィーダのrun2/3のみ成功。 再現不能だったこの手順をコードへ固定した

Fixed

  • --manual が ask_used: true と記録しながら実際には --ask を渡していなかった (記録が実態と食い違い)。G-3の結線で記録と実行を一致させた。 無人モードへaskが漏れないことは専用テストで固定(fail-closedの根幹)

要因分離の結果(トークン爆発・前項の未了分)

  • 構造としては二次: mock計装でmsgsの成長を実測したところ、切り詰めが一切なく 毎ステップ8,224文字ずつ積まれ、累計送信量は二次(原点通過最小二乗 R²=0.9994)。 1ステップ単体の入力は41文字→20ステップ目156,317文字(3,812倍)
  • だが実runの総トークンはステップ数に線形(9run・R²=0.78 / 二次モデルはR²=0.54で当てはまりが悪い)。 1ステップ平均 約2.4万トークンでほぼ一定。差の原因(プロバイダのキャッシュ計上か サンプル不足か)は未解明
  • 実務上の見通し: 総トークンはステップ数でほぼ決まるため、上限180,000での 到達可能ステップ数は約12。実runの実績は14〜22ステップのため、修復後も多くのrunが limits abortする見込み(ただし「上限超過で計測無効」ではなく「有効な上限内でのabort」に変わる)
  • 根本対策(msgsの切り詰め設計・max_steps=25とトークン上限の整合)は設計変更のため別タスクへ

検証

  • pytest tests/harness/: 256 passed(PYTEST_EXIT=0)
  • pytest tests/(全体): 5291 passed, 178 skipped, 26 xfailed(FULL_PYTEST_EXIT=0・143.25s)
  • mypy src/: Success 274 files(MYPY_EXIT=0)/ 変更ファイル ruff: RUFF_EXIT=0

[2026-09-12] - 構造負債3件の消化(models層抽出・xfail誤爆解放・遺物追跡解除)

Changed

  • DBモデル層を webapp から抽出(src/nexuscore/models/ 新設)。base.py に db インスタンス、entities.py に7モデル(git mv で履歴保持)。webapp/models.py と webapp/__init__.py の db は後方互換シムとして再エクスポートのみ残す
    • api / integration / services / cli / webapp の import を nexuscore.models へ切替(archive/ は非現用のため対象外)
    • テスト側 33ファイル147箇所の mock.patch 対象を移動先へ追従(実装移動でmockが効かなくなり97件failしたため)
  • xfail 自動適用機構を完全一致方式へ改修(tests/conftest.py)。_XFAIL_PATTERNS → _XFAIL_TESTS(値を (reason, strict) のタプル化)
  • pytest.ini に xfail_strict = true を追加。フレーク(実行順・環境依存)のみ各マーカーで strict=False を明示

Fixed

  • xfail の部分文字列マッチによる誤爆12件。if pattern in item.name により25パターンが実際には37テストへ適用されていた(test_error_code_catalog が同ファイルの6テスト全部を、test_main_block が別ファイルの無関係なテストを無効化)。さらに strict=False 固定のため、既に直ったテストが永久に xfail のまま残り XPASS 12件が常態化していた
    • NEXUSCORE_DISABLE_AUTO_XFAIL=1 でのフルスイート実測(25 failed, 5272 passed)により「今も本当に失敗する25件」を確定し、残りを解放

Removed

  • logs/ 75ファイルの git 追跡を解除。.gitignore:106 に logs/* があるのに追跡下だった(git仕様で追跡済みには無効)。中身は2025-08-28のexport dryrunログ・最終更新2025-11-24・参照元0件
  • 構造ダンプ2件(src/folder_structure.txt 9,752行 / tools/project_structure_export/NexusCore_folder_structure.txt 34,014行)の追跡を解除。ともに commits=1(2025-08-19の一度きり)で tools/export_structure.py が生成する側・読込参照ゼロ
  • .gitignore に *_folder_structure.txt を追加し再追跡を防止
  • いずれも git rm --cached のため実体はワーキングツリーに残存(可逆)

効果(自作ASTスキャンによる実測)

  • 循環依存: 6組 → 5組(integration↔webapp が 6/4 → 0/4 の一方向になり解消)
  • api → webapp: 28 → 4(残りは orchestrator_helper / celery_app / task_lock / create_app)。2026-08-12 のレビュー以降 5回連続で同値だった指標が初めて動いた
  • integration → webapp: 6 → 0
  • 追跡ファイル総数: 1,626 → 1,549
  • 実際に検証されるテスト: 5,265 → 5,271 passed(誤爆で眠っていた6件が復帰)・XPASS 12 → 6

対象外と判定したもの

  • core ↔ webapp 循環(2/14): 3エッジとも logging_service / logging_provider 参照で models 無関係。webapp/__init__.py:102-107 に既に register_logging_provider による依存逆転の仕組みがあるため、それを使い切る別対応が必要
  • tests/integration/ への integration マーカー付与: 不要と実測で判定。pytest.ini:49 のマーカー定義は「実APIキーを必要とするテスト」の意味であり、tests/integration/ の8ファイル116テストは外部依存ゼロ(redis/httpx/docker/subprocess の grep 0件)。付与すれば116テストが無意味に除外される

検証(生exit code・パイプ無し)

  • pytest -q: 5271 passed, 178 skipped, 9 deselected, 26 xfailed, 6 xpassed / PYTEST_EXIT=0(変更前と全数値一致=振る舞い保存)
  • ruff check src/ tests/: All checks passed! / RUFF_AFTER_EXIT=0
  • mypy src/: Success: no issues found in 274 source files / MYPY_EXIT=0
  • xfail_strict の fail条件検証: docs/api/ERROR_CODE_CATALOG.md を一時作成して strict=True のテストを XPASS させ、[XPASS(strict)] → FAILED になることを確認(strict=False 側は 1 xpassed のまま緑)。一時ファイルは削除済み
  • import 同一性: nexuscore.models.db is nexuscore.webapp.db is nexuscore.webapp.models.db

[2026-09-11] - streamlit依存の整理(tools/tests/ui限定使用・削除ルート選択・2026-08-12包括レビュー残課題の完結)

Removed

  • requirements.txt — streamlit>=1.29.0,<2.0.0 を削除(2026-08-12 包括レビュー残課題・A群(4)で torch/tensorflow/SpeechRecognition/pydub/websockets/psutil 削除済みの最後の1件)。networkx は torch 削除時に明示化した依存のため維持(L11-13)
  • tools/streamlit_dashboard.py — Streamlit製進化ダッシュボード。実測: Makefile/CI/docs/tests から参照0件・git履歴は初回commit以後変更なし → 現用性なしと判定
  • tools/cost_dashboard.py — Streamlit製LLMコスト見積ダッシュボード。参照0件に加え収録モデル単価が gpt-4o/claude-3.5 系で陳腐化 → 現用性なしと判定
  • tests/ui/test_streamlit_legacy.py — レガシーStreamlitアプリのテスト9件。実測: 全9テスト skip(streamlit_legacy は archive/legacy_modules/ 配下でテストから到達不能・conftest に path 注入なし)=実質 dead test。依存を残してまで復活させる価値なしと判断し削除
  • .venv からも streamlit 1.62.0 をアンインストール(実環境反映)

判断(削除 or requirements-dev.txt 移動の二択)

  • 削除を選択。根拠: ①tools/ 2ダッシュボードは参照ゼロ+陳腐化で dev 移動しても使い手なし ②legacy test は全 skip の dead test で保守コストのみ残る ③dev 移動は CI に 200MB超の streamlit インストールコストを残す
  • archive/legacy_modules/streamlit_legacy.py は issue スコープ外(過去資産保管庫)として残置 — requirements から外れるため import される経路なし
  • src/nexuscore/analyzer/context_agent.py L147-148 の “streamlit” は requirements.txt 内の文字列検出ロジック(import 不要)のため変更なし・test_multi_llm_review_coverage.py の検出テストは引き続き pass

検証(生exit code)

  • importスモーク(nexuscore 配下7パッケージ+nexuscore.ui+tools/dashboard+tools/genesis_analyzer・動的import実使用の教訓に基づく): 全OK / EXIT=0・import streamlit → ImportError(要件通り除去)
  • requirements系3ファイル+.venv pip list の streamlit 残存 grep: GREP_EXIT=1(0件)
  • フルテスト(streamlit uninstall 後・pytest tests/ -q): 5265 passed / 178 skipped / 9 deselected / 26 xfailed / 12 xpassed / EXIT=0(164.01s)。skip 187→178(−9)は削除した legacy test の全skip数と整合・passed 不変
  • tests/ui 単体回帰: 65 passed / 33 skipped / 4 xpassed / EXIT=0(xpass は既知の gradio sys.modules pollution・今回の変更と無関係)
  • ruff(src/tests): All checks passed! / RUFF_EXIT=0

[2026-09-11] - ui層カバレッジ方針の実測と決定(kernel削除+UI描画レイヤーomit・84.08%→86.38%)

Added

  • .coveragerc [run] omit — UI描画レイヤー(Gradioタブbuilder)4パターンを追加(unified_gradio_ui.py・_state.py・_llm_init.py・*_tab.py)。omitコメントに実測根拠と再評価条件(E2E/Browserテスト導入時)を明記。ui/policy_interface.py(実測93.33%・テスト実在)は意図的に測定継続

Removed

  • src/nexuscore/core/nexus_os_kernel.py — デッドコード削除(実測: src/tests/tools 参照0件・カバレッジ0.00%(75/75 miss)・中身は DummySearchTool/DummyLLMClient のプレースホルダスタブ)。omit で隠すのではなく削除を選択(スタブ実装の残置は将来の改修誤誘導になるため)
  • scripts/run_vc_scout.py — kernel の唯一の参照元。ただし実測で ModuleNotFoundError: No module named 'nexus_os_kernel'(kernel は移設済みで flat import が既に破綻・起動不可)+ ドキュメント参照なしのため関連整理として削除

Changed

  • README.md — カバレッジ表記を 84.08%(CI 2026-09-10)→ 86.38% / branch 81.84%(ローカル serial フルテスト実測 2026-09-11) に更新。数値変化の理由(①kernel削除 ②UI描画レイヤーomit)を出典セクションに明記・テスト数5,499のCI出典は維持

検証(生exit code)

  • 変更前フルテスト+coverage(serial・5,488テスト): 2 failed(webapp flake・単独実行でpass実測済)/ BASELINE_EXIT=1 / TOTAL 84.02%(15,570 stmts)
  • 変更後フルテスト+coverage(同条件): 5265 passed / 187 skipped / 26 xfailed / 12 xpassed / AFTER_EXIT=0 / TOTAL 86.38%(14,988 stmts・260 files)
  • ruff(src/tests): All checks passed! / RUFF_EXIT=0
  • bandit(-ll・High/Medium severity): 0件 / BANDIT_EXIT=0
  • kernel参照の固定プロトコル再検索(1回目N=1→2回目N=1・scripts/run_vc_scout.py のみ): 削除後に残存参照なし

[2026-09-11] - mutmut対象拡大とmutation score実測(全体64.6%・生存503 mutant)

Added

  • pyproject.toml [tool.mutmut] — paths_to_mutate を mutation_tester_agent.py のみから中核5ファイルへ拡大(+ llm/llm_router.py・orchestrator/authority_runner.py・orchestrator/run_lock.py・orchestrator/run_state_integrity.py)。tests_dir を対応14テストファイルへ拡大・also_copy = ["src"] 新設(mutants/ コピー内の依存 import 解決)
  • docs/reports/mutation_score_report_20260911.md — 実測レポート(mutmut 3.5.0・全1,433 mutants完走)
  • artifacts/mutation/survived_mutants_20260911.txt — 生存503 mutantの全一覧

Changed

  • カバレッジ84.08%に対するアサーション強度の実測値を初めて確定: 全体 score 64.6%(killed 737 + timeout 181 / 評価対象1,421)。llm_router 55.7%・run_lock 53.5%・run_state_integrity 70.2%・authority_runner 91.9%(timeout 179件=58%を含み過大評価の可能性)

検証(生exit code)

  • 対象14テストファイル回帰: 233 passed / PYTEST_EXIT=0
  • pyproject.toml パース(tomllib): TOML_EXIT=0
  • ⚠️ mutmut run は1,433/1,433完走・サマリー出力後に終了処理でデッドロック(WCHAN=futex_wait_queue 実測)し自力ではexitしないため MUTMUT_EXIT=143(SIGTERM停止)。スコアは mutants/*/.py.meta の exit_code_by_key 直接集計

[2026-09-10] - README陳腐化修正(audio/不存在削除・カバレッジ実測更新 84.08%)

Fixed

  • README.md — 存在しない src/nexuscore/audio/ の記載を削除(Whisperは modules/whisper_handler.py に実在・該当行の説明は維持)
  • README.md — カバレッジ/テスト数を実測更新: 84.69%(2026-07-09)→ 84.08% / branch 79.94% / 5,499テスト(2026-09-10)。出典=GitHub Actions CI run 34479260801(main push・success)の coverage.py TOTAL 行+coverage.xml artifact(branch-rate=0.7994)をREADME本文に併記
  • docs/spec(CR仕様書)参照は実在と整合を確認済み・docs/specs はREADME参照ゼロのため変更なし

検証(生exit code)

  • 陳腐化表記残存 grep "5,465|84.69|2026-07-09|audio/" README.md: GREP_EXIT=1(0件)
  • importスモーク: import nexuscore → EXIT=0
  • 回帰スモーク pytest tests/cli tests/core -q: 1010 passed / EXIT=0

[2026-09-10] - L407: CI 56run連続赤の解消(Bandit B602 nosec化+ローカルゲート統合)

Fixed

  • src/nexuscore/harness/tools/exec.py — Bandit B602(subprocess shell=True)High の nosec 化(行末コメント・根拠=モジュールdocstringの3層防御設計+ask承認が最終防線)。Task 20の設計判断自体は変更しない(Surgical Changes)
  • ローカル品質ゲートにBanditが不在でCIのSecurity Vulnerability Scanだけが赤になり続けた構造を解消(08-30以降56run連続赤・11日間)

Added

  • Makefile に security ターゲット新設(CI Security Vulnerability Scanと同一条件のbanditコマンド)+ make qa チェーンへ組込(format → lint-fix → typecheck → security → test)

検証(生exit code)

  • ローカルbandit(CI同一コマンド): 修正前 High: 1 / EXIT=1 → 修正後 High: 0 / EXIT=0
  • make security: MAKE_SECURITY_EXIT=0
  • pytest tests/harness/: 236 passed(PYTEST_EXIT=0)
  • ruff check src/nexuscore/harness/tools/exec.py: RUFF_EXIT=0

[2026-09-09] - Phase B: 定題実行cron本番登録(cron-setup規定路線・実測ゲート合格)

Added

  • run_harness_task.py に cron-setup規定路線の排他機構を実装: ①当日成功スタンプ(JST明示・成功時のみ書込=失敗翌日再試行可・同日2回目はEXIT=3 skip・--forceで手動再実行)②起動時selfcheck(venv不在・題庫不在→exit 78+Discord通知)③失敗時Discord通知(best-effort・webhook未設定/送信失敗時は .notify.fail 退避)④成功時heartbeat(mtimeでstale検知)

検証(cron-setup Step 5・生exit code)

  • dry-run: DRYRUN_EXIT=0
  • 本番1回目: RUN1_EXIT=0・stamp=2026-09-09書込・heartbeat作成・題庫1題[x]化(tokens=247,456・ハード上限超過を警告記録)
  • 同日2回目: RUN2_EXIT=3 + 「当日成功済み → skip」(本機構のfail条件を合格)
  • --force --dry-run: 次のお題を正しく選択(FORCE_EXIT=0)
  • 実測でcronコマンド形式のミスも捕捉(timeout 960 PYTHONPATH=... はenv展開されずexit 127・cron行は source && export && timeout 順に修正済み)

登録

  • WSL crontab: 43 23 * * *(毎日1回・secrets source込み・timeout 960・絶対パス)・正典: obsidian-ssot 自動化.md Cron表

[2026-09-09] - Phase 5 Task 27(Phase A): harness計測定題ラッパー+題庫新設(v4仕様)

Added

  • scripts/run_harness_task.py 新設 — v4確定仕様の定題実行ラッパー: ①run_state日時分離 ②題庫(docs/harness_題庫.md・無人用/手動用セクション分離)からカテゴリ均等化強制の非復元ランダム抽出(週シード) ③ガードレール(題庫枯渇<3警告/0停止・月額トークン予算到達時は短冊お題優先・watchdog正規化hash二段<8警告/<5停止・連続欠損>3/>5日警告) ④run毎に計測6項目を metrics_history.jsonl へ恒久追記 ⑤1run上限: トークンソフト100k/ハード200k(事後検知)・時間ソフト10分/ハード15分強制終了 ⑥題庫[x]マーカーの原子的更新(flock競合時skip)
  • docs/harness_題庫.md 新設 — 実課題由来のお題7題(無人用・読む系3カテゴリ)+手動用4枠
  • tests/harness/test_run_harness_wrapper.py 新設 — 9ケース(パース/カテゴリ均等化/短冊優先/枯渇/正規化hash/watchdog二段/月次トークン/原子的[x]更新/履歴読込)

Changed

  • scripts/collect_harness_metrics.py に metrics.json 書込の flock 排他を追加(r2 Gemini#4・手動/cron競合防止)

検証

  • 新規9ケース緑・harness全体 200 passed・ruff All checks passed・題庫dry-run実測(カテゴリ均等化抽出で正しく1題選定)

    [2026-09-09] - Phase 5 Task 25: 計測6項目収集スクリプト+Web UI state汚染修正

Added

  • scripts/collect_harness_metrics.py 新設 — spec §10 計測6項目(429頻度〔breaker OPEN代理観測〕/ブレーカ遷移/ask応答時間〔計装未実装=null〕/checkpoint失敗率/abort分布/トークン量)を artifacts から収集し artifacts/harness/metrics.json へ出力。checkpoint log の混在テキスト(askログ+末尾JSON)から最後のJSONを抽出
  • tests/harness/test_collect_metrics.py 新設 — 6ケース(abort分布/トークン/breaker代理/checkpoint抽出/unparseable失敗扱い/純JSON抽出回帰)

Fixed

  • Web UI state汚染(実害): _run_harness が RunStateStore()(CLI既定パス・CWD相対)を使い、Web UIスモークテストがCLI中断runのresume stateを上書きしていた(Task 24 run1のdeepseek state 426045 tokens/limits がpytest検証中に破壊された実測)→ Web UI実行の保存先を run_state_webui.json に分離(回帰テスト test_run_does_not_touch_cli_default_state)
  • collect_harness_metrics._extract_last_json の境界バグ(range(len-1, 0, -1) で位置0の外括弧を試さず純JSONログがunparseable扱い)を修正

検証

  • harness全体 191 passed(184+7)・ruff All checks passed・metrics実測: checkpoint失敗 0/3・abort分布 limits=2(うち1件はWeb UIスモーク)/none=2・tokens mean 44,066/max 167,899

[2026-09-08] - Phase 4 Task 23: ハーネス Web UI 薄い実装(FastAPI + HTMX方針・薄い1画面)

Added

  • api/harness_routes.py 新設 — APIRouter(prefix="/harness") でGET /harness/(フォーム)+POST /harness/run(同期実行・結果JSON表示)。harness_cli.build_llm/build_registry を再利用(DRY)
  • api/fastapi_app.py の _register_routers にharness_routerをinclude(ADR-002決定Aどおり既存FastAPIアプリへ統合)
  • tests/harness/test_web_ui.py 新設 — フォーム表示・実行結果表示・create_app結合の3テスト

plan雛形からの意図的変更(実契約突合)

  • 配置を webapp/harness_routes.py(plan雛形)→ api/harness_routes.py へ変更(FastAPIアプリ実体はapi/)
  • LLMRouter経路は不使用(RoutedLLM不適合・Task 15と同型)
  • ask承認UIは本実装に含めない: AskSessionはTTY結合のためWeb UIでは表現できず、ask=False(registry=読む系のみ・fail-closed)。ask UIは将来拡張(run_state ask履歴結線§122と同時期)・既定provider=mock(オフライン安全側)

検証

  • TDD: RED(collection error)→ GREEN 3件。harness全体 184 passed・ruff All checks passed・mypy src/ 0 errors(272 files)

[2026-09-08] - Phase 4 Task 22: ハーネス Web UI スタック決定(FastAPI + HTMX)

Added

  • docs/adr/ADR-002-harness-ui-stack.md — ハーネスWeb UIスタック決定(FastAPI+HTMX・案A採用)。plan Task 22雛形を本repoのADR命名規約(ADR-001-型)に合わせて ADR-002-harness-ui-stack.md で実装(planの 2026-08-30-日付指定からの意図的変更・実契約突合)

[2026-09-07] - Phase 3 Task 21: CLIのexec結線(build_registry抽出)+ チェックポイントE2E合格

Added

  • cli/harness_cli.py に build_registry(ask: bool) を新設しCLIのtool registry構築を抽出。--ask 時に run_command(policy既定 default: ask の撃つ系)を登録するよう結線 — これがないとplan Task 21の「pytest実行をask承認込みでE2E」がtool不在で失敗する(plan本文と実契約のズレ・変更記録方式でdocstringにも記録)
  • tests/harness/test_harness_cli.py に build_registry のテスト2件新設(–ask時=読む系+書く系+撃つ系6種/–ask無し=読む系のみ)

検証

  • TDD: RED(AttributeError: build_registry)→ GREEN(CLIテスト9件PASSED・EXIT=0)
  • harness 181 passed(179+新規2)・ruff 変更2ファイル All checks passed
  • Task 21チェックポイントE2E合格(deepseek-chat+疑似TTY): run_command 'pytest tests/harness/ -q' をask承認込みで実行 → [ASK] ... approve? → y → 181 passed・exit code 0・abort_reason=null(成功判定達成)。1回目実行はscript内側パイプでaskチャネル不通→denied: ask denied_timeout のfail-closed拒否経路も実測。E2Eログ: artifacts/checkpoints/phase3/2026-09-07/log.json

[2026-09-07] - mypy src/ 4件赤の解消(Task 17-20追加分・型注釈レベル)

Fixed

  • harness/tools/exec.py:55: # type: ignore[arg-type] の誤コード指定(実際は call-overload)を修正。動作変更なし
  • harness/loop.py:147: msgs を list[dict[str, Any]] と明示注釈(tool_calls付きassistantメッセージ連結の dict-item 誤検知解消・実態に合わせた注釈のみ)
  • harness/loop.py ask経路: ask_session is None のfail-closed分岐を追加(ASK は ask_supported=True=非None でしか返らない tool_gate.evaluate 契約だが、到達不能経路でも承認なし実行の抜け道を作らないため明示拒否 error: ask_session missing・mypy narrow を兼ねる)

検証

  • mypy src/ : Success: no issues found in 271 source files(exit 0・パイプなし直接取得)
  • pytest tests/harness/ -q : 179 passed(exit 0)・全体: 5208 passed, 0 failed(exit 0)

[2026-09-06] - Phase 2 Task 17: 書く系tools 2種(write_file / edit_file)

Added

  • src/nexuscore/harness/tools/write.py 新設: write_file(親dir作成+1MB上限+deny_paths)・edit_file(1件マッチのみ実行・複数はambiguous)
  • テスト12件(tests/harness/test_tools_write.py)・harness計測141件PASSED(129+12)

Changed

  • round7修正条項の反映: edit_file複数マッチ=0件not_found/1件実行/2件以上ambiguous(match_count返却・実行せず)— plan本文のValueError方式を上書き
  • plan雛形からの安全強化(docstring記録): ①deny_paths対応(harness C案束縛の供給対象にする・書込経路のfail-open防止)②1MB上限(読む系MAX_BYTESと対称)③非UTF-8保護(strict読み・書き戻しでバイナリ破壊しない)
  • ToolResult に match_count/path フィールド追加(同型docstringの「Task 17/20統一予定」どおり)

Fixed(3機MLR採用7件・MiniMax25/Gemini2/OR10の計37指摘から・2026-09-06)

  • 原子書込(同dir一時ファイル→fsync→os.replace・書込途中死でも元ファイルを壊さない): write_file/edit_file共通ヘルパー _atomic_write_text() 新設
  • edit対象ファイル不在はnot_found ToolResult(生FileNotFoundErrorをLLMへ出さない・Gemini+ORの2機独立一致)
  • 置換後サイズの上限検査(old→new膨張で1MB突破する置換は実行せずtoo_large)
  • old==newはinvalid_argument(no-op書込によるmtime更新・監査汚染を防止)
  • symlink対象の書込拒否(symlink_refused・LLM指定パスがsymlink経由で機密ファイルへ迂回する単純攻撃を遮断。TOCTOU競合までは閉じない=既知制限をdocstring明記)
  • is_deniedをtools/__init__.pyへpublic化・共通化(read.pyの_is_deniedを移動・private import流用のリスク解消)
  • テスト8件追加(MLR採用分)・harness 149件PASSED(141+8)
  • 除外パス照合_is_denied→is_denied移動に伴うread.pyのimport整理(fnmatch/os移動)

[2026-09-06] - Phase 2 Task 18: ask確認フロー(CLI対話)+policy拡張

Added

  • src/nexuscore/harness/ask.py 新設: AskSession(select(2)ベースstdin監視・timeout=deny・round7修正のthreading.Timerを排除)+ AskResult(StrEnum)(APPROVED/DENIED_TIMEOUT/DENIED_USER)+ _ask_supported()(TTY判定・CI/pipe起動はask不可→denyへ倒れる安全側)
  • テスト8件(tests/harness/test_ask_flow.py): y承認・大文字小文字無視・n拒否・空入力拒否・タイムアウトdeny・_ask_supported()型検証・ask_supported=False=deny/True=ask・deny_paths一致はaskに上がらず即DENY
  • tool_policy.yaml: write_file/edit_file を default: ask + deny_paths: ['.git/**', '**/.env', '**/secrets/**'] に拡張
  • harness計測157件PASSED(149+8)

Changed

  • plan雛形からの変更点(ask.py docstring記録): ①雛形の未使用 import signal/threading 削除(select方式に不要)②テスト可能性のため reader 関数を注入可能化(雛形テストの monkeypatch(builtins.input) はselectのstdin監視と非互換)③store はask履歴べき等記録用に受け取るが結線はTask 19以降
  • ToolGate(既存)の default: ask 経路をそのまま活用(Task 10で実装済み・ask_supported=True ならASKを返す)

Fixed(3機MLR採用5件・MiniMax21/Gemini4/OR6の計31指摘から・2026-09-06)

  • 【critical・実バグ】既定readerの引数不一致: _readline_with_timeout(prompt, timeout) を prompt() から1引数で呼んでおり本番経路で必ずTypeError → timeout束縛済み1引数ラッパへ修正(Gemini発見・2テスト追加)
  • 対話チャネル不在のfail-closed: stdin/stdoutが非TTYなら即None=deny(呼び出し側の判定漏れに依存しない・MiniMax+Gemini+OR)
  • EOF(Ctrl+D)の正規化: readline戻り’‘をDENIED_TIMEOUTへ(’‘をDENIED_USERと誤合流させない・MiniMax+Gemini)
  • timeout通知をstderrへ(stdout JSON契約保護・MiniMax)
  • Windows非対応の明示的ガード(select(2)はPOSIXのみ・spec §10前提をRuntimeErrorで明示・Gemini)

[2026-09-06] - Phase 2 Task 19: ask結線+tool定義スキーマ自動生成+チェックポイントE2E

Added

  • ask結線(plan外の結線ギャップ解消): AgentHarness(ask_session=...) 新設・gate.evaluate(ask_supported=ask_session有無)・Mode.ASK時はAskSession.prompt()承認のみ実行(拒否/タイムアウトはdenied: ask <result>通知)。CLIに--askフラグ(write_file/edit_fileをregistry追加+AskSession接続・非TTYはdeny二重防御)
  • _tool_defsシグネチャ自動スキーマ生成: 旧実装の空properties: {}ではLLMが引数名を推測して誤名(file_path/old_string等)を渡しTypeErrorで完遂不能(Phase 1チェックポイント項目①「空properties問題」の顕在化)。シグネチャからparameters/required/descriptionを自動生成・policy束縛対象のdeny_pathsは公開しない
  • テスト6件新設(ask結線4+スキーマ2)・harness 165件PASSED

Phase 2チェックポイントE2E実測(deepseek-chat・疑似TTY)

  • 承認経路: [ASK]表示→y承認→edit_file実行→ファイル実改変確認(version = 1→2・2 steps/1,478 tokens/abort null)
  • 拒否経路: 入力消費後のaskはタイムアウト→deny通知→LLMが「編集は適用されなかった」と誠実報告・ファイル無変更
  • 実行ログ: artifacts/checkpoints/phase2/2026-09-06/log.json(gitignore済)

[2026-09-06] - Phase 3 Task 20: 撃つ系tool(run_command)+禁止パターンdeny

Added

  • src/nexuscore/harness/tools/exec.py 新設: run_command()(shell=True+タイムアウト60s+末尾5KB保持・deny_patterns+ask+上限の3層防御)
  • ToolGateへdeny_patterns判定を追加: コマンド文字列の部分一致で即DENY(ask承認に上がらない)・非list型はfail-closed deny-all(deny_pathsと対称)
  • tool_policy.yaml: run_command: { default: ask, deny_patterns: ['rm -rf', 'sudo ', 'git push --force', ':(){:|:&};:', 'mkfs', 'dd if='] }
  • テスト10件(exec 5+deny_patterns 5)・harness 175件PASSED
  • repo policy実測: 禁止コマンド=deny・通常コマンド=ask・非TTY=deny・.env編集=deny

Changed

  • round7修正条項の反映: stdout/stderrは末尾5KB保持(エラー根本原因は末尾に出ることが多い・plan雛形の先頭切りを上書き)
  • タイムアウトは生TimeoutExpiredでなくToolResult(status="timeout")通知(読む系/書く系と同一規約)
  • ⚠️ shell=Trueは本設計の必須要件(LLM選択コマンドの実行)・安全性はGate deny_patterns+ask+タイムアウトで担保(plan本文のsecurity-guidance指摘どおり)

Fixed(3機MLR採用5件・MiniMax11/Gemini4/OR9の計24指摘から・2026-09-06)

  • encoding=”utf-8”+errors=”replace”明示(バイナリ出力でUnicodeDecodeError不発・Gemini+OR)
  • stdin=subprocess.DEVNULL(対話型コマンドがaskチャネルのstdinを奪ってハング/入力奪取する経路を遮断・OR)
  • timeout_secondsの型検証+[1,600]クランプ(LLMが文字列/負数/巨大値を渡しても安全・Gemini)
  • OSErrorもToolResult(status=”exec_error”, detail=…)通知(生例外でLLMを汚さない・Gemini+OR)→ ToolResultへdetailフィールド追加
  • ループ統合テスト新設(Gate deny判定→道具不実行をAgentHarness結合で検証・MiniMax)+MLR採用分テスト3件・harness 179件PASSED
  • 既知制限をdocstring明記: shellメタ文字経由のdeny_patterns回避は原理的に閉じない(ask承認の全文表示が最終防線)・env/cwd非対応

[2026-09-05] - Phase 1 Task 15: harness_cli.py(CLI入口)

Added

  • src/nexuscore/cli/harness_cli.py 新設: python -m nexuscore.cli.harness_cli "<task>" でAgentHarness起動・JSON 1行出力・abort_reason なし=exit 0 / あり=exit 1
  • --provider mock(LocalToolCallDummyLLM・オフライン動作確認用)・--model "vendor:model"(実プロバイダはToolCallingMixin済み4ファミリ経由で直接生成)・--policy・--state-path オプション
  • テスト7件(tests/harness/test_harness_cli.py): exit 0/1写像・mock limits abort・state保存・policy不在fail-closed完走・未対応provider SystemExit・mock構築・factory例外cli_error化
  • harness計測: 129件PASSED(Task 14の122件+今回7件)

Fixed(3機MLR採用8件・MiniMax12/Gemini4/OpenRouter9の計25指摘から)

  • 予期せぬ例外をJSON(abort_reason: cli_error)+exit 1で返すようmain()本体をtry/except化(SystemExitはargparse同型の意図的経路として透過)
  • abort時に理由をstderrへ1行出力(exitコードは1統一・spec §6どおり)
  • 「JSON 1行出力」テストをlen(raw.strip().splitlines()) == 1へ厳格化(旧assertは複数行でもPASSする緩い検証だった)
  • fail-closedテストにabort_reason is None(健全完走)を明示・出力キー網羅assert追加
  • --provider/--modelのhelp文言で「openai以外は–model必須」を明記・docstringにresume非対応(Task 16で対応予定)とpolicy不在時のfail-closed挙動を記録

Changed

  • plan雛形のLLM取得経路を変更(docstringに記録): 雛形の LLMRouter().get_llm_for_task() は RoutedLLM(complete_with_tools 未実装・_routed_llm.py:34-107)を返しharness契約不適合(1呼出目でAttributeError)。create_provider() 経由で ToolCallingMixin 済みプロバイダを直接生成する方式へ。RoutedLLMのtool対応は別途起票
  • DEFAULT_MODELSを実在確認済みモデルへ修正(Task 16チェックポイント実測): openai:gpt-5.1-instant は本アカウントで404(llm_router cheap_mapの値は実在しなかった)→ openai:gpt-5.1(/v1/models一覧で実在確認)+ deepseek:deepseek-chat(チェックポイント実行で実測)。なおOPENAI_API_KEYはクレジット枯渇(429 insufficient_quota実測)のため実行は不可・deepseekで代替

Task 16: Phase 1チェックポイント(実プロバイダ検証・2026-09-05)

  • 検証項目① 合格: 実プロバイダ(deepseek-chat)でCLI実行→search_textがtool args付きで実行・実ヒット(SSOT内harness言及ファイル群)をLLMが要約して返答・abort_reason: null(4 steps / 7,405 tokens / 8秒)。空propertiesスキーマでもargsが渡ることを実証
  • 検証項目② 合格: registryは read_file/list_dir/search_text の3つのみ・read.pyにwrite/exec/edit定義ゼロ(grep EXIT=1)
  • Step 2(state確認): artifacts/harness/run_state.json にloop_steps/tokens/breaker状態が保存・2回目実行で更新確認(steps 4→7)。明示resume機能はPhase 2
  • 実行ログ: artifacts/checkpoints/phase1/2026-09-05/log.json(gitignore済・ローカル保管)

[2026-09-05] - 品質ゲート3赤の復旧(ruff/pytest 緑化 + mypy 14→1)

Fixed

  • ruff exit 1 → 0: tests/harness/test_mock_provider.py の I001(import順)を --fix で解消。ruff check src/ tests/ → All checks passed!
  • pytest exit 1 → 0: tests/harness/test_diagnostics.py:7 の ["python", ...] を sys.executable へ(FileNotFoundError: 'python' による恒常fail・2026-08-04 に修正済みの同型バグの再発)。5151 passed / 187 skipped / 27 xfailed・実テスト失敗0件
  • tool-calling 経路の stub fallback が実際に壊れていた問題(mypy 12件の実体): _stub_fallback_response は as_json の値に関わらず常に str を返すのに、_call_http_tool は dict 契約だったため、NEXUSCORE_ALLOW_STUB_FALLBACK=1 かつ real call 失敗時に _adapt_response_native_to_internal が AttributeError: 'str' object has no attribute 'get' でクラッシュしていた(2026-09-05 実測)。型注釈だけ合わせるとバグを型で正当化するため、実態側を修正:
    • BaseLLM.execute_real_or_fallback に stub_factory を追加し @overload でジェネリック化(stub_factory 無し=str 限定 / 有り=呼び出し側の型 _R)。渡し忘れを mypy が検出する契約にした
    • 4provider(openai / openai_compat / anthropic / gemini)の stub 応答を _tool_stub_response() へ切り出し、stub モードと fallback で共用
    • fallback 無効(既定)時は従来どおり raise(C5 silent-fallback 対策を維持)
  • session 未初期化時の不明瞭な AttributeError: BaseLLM._require_session() を新設し、'NoneType' object has no attribute 'post' ではなく明示的な RuntimeError にした(4provider の union-attr エラーも同時解消)
  • harness/diagnostics.py:159 の report 型を dict[str, dict] → dict[str, Any](_measured_at に str を入れるため)

Added

  • テスト12件(tests/harness/test_tool_calling_mixin.py): 4provider × ①fallback が dict を返す ②fallback 無効時は raise ③session 未初期化で明示的 RuntimeError

Known / 未対応

  • mypy は 14件 → 1件。残る harness/loop.py:192("tool_calls": list を dict[str, str] へ入れる dict-item)はTask 14 実装中の別セッションが占有中のため意図的に対象外。ゲート自体は exit 1 のまま
  • GeminiLLM.__init__ は self.base_url / self.api_key を設定しないため、_call_http_tool の real 経路は現状 AttributeError になる(tool-calling real 経路が未完成・別途起票)
  • tests/e2e/helpers/server.py:38 と tests/analyzer/test_unified_analyzer_coverage.py:844 にも "python" ハードコードが残るが、それぞれ skip / XFAIL で露見していないため今回は非変更(別途起票)

[2026-09-05] - loop.py実装(Phase 1 Task 14)

Added

  • loop.py AgentHarness最小ループ: tool callingループ+ToolGate/ブレーカ/RunState統合。4ハードリミット(max_steps 25/max_wall 600秒/max_tool_calls 40/max_tokens 50万)+段階的反応(80%ログ警告・90%abort)
  • round7修正条項3件の実装: loop↔breaker連携順序固定(LLM呼出前allow_request→429検出→OPEN遷移save→re-raise・SIGINTはsave+graceful return)/deny時tool_result形式("denied: <reason>")/道具実行前budget確認(超過見込み=would_exceed_limit ToolResult・実行せず)
  • 起票2件の実装義務を履行(バックログTask 14節): ①probe結線=LLM呼出直前にallow_probe()を記録し成功でrecord_probe_success()・失敗でrecord_probe_failure()(HALF_OPEN→CLOSED復帰を結合テストtest_probe_recovery_half_open_to_closedで実現・起票fail条件クリア)②deny_paths C案=初期化時にpolicy値をregistry束縛(ToolGate.deny_paths_for()新設・LLM引数のdeny_pathsは破棄で上書き不可)
  • テスト22件(ScriptedLLMスタブで決定論検証・probe復帰/429検出/90% abort/80% warn/SIGINT/PartialFailure abort/deny_paths束縛+LLM上書き不可)

Fixed

  • plan骨格コードの実装時修正5件(loop.py docstringに記録): ①args=→tool_args=(Task 10改名追従)②deny時record_failure削除(denyはpolicy判定・spec §5トリガは429×3/タイムアウト連続)③1ステップ1tool_call→全tool_calls処理(OpenAI契約)④token比較を直前応答のみ→累計化 ⑤tool result前にassistant(tool_calls付き)メッセージ連結(OpenAI契約)
  • 3機MLR採用11件適用(42指摘・MiniMax 31/Gemini 3/OpenRouter 8・却下12種はふくけい承認済み): SIGINT時に現在stepで保存/道具完了後の保存はin_flight=None/ブレーカ記録をprovider系例外(requests.RequestException・status_code属性)に限定/tool_calls_usedを実行試行で加算/functools.wraps/[truncated]マーカー/probe結線の直列実行契約明文化+テストassert/判定順序根拠コメント。Phase 1チェックポイント検証項目へ昇格: 実プロバイダでのtool args実検証・registry読む系のみ確認(MLR却下②③の代替処遇)

[2026-09-04] - 包括レビュー r3(差分・コード変更なし)

Audit(レビューのみ・本エントリによるコード変更は無し)

  • 2026-08-29 レビュー以降の28コミットを差分評価。A群(1)〜(8)の成果を実測確認: node_modules tracked 3,075 → 0(追跡ファイル 4,658 → 1,605・−65%)/pip-audit -r requirements.txt 4件 → 0件(No known vulnerabilities found / exit 0)/CIに sca-scan 新設・secret-scan 独立workflow化
  • src/nexuscore は +1,317 LOC(32,844→34,161)だが CC>20 は 11 のまま据え置き・docstring欠落 20%→19%

要対応(検出・未修正)— 品質ゲート3つが赤・全件 Phase 1(harness) 由来

  • ruff src/ tests/ exit 1: tests/harness/test_mock_provider.py:14:1 I001(--fix 可)
  • mypy src/ exit 1: 13 errors / 5 files。openai_provider.py:201,205 / openai_compat.py:214,218 / anthropic_provider.py:162,166 / gemini_provider.py:198,202 に同型3件ずつ(ToolCallingMixin Mix-in 時の複製)+ harness/diagnostics.py:186。Mixin の型シグネチャ側で1箇所直せば4箇所とも解決する見込み
  • pytest exit 1: tests/harness/test_diagnostics.py::test_mro_command_writes_file が恒常fail(単体でも失敗)。1 failed, 5096 passed, 187 skipped / 200.09s
    • 真因: tests/harness/test_diagnostics.py:7 の ["python", ...] ハードコード → FileNotFoundError: 'python'。2026-08-04 の「pytestサブプロセスpythonハードコードsys-executable化」で修正済みの同型バグの再発(既存23箇所は sys.executable)
    • 注意: CI は ubuntu-latest + setup-python で python が存在するためCIでは緑になりうる(ローカルのみ落ちる型)

構造(未修正)

  • 循環依存 5組 → 6組。新規 harness ↔ llm (2/4) を Phase 1 実装が追加
  • api → webapp = 28 エッジは 2026-08-12 / 08-29 / 09-04 の3回で完全同値(models層抽出が未着手)
  • logs/ 75ファイルが .gitignore に logs/* があるのに追跡下(最終更新 2025-11-24)/folder_structure.txt 2件 43,766行は commits=1 の陳腐化ダンプ
  • coverage.xml は Jul 8 のまま(58日前)

参考(除外判定の根拠・実測)

  • evaluation/ = evalplus の外部取込(LICENSE あり・commit 1件・以降未編集)
  • sdk/typescript = openapi-generator の自動生成(.openapi-generator/FILES・DO NOT EDIT)
  • 詳細記録: obsidian-ssot/01_DECISIONS/NexusCore/2026-09-04_包括レビューr3-A群成果確認と新規実装の品質ゲート3赤.md

[2026-09-05] - circuit_breaker.py実装(Phase 1 Task 13)

Added

  • circuit_breaker.py ブレーカMVP(CLOSED→OPEN→HALF_OPEN・プロバイダ単位): 60秒窓内threshold回のfailureでOPEN・cooldown_seconds(既定300秒=BACKOFF_MAX)経過後にHALF_OPEN遷移→probe_required回のプローブ成功でCLOSED復帰
  • round7修正条項の管轄分離を明示: cooldown=「OPEN→HALF_OPEN遷移までの待ち」・Retry-After未指定時の指数バックオフ(base 2.0秒・full jitter)はリトライ層(Mixin/ループ)の管轄と文書化
  • export_state() 新設(round7修正条項: breaker復帰判定をstate経由で): breaker_state/breaker_opened_at/probe_attempts/probe_resultsをRunState(Task 12)と結線
  • テスト7件(FakeClock注入でcooldown経過を決定論的に検証)
  • 既知不整合を記録: plan本文のprobeテストはcooldown既定300秒のままだと通らない(windowとcooldownの混同)→ テスト側で明示渡し(plan改訂はせずdocstringに記録)

Fixed

  • 3機MLR採用4件(commit 1aeca1ed): record_probe_failure にHALF_OPEN以外の誤用ガード(CLOSED中の誤呼びで強制OPENしない)・probe_attempts を成功/失敗両方で加算・窓判定の二重フィルタ排除・record_failure の非429セマンティクスをdocstring明記。テスト10件(境界値: cooldown±0.1秒込み)

[2026-09-04] - run_state.py実装(Phase 1 Task 12)

Added

  • run_state.py 原子的状態保存・quarantine・ロック(spec §5/§10・round7修正条項3件反映): RunStateStore.save() が SaveResult.SUCCESS/PARTIAL_FAILURE を返却(Task 14ループがPartialFailureでabort判断)・load_or_quarantine() は起動時scanで *.tmp を発見した場合に本体+checksum有=本体採用・無=quarantine化
  • RunState 拡張(round7修正条項・breaker復帰判定をstate経由で行う): breaker_opened_at: str|None・probe_attempts: int・probe_results: list[bool] を追加(to_dict()で永続化)
  • ファイルロックは fcntl.flock 固定(spec §10: Linux/WSL前提・Windows対応はPhase 5以降)
  • テスト7件(原子write/破損quarantine/orphan temp×2/PartialFailure/breaker拡張/fcntl可用性)→ harness計67件PASSED(既存diagnostics環境依存1件は先行存在確認済み)

[2026-09-04] - 読む系tools 3種実装(Phase 1 Task 11)

Added

  • 読む系tools 3種(src/nexuscore/harness/tools/read.py): read_file / list_dir / search_text・テスト7件(harness計57件中・1件は本変更と無関係の既存環境依存失敗=diagnosticsのサブプロセスPYTHONPATH問題・先行存在確認済み)
  • ToolResult dataclass新設(round7修正条項①): read_file が1MB超過時に ToolResult(status="too_large", size, allowed_max) を返す(plan本文のValueError送出を修正条項が上書き・fail-soft継続・Task 17/20のnot_found/ambiguous/would_exceed_limitも本型に統一予定)
  • list_dir deny_paths事前フィルタ(round7修正条項②): deny_paths一致エントリをLLMに見せる前に隠蔽・照合はtool_gateと同一セマンティクス(glob×normpath+ファイル名単体)・非list型は全隠蔽(fail-closed・tool_gate deny-all相当)
  • tool_policy.yaml 初期版(読む系3道具=allow・provider_priority/provider_insecure_default)

[2026-09-01] - G1陽性対照実験完走 + deny_paths fail-open修正

Fixed

  • deny_paths 非list型を破損扱いで deny-all(境界①・L438): 文字列 deny_paths: 'denied' が1文字ずつfnmatchされ保護が無効化される(=fail-open)実測バグを isinstance(deny_paths, list) ガードで構造的に排除(非listはDENY+reason付与)

Added

  • G1境界テスト5件(deny_paths非list deny-all / 0バイトポリシー deny-all / 略記文字列conf deny / mock複数tools先頭選択 / _flush 例外伝播)→ harness計50件 PASSED
  • ミューテーションG1陽性対照実験完走: baseline中央値1.22s(n=5・分散+44.3%<50%閾値)・手動パッチ変異5件(M1〜M5)が境界テスト全てkill+リバース検証全pass=陽性判定(事前固定基準「3件以上・fail-open系1件以上」を達成)

Notes

  • 変異テスト詳細は obsidian-ssot 01_DECISIONS/NexusCore/2026-09-01_ミューテーションG1陽性対照実験完走.md・境界対応表 00_SYSTEM/マルチLLMレビュー/2026-09-01_ミューテーション導入判断レビュー/g1_mutation_table.md

[2026-09-01] - ToolGate.evaluate引数改名(args→tool_args・ミューテーション対応)

Changed

  • ToolGate.evaluate の仮引数 args を tool_args に改名: mutmut 3.5.0 が生成するラッパーが内部変数 args = [] を作り仮引数と衝突し、クリーン(変異なし)状態で引数辞書が空リスト化する実測バグへの対処(sentaku C案確定・キーワード専用引数のため spec §4 の契約は不変・テスト15call site更新)
  • テスト45件 PASSED・mutmut再実行で clean test 通過を確認(G0: 106ミュータント生成/G3: 26.9秒・通常実行の約10.8倍)

Notes

  • mutmut生存ミュータント39件はトリアージ保留(サンプル: 初期値dead store等の等価ミュータント+conf非dictガードの未テスト=P2起票済み境界③と一致)

[2026-09-01] - Task 10 push後3機レビュー対応(セキュリティ欠陥3件修正)

Fixed

  • ネストされたargsのdeny_paths回避(Gemini critical): args.values() の浅いスキャンでは {"paths": ["denied1.txt"]} のようなlist/dict内部の文字列が検査対象外になり deny を回避可能だった。_iter_arg_strings() で再帰列挙に修正
  • ../ トラバーサルのパターンマッチ回避(Gemini high): src/../.git/HEAD が '.git/**' パターンに一致せず回避可能だった。os.path.normpath() で正規化してからマッチ
  • UnicodeDecodeError 未捕捉(両機指摘): 破損バイト列のポリシーで __init__ が例外送出=fail-closed崩れ。捕捉に追加
  • FIFO等特殊ファイルでの無限ブロック(Gemini fail条件): is_file() 事前検証を追加し、特殊ファイルは破損扱いで fail-closed
  • tools: null で _loaded=True になる不整合(MiniMax high+Gemini med統合): toolsセクションの構造検証を追加し破損扱いに。非dictポリシー時の「コメントと実装の乖離」も解消

Changed

  • deny reason にヒットしたパス値を含め機械可読prefix化(ask required but channel unavailable 等)・deny_paths優先順位(deny最強)をdocstring明記・load_policy 戻り値を dict[str, Any] に強化

Added

  • テスト5件追加(ネストdeny/トラバーサル正規化/FIFO fail-closed/デコード破損/tools null)→ harness計45件 PASSED
  • レビュー正典: obsidian-ssot 00_SYSTEM/マルチLLMレビュー/2026-09-01_Task10-ToolGateレビュー/(MiniMax 13+Gemini 5・OpenRouterは2回502で2機統合)

保留(Phase 2以降)

  • YAML重複キー検出(後勝ちの危険性指摘)・ツールスキーマ由来のpath引数特定(過剰拒否対策)・askタイムアウトの本体実装(ループ側)・判定logger

[2026-09-01] - エージェントハーネス Phase 1 Task 10(ToolGate fail-closed + policy loader)

Added

  • src/nexuscore/harness/tool_gate.py: 権限ゲートToolGate(spec §4)。道具1回ごと個別判定(束ね承認不可)・Mode(StrEnum: allow/ask/deny)+GateDecision(mode/reason)。deny_paths(fnmatch glob)をdefaultより先に評価・未登録tool=deny(保守側既定)・ask_supported=False時はdeny(Phase 1に確認チャネル無し→書く系はdeny)
  • src/nexuscore/harness/config.py: load_policy() — tool_policy.yamlローダ(非dictは{"tools": {}}へ正規化・例外は握りつぶさず上位へ)
  • テスト追加: tests/harness/test_tool_gate.py 9件 → harness計40件 PASSED

Fixed

  • plan雛形のfail-closed穴: 雛形はFileNotFoundErrorのみcatchで、YAML構文破損時にyaml.YAMLErrorが素通りし(除句にyaml import無しのNameErrorも潜在)非dictポリシーでクラッシュ=fail-open相当。破損判定を「ローダ結果の構造検証+広範catch(FileNotFoundError/yaml.YAMLError/OSError)」に統一
  • plan雛形テストの自己矛盾: 雛形テストはask_supported=FalseでASKを期待するが雛形実装・spec §4(askタイムアウト=deny)の方向はDENYが正。テストをask_supported=Trueでの独立性検証に修正

Notes

  • 検証網羅区分: 正常系4件(個別判定/deny_paths/読むallow/ask対応時ASK)・境界1件(未登録tool=deny)・異常系4件(ポリシ不在/YAML破損/非dict/ask非対応)
  • 判定のrunイベントログ記録(spec §4)はループ側責務として本クラスでは行わない(Phase 1 MVP・YAGNI)

[2026-09-01] - エージェントハーネス Phase 1 Task 9(LocalLLM用tool_callダミー)

Added

  • src/nexuscore/harness/mock_provider.py: LocalToolCallDummyLLM — LocalLLMを内包するテスト専用ラッパー。先頭tool名のダミーInternalToolCall(args空dict・呼び出し側で補完する設計)を返す。実HTTPは一切叩かずlast_call_modeは常にstub。capability tableには一切触れない(plan 1959行「mock実行時はcapability更新禁止」・テストで固定済み)
  • テスト追加: tests/harness/test_mock_provider.py 6件 → harness計31件 PASSED

Notes

  • plan雛形からの変更点: ①雛形はtoolあり応答でcontent: Noneを返すがToolCallingMixinの戻り値契約はcontent: strのため""に修正 ②雛形の_innerが未使用でwrapが形骸化するためmodel_name/last_call_modeを委譲する契約を追加
  • 検証網羅区分: 正常系3件(tool_call返却/契約準拠/wrap委譲)・境界1件(tools空)・異常系2件(オフラインstub保証/capability不触)

[2026-08-31] - エージェントハーネス Phase 1 Task 8(capability table実装)

Added

  • src/nexuscore/harness/capability.py: provider単位のcapability table(CapabilityTable)。spec §10 のスキーマ {supports_tool_calling, last_verified_at, schema_version} を JSON で原子的書き込み(temp+rename)永続化。パスは NEXUSCORE_CAPABILITY_PATH 環境変数で上書き可(既定 artifacts/harness/capability.json)
  • 更新契機3系統API: ①Phase 0バルク書込=update_many() ②Mixin初期化時/③明示的refresh=set()。supports_tool_calling(provider_id) は計測済みならbool・未計測なら None(False と区別・fail-closed側)
  • テスト追加: tests/harness/test_capability.py 7件(スキーマ永続化 / tz-aware ISO / 再構築 / 未計測None / バルク / 上書き / .tmp残存なし)→ harness 計22件 PASSED

Notes

  • plan雛形からの変更点: 雛形に無い update_many() を追加(雛形の set() のみでは spec §10 の「更新契機3系統」契約を満たせないため)・utcnow()(Python 3.12 非推奨)を now(dt.UTC) に変更
  • Mixin初期化時/refresh 系統の実際の配線(ToolCallingMixin 側からの呼び出し)は後続タスク(ToolGate/ループ統合)で実装
  • 実装中に Write 出力が途中で崩壊し汚染ファイルを書き込む事故が1回発生 → Read実体確認後、分割書込で再生成して復旧(テスト7件で機械検証済み)

[2026-08-31] - エージェントハーネス Phase 1 Task 7(残り3プロバイダー Mix-in)

Added

  • OpenAICompatLLM Mix-in: class OpenAICompatLLM(ToolCallingMixin, BaseLLM) — GLM/MiniMax/DeepSeek/Moonshot の基底。adapter は OpenAILLM と同じ構造(OpenAI互換のため identity 変換)。HTTP 経路は既存 self.session/api_path を再利用、stub 時は固定 echo tool_call 応答
  • AnthropicLLM Mix-in: class AnthropicLLM(ToolCallingMixin, BaseLLM) — Anthropic 専用 adapter。messages 先頭の system ロールを system フィールドに分離、tools は {name, description, input_schema} 形式に変換。content 配列の tool_use/text ブロックを分離抽出。/v1/messages にPOST、stub時は固定 tool_use 応答
  • GeminiLLM Mix-in: class GeminiLLM(ToolCallingMixin, BaseLLM) — Gemini 専用 adapter。generateContent 形式の contents[].parts[] ↔ OpenAI messages、tools[].functionDeclarations[] ↔ tools を相互変換。HTTP直接叩き(/v1beta/models/{model}:generateContent?key={api_key})、既存SDK経路(execute())とは別経路
  • テスト追加: tests/harness/test_tool_calling_mixin.py にパラメタライズド6ケース追加(OpenAICompat/Anthropic/Gemini × complete_with_tools stub / MRO確認)→ 計14件 PASSED

Notes

  • 各adapterは Task 6 の防御ガード(choices空 / message不在 / tool_call.function.name不在 / candidates空 / parts不在 / name不在)を反映済み
  • 既存tests/llm/ 638 passed・5 errors は pytest-mock 未導入による事前壊れ(5a0140db HEAD でも同じ失敗を確認済み)→ Task 7 由来ではない新規回帰ゼロ
  • tests/llm/logs/ はNexusCoreの追跡外ディレクトリ(以前からの未追跡物・触らない)

[2026-08-31] - セキュリティレビュー対応(Task 6 push後の自動レビュー指摘)

Changed

  • _call_http_tool の real_calls 経路を execute_real_or_fallback で包む: HIGH指摘対応。r.raise_for_status() + r.json() の生例外を投げず、C5(silent-fallback)対策のフォールバック経路と NEXUSCORE_ALLOW_STUB_FALLBACK 互換性を回復
  • _adapt_response_native_to_internal の防御ガード: MEDIUM指摘対応。choices 空 / message 不在 / tool_call.function.name 不在を KeyError/AttributeError でクラッシュさせず、空 tool_calls を返す安全側に倒す
  • テスト追加: tests/harness/test_tool_calling_mixin.py に4ケース追加(empty_choices / missing_message / tool_call_without_function_name / stub_path_unchanged)→ 計8件 PASSED

Security

  • finding 1 (HIGH): _call_http_tool の例外処理を execute_real_or_fallback で統合
  • finding 2 (MEDIUM): _adapt_response_native_to_internal の防御ガード追加

[2026-08-31] - エージェントハーネス Phase 1 Task 6(OpenAILLM への Mix-in・template provider)

Added

  • Mix-in 適用: src/nexuscore/llm/providers/openai_provider.py:11 の class OpenAILLM(BaseLLM) を class OpenAILLM(ToolCallingMixin, BaseLLM) に変更
  • 3差分フック実装(OpenAILLM):
    • _adapt_request_openai_to_native: {model, messages, tools, **kwargs} を返すだけの identity(OpenAI ネイティブ=OpenAI 形式のため変換不要)
    • _adapt_response_native_to_internal: OpenAI chat completions の choices[0].message.tool_calls を InternalToolCall.from_openai で中立表現に変換
    • _call_http_tool: 既存 self.session / Azure設定 / self.real_calls を再利用する HTTP 経路。stub モードでは固定の echo tool_call を返す(Task 9 の force_429 と区別)
  • テスト: tests/harness/test_tool_calling_mixin.py 4件 — 必須3キー / InternalToolCall変換 / MRO確認 / adapt_request

Notes

  • 既存テスト(harness/以外)は Task 5 完了直後の HEAD (71c945ed) で同じく6件失敗していたことを実測で確認(fakeredis/python-patch/gradio の依存未導入・debugger_agent系ロジック)→ Task 6 による新規回帰ゼロ
  • Phase 0 撤退判定(Task 4)で承認済み・Task 6 着手OK

[2026-08-31] - エージェントハーネス Phase 1 Task 5(ToolCallingMixinスケルトン)

Added

  • ToolCallingMixin: src/nexuscore/harness/tool_calling_mixin.py — OpenAI/Anthropic/Gemini 3形式の tool calling 差分を吸収する Mixin のスケルトン
    • InternalToolCall: 内部中立表現(name/args/id・__slots__ 制限)。from_openai/from_anthropic/from_gemini の3変換 + to_openai の書き出し
    • _sanitize_id: spec §10 の正規化(^[a-zA-Z0-9_-]{1,64}$)— 不正文字除去・64字カット
    • ToolCallingMixin.complete_with_tools: OpenAI 形式 messages/tools → {content, tool_calls, usage} の公開 API
    • 3フック _adapt_request_openai_to_native / _call_http_tool / _adapt_response_native_to_internal は NotImplementedError のまま Task 6/7 で provider 別 override する設計

Notes

  • Phase 0 撤退判定(Task 4)で「全項目非該当」を別セッションで確定後に着手。詳細: 01_DECISIONS/NexusCore/2026-08-31_phase0_failfast判定.md(SSOT)
  • 既存 tests/harness/(diagnostics テスト1件)の回帰なし

[2026-08-31] - orchestratorパッケージ利用実態棚卸し(デッドコード判定)

Added

  • 棚卸しレポート: docs/refactoring/orchestrator利用実態棚卸し-2026-08-31.md — src/nexuscore/orchestrator/(1373行・テスト15ファイル)の全参照マップと3択判断

Notes

  • 判定: ① 統合維持(デッドコードではない)。REST API(POST /api/v1/runs 等)経由で uvicorn 本体から全モジュール到達可能・src内孤立モジュール0件(grep実測)。CLI(main_cli)・webapp経路は本パッケージ不使用
  • テスト実測: tests/orchestrator 111 passed / 7 skipped(main_cli配線の未実装skip)・tests/api run_view 11 passed / 1 xfailed
  • skip 2件が stale monkeypatch(_load_guardian_credentials 廃止追従未実施)— フォロー候補としてレポートに記録

[2026-08-31] - エージェントハーネス Phase 0(fail-fast spike)実施

Added

  • diagnostics CLI: src/nexuscore/harness/diagnostics.py — mro / override_check / factory_pos / retry_diff / tool_echo / ack の6サブコマンド(計測結果は artifacts/phase0/・gitignore対象)
  • Phase 0判定基準: artifacts/phase0/CRITERIA.md(撤退判定基準の凍結)+ CHECKLIST.template.md
  • テスト: tests/harness/test_diagnostics.py

Changed

  • plan雛形コードのバグ4件を修正して実装(argparseサブパーサー二重登録 / --out 無視 / override_checkの継承メソッド誤拾い / retry_diffの共通HTTP層〔http_client.py urllib3 Retry〕見落とし)
  • tool_echo は実HTTP呼出を試行し結果をありのまま記録する方式(ok捏造なし)

Notes

  • 計測結果: 全項目で撤退基準非該当(MRO全OK・mixin_overlap=[]・実効リトライ欠落0・echo往復 glm/minimax/openrouter/deepseek の4種成功・openai=429レート制限で未確認・moonshot=APIキーなし)
  • Task 4(撤退判定)は別セッション+ふくけい承認で実施(Phase 1着手は未確定)

[2026-08-30] - エージェントハーネス設計フェーズ完遂(spec + 実装計画)

Added

  • 設計spec: docs/superpowers/specs/2026-08-30-nexuscore-agent-harness-design.md — Claude Codeのようなエージェントハーネス(tool callingループ+権限ゲート+サーキットブレーカ)を自前実装する設計。D案(フォーマット別Mixin共用方式・4クラスへMix-in)+MVP/強化層の2階層化
  • 実装計画: docs/superpowers/plans/2026-08-30-nexuscore-agent-harness.md — Phase 0〜5・27タスクのTDD構成計画(Phase 0 fail-fast spike→読む→書く→撃つ→Web UI→dogfooding)
  • レビュー: multi-llm-review triple 7ラウンド計132件の指摘を統合(経緯: obsidian-ssot 00_SYSTEM/マルチLLMレビュー/2026-08-30_NexusCoreハーネス方式選定/)

Notes

  • 本エントリは設計フェーズのみ(実装は未着手・Phase 0から次セッションで開始)
  • 既存コードへの変更はゼロ(spec/plan/docs追加のみ)

[2026-08-29] - A群消化: 脆弱性4件解消・CI保護強化・テストの完全オフライン化

Security

  • 既知脆弱性4件を解消(pip-audit 実走で検出・修正後は No known vulnerabilities found): Flask-CORS 4.0.2 → >=6.0.0(PYSEC-2026-1383/-1384/-1385)・pytest 7.4.4 → >=9.0.3(PYSEC-2026-1845・9.1.1で5,029テスト緑を確認)
  • 未使用依存5件を削除: torch / tensorflow / SpeechRecognition / websockets / psutil(AST実測で実import 0件)。pydub/standard-aifc は維持 — gradio が import 時に pydub を要求する実行時推移依存のため(コレクションエラー4件で実測・「直接import 0件」でも削除不可の反証実績)
  • pip-audit を CI ゲート化(sca-scan job 新設・requirements.txt 対象)
  • gitleaks を独立 workflow 化(secret-scan.yml): push/PR=差分走査 + 週次 schedule(月曜 03:23 UTC)=全履歴走査で「push時は差分のみ」との宣言乖離を解消
  • vscode-extension/node_modules/ 3,075ファイルを追跡解除(package-lock.json は追跡維持)・孤児 submodule gitlink 削除(tree_sitter_languages/tree-sitter-python・CI post-checkout の exit 128 warning 解消)

Fixed

  • utils/tree_sitter/_analyzer.py:238 のログ書式バグ(%.1%% → %.1f%%・2026-05-12混入の潜在バグ。pytest 7 は握りつぶし pytest 9 は致命化)
  • networkx を明示依存に追加: analyzer/graph_builder.py の直接importが torch の推移依存で暗黙供給されており、torch 削除で CI 新規環境のみ収集エラー3件(2026-08-30 実測)。fresh venv からの再インストールE2Eで 5,027 passed を確認
  • テスト中の実ネットワーク呼び出しを禁止: LLMRouter.__init__ の _detect_and_update_models が OpenAI/Gemini models.list に実HTTPSリクエストを送っていた(cProfile 実測: 単一テストで28リクエスト・20.5秒)。既存スイッチ NEXUS_DISABLE_MODEL_DETECTION を conftest で有効化 → スイート 876s → 149.68s(約6倍高速化)かつネットワーク非依存の決定的実行に

Changed

  • Python バージョン宣言を3.12へ統一: .python-version 3.11.9 → 3.12.3・ci.yml security-scan job 3.11 → 3.12
  • Safe Tests workflow を削除: ci.yml test job と同一スイートの重複実行・独自 env 変数(NEXUSCORE_DISABLE_REAL_LLM 等)はコード参照ゼロの実測に基づく
  • pytest 9.1.1 移行(7.4.4 → 9.1.1): 5029 passed / 187 skipped / 26 xfailed / 12 xpassed

検証証跡(全て生 exit code 0)

  • pytest -q: 5029 passed, 187 skipped, 9 deselected, 26 xfailed, 12 xpassed in 149.68s
  • mypy src/: Success(255ファイル)・ ruff check src/ tests/: All checks passed
  • pip-audit -r requirements.txt: No known vulnerabilities found
  • 起動スモーク python main_cli.py --help: usage 出力

[2026-08-29] - 包括レビュー(差分・コード変更なし)

Audit(レビューのみ・本エントリによるコード変更は無し)

  • 2026-08-12 包括レビューの10件を実測で答え合わせ。完全解消1件(生成物90+件のgit追跡解除・src/sandbox_logs tracked=0)・部分解消3件(CI静的解析配線/mypy.ini の3.12是正/tests→app/ 直import 20→0)・未解消6件。循環依存 5組→5組・api → webapp 28→28 と同値、README は乖離が拡大
  • 品質ゲート実走: ruff check src/ tests/ exit 0 / mypy src/ exit 0(255ファイル)/ pytest -q 5029 passed, 187 skipped, 27 xfailed, 11 xpassed exit 0(123.19s)

Security(要対応・未修正)

  • pip-audit -r requirements.txt で既知脆弱性4件を検出(exit 1): flask-cors 4.0.2(PYSEC-2026-1383 / -1384 / -1385 → Fix 6.0.0)・pytest 7.4.4(PYSEC-2026-1845 → Fix 9.0.3)。requirements.txt の上限 Flask-CORS<5.0.0 / pytest<8.0.0 が修正版の取り込みをブロックしている。pip-audit は requirements-dev.txt に導入済みだが CI に未配線(semgrep detect-secrets も同様)

検出された未整理(新規・前回未検出)

  • vscode-extension/node_modules/ が 3,075ファイル / 442,980 LOC git追跡下(自作の拡張コードは10ファイル / 3,598 LOC のみ)。logs/ 75ファイル / 34,586 LOC も追跡下
  • CI の ruff ジョブは src/ tests/ のみを対象とし、tools/(56py) scripts/ dev_tools/ app/ database/ main_cli.py は未 lint → ruff 1,160件(660件は --fix 可)。複雑度ワーストも tools/ に集中(code_export_for_ai.py:569 CC=45・stit_branch.py:640 main 341行)
  • Python バージョン宣言が4箇所で不一致(pyproject >=3.12 / .python-version 3.11.9 / ci.yml:27 3.11 / safe-tests.yml:42 3.11)
  • README の陳腐化: src/nexuscore/audio/ は不在・「5,465テスト」主張(4箇所)に対し実測収集 5,237・「84.69%」に対し coverage.xml は 84.99%(かつ 2026-07-08 生成で44コミット前)・「Pylint 8.0+」だが pylint の宣言は0件
  • 詳細記録: obsidian-ssot/01_DECISIONS/NexusCore/2026-08-29_包括レビュー差分-前回10件消化状況と新規3件.md

[2026-08-21] - FKB真因判別・案1: Debugger指示文の候補解化(アンカリング緩和)

Changed

  • agents/debugger_agent.py: KBヒット時のLLM指示文を命令形 Apply the following pattern から「候補解提示+真因一致確認の要求」(同一シグネチャでも真因は異なり得る旨・不一致時は棄却して通常分析)へ変更。Zenn記事への realbios氏コメント(シグネチャ既知≠真因既知・知識の粒度を「答え」でなく「切り方」に)の指摘が debugger_agent.py:146-148 の命令形指示とFKB実データ102件のsignature→solution直接対応で実際に当てはまることの検証結果(2026-08-19)を受けた第一段階対応。案2(FKBスキーマへ candidate_causes[]+discrimination[] 判別プローブ追加)は後続
  • テスト: tests/agents/test_debugger_agent.py に test_kb_instruction_treats_solution_as_candidate 追加(candidate/verify 含有・命令形文言の不在を検証)

[2026-08-18] - C3 Plan2: Orchestrator内部冪等性(phaseチェックポイント+LLM結果キャッシュ)

Added(C3 Plan2・マルチLLMレビュー+L3弁証論反映)

  • core/run_checkpoint.py: チェックポイント単一キーcheckpoint:{run_db_id}(1回SET=アトミック・schema_version・512KB超zlib圧縮)+run_phases_with_checkpoint()(完了phase skip・heartbeat_fn依存注入)+LLM結果キャッシュ(フルハッシュ・TTL24h)+timeout1s+60sサーキットブレーカ
  • orchestrator.py/orchestrator_helper.py: phaseループ委譲+heartbeat_fn経路貫通(CLI実行=run_db_id Noneは無効)
  • _execute_task_via_npe: LLMキャッシュhit時guarded_llm_call skip(hit/missログ・NEXUSCORE_LLM_CACHE=0/NEXUSCORE_CHECKPOINT=0で無効化)
  • celery_app.py: 実行ロックTTL 30s→600s+phase完了heartbeat(並走防止)・ロック失敗時は660s後retry(タスク消失防止)・不変条件LOCK_TTL<visibility_timeoutをCIテスト固定・SUCCESS時checkpointクリア
  • テスト環境では NEXUSCORE_LLM_CACHE=0 をconftestで既定設定(実Redis稼働環境でのテスト間キャッシュ衝突防止)

Fixed(マルチLLMレビュー MiniMax+Gemini 採用6件・2026-08-18)

  • run_checkpoint.py: 未知phase名のKeyErrorクラッシュ→警告+フル再実行に退化 / get_client接続プールをURL-keyedキャッシュ+atexitクロース / llm_cache_keyのmodel=Noneガード / OrchestratorContextをmodule-level import(テスタビリティ) / ブレーカのプロセスローカル性を明記
  • celery_app.py: SUCCESS時checkpointクリアをcommit後(finally)へ移動(commit前クラッシュ→再配送フル再実行の窓縮小)+ final_status早期初期化(空requirement早期returnでのUnboundLocalError→実行ロックリーク修正)+ ロック解放回帰テスト
  • レビュー詳細: obsidian-ssot 00_SYSTEM/マルチLLMレビュー/2026-08-18_C3Plan2実装レビュー/

[2026-08-18] - Safe Tests workflow赤修正(Redis service追加)

Fixed

  • nexuscore-safe-tests.yml: C3冪等性テスト(test_celery_job_state_machine 3件)と test_fastapi_project_runs.py::test_trigger_project_run_success が実Redis localhost:6379を参照するため、ci.ymlと同一の redis:7-alpine サービスコンテナを追加(2026-08-15のci.yml CI赤復旧時にsafe-tests側への追加が漏れていた・19連続赤の直近原因)

[2026-08-17] - nexuscore-bench Phase 0: 壁2/壁3解消+FKBフルループ実証

Fixed(学習ルートの本質バグ2件・nexuscore-bench検証で発見)

  • debugger_agent.py _generate_fixed_code: LLM応答全体をコードとみなす仕様を改め、```pythonフェンス優先でコード抽出(「説明文+コード」応答で説明文ごと書き込みSyntaxErrorになる事故を根本修正)
  • debugger_agent.py: LLMがunified diff形式で回答した場合に元ソースへ適用してfixed codeを再構成(diff本文がそのままコードとして書き込まれる事故を修正)
  • knowledge_curator_agent.py: サンドボックス検証失敗時にpytest出力tailをログ(観測フック・上記バグ特定の鍵)

Added(nexuscore-bench Phase 0・spec: obsidian-ssot 2026-08-17-nexuscore-bench-design.md v1.1)

  • 壁2-A: patch_applier.py に削除行数上限ガード(max_delete_lines=20・SelfHealingConfig 連携)
  • 壁2-B: _guardian_helpers/ast_safety.py(削除適用後のAST安全検証+適用前スナップショットからのロールバック・reject時は人手承認フラグ)
  • 壁3: タスク単位LLBプロファイルenv上書き(NEXUS_TASK_MODEL_<TASK>・例: DEBUG=gemini_secondary。カテゴリ単位envより優先・未設定で完全不変の後方互換)
  • FKB参照ログ: knowledge_reference_logs テーブル+log_reference/query_references/get_id_by_signature(bench主指標の前提)+Alembic migration a7c3f91d5e02
  • FKB運用: snapshot(全エントリJSON書出)+disabled論理削除+scripts/fkb_ops.py CLI(汚染スパイラル対策)
  • scripts/verify_fkb_fullloop_real.py: フルループE2E検証(失敗→postmortem→curator→FKB保存→次タスク参照→修正成功)

Verified

  • FKBフルループE2E: 4/4 (100%)(postmortem/debug=Gemini 3.1 Pro・curator=MiniMax・隔離sqlite)
  • 全テスト回帰: 4,995 passed(ベースライン4,975+新規20件・回帰ゼロ)・ruff緑
  • GLM現行ルーティングでは0/4(GLM 429連発+修正品質不足の実証データ→壁3再定義: 「出力パース堅牢性」が本質障壁の一つだった)

Fixed(mypy src/ 17エラー→0)

  • phase_runner_mixin.py: ホスト(Orchestrator)が提供する architect_agent/guardian_agent/constitution を TYPE_CHECKING ブロックに型宣言(mixin契約の明文化・6エラー解消)。docstring の契約列挙も実態より古かった
  • openrouter_key.py ×3: current_user.id(AuthenticatedUser に存在しない属性=実行時 AttributeError の潜在バグ)→ get_user_id_from_auth() 変換アダプタ経由に修正(_projects_runs.py と同じパターン)
  • guardian_agent.py: self.model の or 合成が str | None になるのを条件式で str に確定(空文字フォールバックの実挙動は不変)
  • unified_analyzer.py: _save_analysis_cache に self.cache is None ガード追加+2ループ目の変数名衝突(file_hash の再代入で str None 化)解消
  • unified_config.py: os.getenv("FLASK_SECRET_KEY", ... else None) が str 型フィールドに None を入れうる型違反を解消(本番未設定時 None→空文字=Flask が起動拒否・実挙動ほぼ不変)
  • retry_utils.py: 新 mypy(1.20系)で不要になった stale な type: ignore[arg-type] を除去
  • mypy.ini: python_version 3.11→3.12 是正(pyproject requires-python>=3.12)・api/archive を exclude 追加(非現用コード・bandit/ruff と同じ除外方針)・未使用セクション(プリフィックス無し github_webhook)除去・UI層の attr-defined 無効化(gradio の minor バージョン差でイベント属性型定義が変わるため: ローカル実証 6.13 vs CI解決 6.24 で Button.click 等が16エラー・他エラーコードは検査継続・commit 5168227e)

Added(CI)

  • ci.yml test job に mypy ステップ(mypy==1.20.2 固定・mypy src/)を追加。依存未インストール環境では mypy 結果が変わる(pydantic 等の型情報が必要・空venv実測で32エラー)ため、フル依存インストール後の test job 内で実行する構成(別 job 化しない理由)

Verified

  • mypy: Success: no issues found in 253 source files(python 3.12・archive 除外)
  • 回帰: config+analyzer+api 622 passed / core 911 passed / guardian 3 passed・ruff src/tests 緑

[2026-08-15] - C6 Step2: ruff CI ジョブ追加・gitleaks 実効化

Added

  • ci.yml に Lint (ruff) ジョブ(src/ + tests/ 範囲・ハードゲート)を追加。src/tests の ruff 緑(2026-08-14 達成・commit 327c4a18)を CI で永続担保。走査範囲は src/tests のみ(scripts=30件・tools=1070件の残存違反は P2 対応後に拡張)。ruff>=0.15.0,<1.0.0(ローカル実測 0.15.12 に揃え・requirements-dev.txt 範囲内)
  • gitleaks を実効化: continue-on-error: true を除去し、検出で CI が赤になるよう変更(2026-08-05 導入以降の検出ゼロを確認済み)

Changed

  • README の静的解析宣言を実態に更新: ruff(src/tests 全走査・CI必須ゲート)+ gitleaks(CI必須ゲート)・mypy は src/ 残17エラー解消後に CI 導入予定

[2026-08-15] - CI 赤化解消(GitPython 依存追加)

Fixed

  • CI が 2026-08-01 以降全 run failure していた問題を解消(収集エラー2件+テスト失敗7件の計9件・CI赤の2週間で回帰が表面化せず潜んでいた):
    • src/nexuscore/agents/guardian_agent.py:8 の import git(GitPython)が requirements.txt に未宣言で、CI(クリーン環境)でのみ ModuleNotFoundError: No module named 'git' により7テストファイルが収集エラー→全テスト未実行(exit 2)。ローカル .venv には入っていたため気づかず。requirements.txt に直接依存として GitPython>=3.1.40,<4.0.0 を追加(lock 側は既に gitpython==3.1.45)
    • tree_sitter_checker.py から CONFIG/TREE_SITTER_AVAILABLE/Style の legacy re-export を復元: 2026-08-02 commit 8229ac0f(ruff F401 機械除去)がテストが利用する公開シンボルまで削除。AnalysisResult には # noqa: F401 — legacy re-export 保護が付いていたのに CONFIG 群には付いていなかったのが直接原因。noqa 保護付きで復元
    • _projects_runs.py の関数内 from fastapi import HTTPException が未実行パスで UnboundLocalError になるバグを修正(module level import に統合)。project_not_found 時 404 でなく 500 を返していた
    • celery_app.py: タスク直接呼び出し(テスト)で self.request.id が None のまま Redis SET に渡り DataError: NoneType になるのを uuid フォールバックで修正(acquire/release 両方)
    • test_external_api_smoke.py::test_post_run_with_api_key: 全 os.getenv を “1” に上書きするパッチが C3 の task_lock.get_redis()(REDIS_URL 読み取り)を壊し 500 になっていたのを、NEXUS_USE_CELERY のみ選択化+fakeredis 注入で修正(C3 追加以降の潜在不良)
    • ci.yml の test job に Redis service container(redis:7-alpine)を追加: C3 冪等性テストが実 Redis localhost:6379 を参照するため(CI環境固有の ConnectionError 3件+500 の解消)

[2026-08-15] - C5 残課題の完全テスト追加(T6/T7 retry境界・T9 FAILED集約)

Added

  • tests/agents/test_c5_retry_boundary.py(4件): 8/13実装の retry 境界を機械検証。T6=429 HTTPError が ModelRateLimitError に変換され max_retries=2 で計3回試行+1回目429→2回目成功の復帰 / T7=恒久失敗(5xx・permission denied)は unexpected 分類で1回のみ試行の即例外伝播。既存 test_c5_exception_propagation.py は patch(HAS_RETRY, False) で retry 経路を回避しており、HAS_RETRY=True の実経路(retry_with_context wrapper)は本ファイルが初カバー
  • tests/core/test_c5_orchestrator_failed_aggregation.py(2件): T9=伝播例外で _log_orch_event(run_db_id, "orchestrator", "FAILED", ...) 発火+再 raise+FINISHED未発火(誤成功なし)+メッセージに元エラー含有。呼出側の Run.status="FAILED" DB反映は既存 tests/webapp/test_celery_app.py が担保(役割分離)

Verified

  • 新規6件: 6 passed(0.71s・retry backoff の sleep は monkeypatch で無効化)
  • 回帰: tests/agents+core+llm で 2545 passed / 41 skipped / 0 failed(12分・.venv python使用。システムpythonでは gradio 未依存の3ファイルが収集エラーになるため venv 必須)

[2026-08-14] - ruff 既存違反 tests/ 残り50件→0件解消(L158・C6 CI保護完全化の前提)

Changed

  • tests/ 配下25ファイル・50件のruff既存違反を解消(2026-08-12 src/完了の残・A+Dハイブリッド方針踏襲)
  • F841(34件)・B007(2件)・E741(1件): --unsafe-fixes --select F841,B007,E741 で機械解消(F401除外で再エクスポート壊れ回避・前回教訓)。E741の l→line は手動
  • E731(4件): lambda→def 関数化(test_fallback ×3・test_authority_runner ×1)
  • B017(3件): blind Exception を具体例外化。frozen dataclass の setattr/delete は FrozenInstanceError(import追加)・decrypt の不正 ciphertext は InvalidTag(cryptography.exceptions・import追加・元々 Exception で隠れていた正しい例外型を特定)
  • F401(2件)・F821(1件)・F811(1件)・B018(2件): # noqa で保護。streamlit/tree_sitter は try/except による import 可用性チェック(正当)・test_server_execute.py は module-level skip 済み(archived Flask)・conftest は fixture 再エクスポート

Fixed

  • test_authority_runner:896 test_uses_factory_over_global の検証不全を修正: 元は「検証ゼロの式文」(or 式・orchestrator.start は実装に存在しない)だった。state に next_phase: "planning" を追加し、実在の run_planning_phase 呼び出しで factory優先を検証(factory呼ばれる・global呼ばれないを assert)。実装(resume.py factory選択)は正常・テスト側の実装乖離だった
  • test_imports:27 の属性アクセスは pytest.raises(AttributeError) 内の正当な検証(noqa保護)

Verified

  • ruff check tests/: All checks passed!(50→0件)・ruff check src/: 緑(回帰なし)
  • 修正8ファイル pytest: 227 passed / 0 failed(16 skipped・5 xfailed は既存)
  • 残り赤は pre-existing(gradio/tree_sitter/Redis/Celery 依存・本タスク無関係)

[2026-08-13] - C5 silent stub-fallback 解消(E+α改・例外伝播)

Changed

  • llm/providers/base.py execute_real_or_fallback: real call 失敗時の return _stub_fallback_response(...) を NEXUSCORE_ALLOW_STUB_FALLBACK フラグ判定付き raise に変更(フラグOFF=本番は例外・ON=従来stub)。openai/anthropic/gemini の3プロバイダがカバー(commit 762a4b9c)
  • llm/providers/openai_compat.py: 429は従来通り raise(rate-limited)維持・それ以外のHTTPエラー/Exception を同フラグ判定 raise に変更。deepseek/glm/minimax/moonshot/openrouter の5プロバイダが継承で網羅
  • agents/base_agent.py execute_llm_task: 例外時の {}/"" 握りつぶし(base_agent.py:163-174)をフラグ判定 raise に変更(α・commit c8b6472c)。7/30「案C破壊的(握りつぶされる)」懸念へ構造的回答・二次silent封鎖

Added

  • 環境変数 NEXUSCORE_ALLOW_STUB_FALLBACK(デフォルトOFF=本番例外・=1 で従来stubを統合テスト保護・spec §4.4)
  • tests/llm/conftest.py・tests/agents/conftest.py・tests/api/test_issue_86_base_agent.py: autouse fixture で従来フォールバック挙動の後方互換(フラグON)
  • tests/llm/test_stub_fallback_exception.py(T1/T2: 発生源のフラグOFFで例外・ONでstub)
  • tests/agents/test_c5_exception_propagation.py(T5/T6/T7: αの直接検証・フラグOFFでraise・ONで{}/”“・real成功回帰)

Fixed

  • C5(CRITICAL#5): LLM失敗時にstub文字列を黙って返し下流Coder/Plannerが正規出力と誤認する silent stub-fallback を解消。発生源(プロバイダ層)+ α(execute_llm_task 最終フォールバック)の2層で例外伝播→orchestrator 既存口(run_full_project:197)で Run.status=FAILED 集約。7/30→8/5監査の再逆転(例外伝播)を完結

Verified

  • tests/llm: 645 passed(回帰ゼロ)・tests/agents: 982 passed・test_issue_86_base_agent: 11 passed
  • ruff/mypy 緑(変更ファイル)
  • 残り赤7件は pre-existing(HTTPException 既存バグ・celery・tree_sitter・α無関係)
  • spec: docs/superpowers/specs/2026-08-12-c5-stub-fallback-exception-propagation-design.md

[2026-08-12] - ruff 既存違反解消 src/+tests/(L158・C6 CI保護の前提)

Changed

  • ruff 既存違反 src/ 53件を解消: I001 import並び・UP 型アノテーション現代化・F541 空 f-string 等 safe-fix 30件 + F821/F811/B904/F401/F841 手動修正
  • webapp/orchestrator_helper.py: TYPE_CHECKING import 追加(F821 Run/Project 解消・循環import回避)+ 重複ローカル import 削除
  • api/archive/server.py: require_auth 重複定義(暫定パススルー版 line10)を削除
  • cli/app.py・api/routes/openrouter_key.py: B904 7件に raise ... from 追加(例外チェーン明示)
  • ui/settings_tab.py: 未使用 Gradio 変数を式文に変更(F841)
  • analyzer/_config.py・utils/tree_sitter/_config.py: tree_sitter 可用性検出 import に # noqa: F401(意図的 unused)

Fixed

  • webapp/auth.py: logger 未定義による OAuth callback 失敗時の NameError 二重クラッシュを修正(logging.getLogger(__name__) 追加)
  • webapp/views_projects.py: _render_run_status_badge 再エクスポートを # noqa: F401 で保護(safe-fix の過剰削除で views_dashboard/views_logs の import が壊れたのを修復)

Removed(tests/)

  • TextLocalization/StateMachine テスト削除: fbf09c7b で requirement_agent Gradio UI ごと削除されたがテストが追従せず skip 残存していた dead テスト(test_requirement_agent_comprehensive.py・test_requirement_debugger_comprehensive.py)を除去

Verified

  • ruff check src/: All checks passed!(53→0)
  • ruff check tests/: 235→50件(safe-fix 181件 + dead テスト削除 約30件解消)※残り50件(F841/F401/E731/B017等 + test_server_execute.py の dead ファイル)は別タスク
  • pytest 4905 passed(7件 failed は全て pre-existing・本変更と無関係: Redis未設定/Celery/tree_sitter_checker 未定義属性)

[2026-08-06] - Celery タスク冪等性・再実行保護 Plan1(C3・Redis SETNX分散ロック)

Added

  • src/nexuscore/webapp/task_lock.py: Redis SETNX 分散ロック utility(acquire/release/heartbeat/producer_lock・Lua script で原子 CHECK-AND-DEL・所有者誤解放防止)
  • _acquire_execution_lock ヘルパ(celery_app.py): SUCCESS skip + ロック取得をテスト可能単位に切り出し
  • _celery_idempotency_config ヘルパ: 環境変数から Celery conf 構成(acks_late/reject_on_worker_lost/track_started/visibility_timeout)
  • NotificationLog モデル: UNIQUE(run_id, event_type) で Slack 重複送信防止
  • マイグレーション 9d8346475f27_add_notification_logs(915be6eb487e の chain・autogenerate・drift検証済)
  • docker-compose.saas.yml webapp/celery-worker に Celery 冪等性設定環境変数追加(VISIBILITY_TIMEOUT=7200 は acks_late 長時間タスクに必須)

Changed

  • celery_app.py タスク装飾子: TASK_OPTIONS 定数化・acks_late/reject_on_worker_lost/bind=True/autoretry_for(一時的例外5種)/retry_backoff(最大120s)/jitter/max_retries=5
  • celery_app.py _run_orchestrator_task_internal: 本体を try/finally で囲み Redis ロック取得/SUCCESS skip/例外時確実解放(閾値ヒューリスティック撤回)
  • celery_app.py _finalize_run: Slack 通知を NotificationLog UNIQUE で冪等化
  • views_projects._dispatch_celery_run / api/routes/_projects_runs.py: producer_lock(10s) + 決定論的 task_id(orchestrator-run-{run_db_id}) で重複 enqueue 拒否(失敗時 409)

Security

  • Qiita六か条監査 CRITICAL #3 対策(Plan1): worker落ち/再配送/重複 enqueue による2重実行を確実に防止
  • multi-llm-review(Gemini+MiniMax両LLM CRITICAL一致)で当初「閾値1hヒューリスティック」を撤回し Redis SETNX 分散ロック+決定論的 task_id+producer 二重防御を採用
  • 実例: obsidian-ssot/00_SYSTEM/参考資料/LLMサボりバイアス実例/2026-08-05_閾値ヒューリスティック設計サボり-C3Celery冪等性.md

Verified

  • 22テスト全pass(task_lock 6 / celery_task_options 5 / execution_lock_guard 4 / producer_guard 2 / notification_log 2 / finalize_idempotency 1 / celery_idempotency_config 2)
  • drift検証: notification_logs マイグレーション後 “No changes”(models.py完全一致)

Constraints / 残課題(Plan2)

  • (4) Orchestrator内部冪等性は別Plan: step完了マーカー+LLM結果キャッシュ(JobStateMachine への step API 新設を含む大規模)・Plan1完了後に着手
  • PostgreSQL/Redis本番検証はdocker導入後(C1/C2と同方針)・現段階は fakeredis+SQLite 検証
  • autoretry_for 完全正規化層(RetryableError 共通基底)は Plan2 で完全化

[2026-08-05] - DBマイグレーション初期スキーマ管理(C2・autogenerate + migrateサービス分離)

Added

  • migrations/versions/915be6eb487e_initial_schema_6_tables.py: 初期スキーママイグレーション新設(users/projects/runs/patch_records/execution_logs/api_keys の6テーブル・全index・FK・openrouter_key_enc 含む)。Flask-Migrate autogenerate で models.py から機械生成(手書きによる型・命名ズレ防止)
  • docker-compose.saas.yml: migrate one-shot サービス追加(command: ["flask","db","upgrade"]・restart: "no"・db healthy 待ち)。webapp/celery-worker は depends_on.migrate.condition: service_completed_successfully でマイグレーション完了後に起動
  • Dockerfile.webapp: FLASK_APP / PYTHONPATH を ENV に明示(standalone・flask db CLI 実行時の app context 不足防止)

Changed

  • docker-compose.saas.yml: webapp/celery-worker の depends_on をリスト形式から dict 形式へ昇格(db: service_healthy でDB受付待ち・起動競合回避)

Removed

  • migrations/versions/a1b2c3d4e5f6_add_openrouter_key_enc.py: 削除(clean start)。本番運用なし・既存ローカルDBは破棄前提のため、履歴 chain 化より単一初期マイグレーション(openrouter_key_enc 内包)の方が誠実。既存ローカルDB運用者は flask db stamp head または DB 再作成で追従

Security

  • Qiita六か条監査 CRITICAL #2 対策(初期スキーママイグレーション不在 → autogenerate で生成・新規本番の db.create_all() 暗黙依存を解消)
  • multi-llm-review(Gemini+MiniMax・両LLM CRITICAL一致)で方針転換: 当初「手書きマイグレーション」を撤回し「autogenerate + clean start + migrateサービス分離」を採用(手書きの index/FK 命名ズレ・将来 drift・ENTRYPOINT 起動ループ・SQLite単独検証の不十分さを封じる)

Verified

  • SQLite 一時DB で flask db upgrade → 6テーブル+openrouter_key_enc 作成を確認
  • drift 検証: upgrade 済DBに再 autogenerate → “No changes in schema detected”(models.py と完全一致)
  • 可逆性: downgrade base → 全テーブル削除 → upgrade head → 再作成の往復成功・FK 制約(5テーブル6本)正常

Constraints / 将来課題

  • PostgreSQL(本番想定)での動作検証は docker 導入後に実施(C1と同方針・現段階は SQLite 検証のみ・方言依存コードは使用せず)
  • マイグレーション権限分離(アプリ DML / マイグレ DDL の分離)は将来課題・MIGRATION_DATABASE_URI 導入を検討
  • ENTRYPOINT でのリトライ・advisory lock は Init Container(K8s)採用時に再検討

[2026-08-05] - SaaS本番DB バックアップ戦略整備(C1・sidecar + 日次pg_dump)

Added

  • docker-compose.saas.yml: db-backup sidecar サービス追加(postgres:15-alpine・scripts/backup-db.sh を entrypoint・24hループで日次 pg_dump + gzip・BACKUP_RETENTION_DAYS=7 で自動削除)
  • db サービスに healthcheck(pg_isready)追加・db-backup は condition: service_healthy で起動(db 起動前のバックアップ失敗防止)
  • backup_data ボリューム新設(db-backup が書込・db に /backups:ro で共有・リストア用)
  • scripts/backup-db.sh 新設(ash 互換・pg_dump を一時ファイル出力→gzip でパイプ失敗を捕捉・リテンション削除)
  • docs/setup/saas_db_backup_restore.md 新設(リストア手順・PITR 未対応/外部転送未対応の制限明記)

Security

  • Qiita六か条監査 CRITICAL #1 対策(本番DBバックアップ戦略不在 → 日次フルバックアップで対応・PITR/外部転送は別タスク)
  • B案(C1→C2→C3→C5→C6)の先頭タスク・sentaku L3 + nemotron レビューで「本番運用可能主張には実証根拠先決」と確定した進め方

[2026-08-05] - CI secret-scan 追加・README静的解析宣言の正直化(C6段階的+E)

Security

  • .github/workflows/ci.yml: gitleaks-action@v2 による secret-scan job を追加(git 履歴全体を走査・continue-on-error: true で警告モード導入・順次厳密化)・Bandit に加えシークレット混入を検知

Changed

  • README.md: 「ruff + mypyの静的解析も通過」を正直化。実態は「ruff は変更ファイル単位で検証(verify-post-tool-use hook)・全走査では288件の既存違反が残存(src/53+tests/235)・mypy はCI未実行」だったため、「Bandit(CI必須)+ ruff(変更ファイル単位)+ gitleaks(シークレット走査)で担保・ruff 全走査違反と mypy は段階的CI導入予定」に修正
  • C6(Qiita六か条観点監査 CRITICAL #6)の前提崩壊を記録: README宣言(ruff+mypy通過)は変更ファイル個別のみ・全走査では288件の既存違反で宣言と実態が乖離 → C6「CI保護の完全実施」は前提として既存違反の一括解消(別タスク L 粒度)が必要と判明。本次は gitleaks 警告モード追加のみ実施(small win)

[2026-08-05] - /api/v1/execute project_path バリデーション追加(C4・パスインジェクション型IDOR対策)

Security

  • api/routes/execute.py: validate_project_path 関数を新設し、/api/v1/execute の project_path を検証(Qiita六か条観点監査 CRITICAL #4 対応)
    • os.path.realpath でシンボリックリンクを解決(/tmp/evil -> /etc のような回避を防止)
    • 機密システムパス(/etc, /root, /proc, /sys, /dev, /boot, /usr, /sbin, /bin, /lib, /lib64, /var/log)配下を拒否
    • 機密ディレクトリ名(.ssh, .gnupg, .aws)をパス要素に含む場合を拒否
    • 違反時は ValueError → エンドポイントで HTTPException(400) に変換
    • 従来は os.path.abspath のみで、認証済ユーザーが任意のサーバーパス(/etc, ~/.ssh, 他人プロジェクト)でオーケストレータ(ファイル書込・subprocess実行)を起動可能だった
    • 完全なユーザー別プロジェクト隔離(project_id 経由)は別タスク(M粒度)として残置
  • テスト追加: tests/api/test_execute_path_validation.py(機密システムパス拒否12件・機密dir拒否6件・正当パス許可5件・シンボリックリンク攻撃回避2件)

Changed

  • .gitignore: .env → .env* に強化(.env.bak.* / .env.local 等の派生ファイルを包括無意・誤 git add による公開事故防止・!.env.template 例外は維持)

Fixed

  • api/routes/execute.py: 既存 import ブロック順序(I001)を ruff --fix で整理(本変更の副作用で表面化)

[2026-08-04] - pytestサブプロセス呼び出しの python ハードコード修正(sys.executable化)

Fixed

  • pytest を起動するサブプロセス呼び出し3箇所でインタープリタを PATH の "python" リテラルで固定していたのを sys.executable に変更(venv 不整合防止・実行中プロセスと同一インタープリタを使用)
    • core/phase_runner_mixin.py:461,542(run_in_sandbox 経由の pytest 実行・初回テスト&デバッグループ再テスト)
    • core/quality_regen_loop.py:43(measure_coverage のカバレッジ計測)
    • 従来は PATH の python に依存し、venv 外のシステム python が呼ばれて ModuleNotFoundError 等の不整合が起きうる状態だった。デモ作成時は symlink で応急対応していたが本質修正(handoff 2026-08-04_1117_e3d4 の未解決事項)
  • テスト追加: tests/core/test_quality_regen_loop.py::test_uses_sys_executable_as_interpreter(cmd[0]==sys.executable を機械検証)+ 同ファイルの既存 lint(I001 import sort / F401 unused QualityRegenResult)を整理

[2026-08-04] - 見せる用デモ素材追加(CLI録画GIF・スクショPNG)

Added

  • デモ用GIF: docs/demo/gifs/cli_pipeline_demo.gif(CLIパイプライン12エージェント連鎖の様子・asciinema録画→agg変換・--font-size 20・Gemini+4_5v MCP の2LLM相互検証済)
  • デモ用スクショPNG 3枚: docs/screenshots/cli_pipeline_{phase0_start,mid,phase4}.png(CLI実行各フェーズの静止画)

[2026-08-02] - 低優先度リファクタリング(コード品質スイープ低優先度残・agents/analyzer)

Changed

  • agents: policy_agent.py の ▼▼▼/▲▲▲ 装飾コメント削除、council_cli.py/council_webui.py の未使用import(pathlib.Path)除去、_fallbacks.py/council_cli.py/council_webui.py にモジュールdocstring追加
  • analyzer: context_analyzer.py/context_agent.py のWindows固有パスコメント(📁 C:\Users\USER\...)削除、graph_builder.py のImportError文に pip install networkx 案内追加、_engine.py AnalysisResult の timestamp/data 型ヒント補完
  • analyzer: context_analyzer.py の B013 冗長タプル except (OSError,) → except OSError 修正(7件・ruff自動修正)
  • llm: llm_router.py の未使用import(REQUEST_TIMEOUT)除去(#15)、_model_detection.py/_router_utils.py/llm_router.py/provider_factory.py の import 順序整形(I001・4件)
  • services: git_operations.py の base_dir に型アノテーション(str | None)付与(#13)
  • ui: settings_tab.py の未使用import除去(F401・#16関連ファイル)
  • utils: tree_sitter_checker.py の未使用import除去(F401・4件)/import順序整形(I001)、ついでに verbose 時の _logging alias 不整合による NameError 潜在バグを修正(import sortで表面化)

Fixed

  • 調査(2026-05-26)の鵜呑み回避: 実コード確認で既に解消済み(#16 マジック文字列定数化/#18 インスタンス属性化)や誤検知(#25 例外設計/#22 Sentinel値)を判定し、対象外を記録

第2セッション追加対応(58dc完了後・11コミット・新規failureなし)

58dcが「スキップ(妥当)」とした5エリア(npe/config/api/core/webapp)を含む残り項目を、3 Explore agent での現存確認を経て追加改善。項目レベル重複なし・ベースライン(2 failed/4861 passed)完全一致。

  • npe: _read_today_total に行解析ヘルパ _parse_ledger_cost 抽出(#11)
  • config: フォールバック project version をモジュール定数化(#9)
  • api: MAX_API_KEYS_PER_USER を env(NEXUS_MAX_API_KEYS_PER_USER)化(#12)
  • utils: cleaner の「Return None」誤コメント削除(#13)/test_strategy os.getcwd のOSErrorフォールバック(#18)/zip_output 除外dir定数化+output_dir存在保証(#19)
  • ui: ai_revision_tab のコードブロック除去を code_prompt_tab._strip_code_block で共通化(#19)
  • webapp: CORS origins を env(NEXUS_CORS_ORIGINS)化(#24)/paginate_query 戻り値型を具体化(#31)
  • services: self_healing session_id を env(NEXUS_SELF_HEALING_SESSION_ID)化(#15・format全面整形混入をreset→surgical再適用)
  • llm: BudgetManager/log_transaction にdocstring追加(#18)
  • core: NexusOSKernel.get_service 戻り値型 -> Any(注:NexusOSKernel は code_interpreter 不在で import 不可・死にコード候補)(#15)
  • analyzer: context_analyzer プレビュー読込 10000 → _PREVIEW_READ_BYTES 定数化(#19)
  • agents: council_cli.run_cli_menu にdocstring(#21・他項目は解消済み/誤検知/設計判断でスキップ)

[2026-07-30] - LLM stub応答の silent failure 解消(real無効時に明示的WARN)

Fixed

  • BaseLLM._stub_response(real呼出無効時・APIキー無し等)が黙ってダミー応答を返し「本物のLLMが動いたか」が実行時に判別不能だった問題を解消。stub応答時に WARN ログ(モデル名・原因候補含む)を出し、stub動作を即判別可能に
  • src/nexuscore/llm/providers/base.py: _stub_response に logger.warning 追加
  • tests/llm/test_stub_response_warn.py(新規3テスト): WARN 出力・レベル検証・fallback(今回対象外)の非変更を検証
  • ついでに: base.py の pre-existing な unused import(typing.Any)を削除(触ったファイルの lint クリーン化)
  • 検証: tests/llm 641 passed / 変更ファイル ruff+mypy 緑
  • 範囲: real無効時(_stub_response)のみ。real失敗時(_stub_fallback_response)は既存 log_error(ERROR)あり据え置き

[2026-07-30] - NEXUS_TASK_MODEL_* デッドキー是正(env でモデル振り分け切替可能に)

Added

  • NEXUS_TASK_MODEL_CODING/REVIEW/GENERAL の3 env キーをコード参照し、各カテゴリの primary モデルを env 1行書き換えで切替可能に(2026-07-23監査④デッドキー是正)。値は profile ID(glm_default/gemini_secondary/minimax_default 等)
  • src/nexuscore/llm/task_model_map.py: _TASK_CATEGORY(task→coding/review/general 分類・2026-07-23 3LLM集約構成に準拠)・_CATEGORY_ENV・_resolve_primary() を追加。build_task_model_map_dict() の primary を env で上書き。alias(testing 等)は target のカテゴリを継承
  • tests/llm/test_task_model_env_override.py(新規7テスト): env 上書き(CODING/REVIEW/GENERAL)・未設定時の既定維持・alias カテゴリ継承・未知値フォールバック・secondary/fallback 非上書きを検証

Changed

  • env 値が未知の profile ID(model name 形式や typo 等)の場合は 警告1回+既定フォールバック(移行安全性)。fail-fast でなく既存 .env の古い値(gpt-5 等)でもクラッシュせず稼働。警告は env キーごと1回に重複抑制(_WARNED_BAD_ENV)
  • 検証: tests/llm 638 passed / 変更ファイル ruff+mypy 緑 / 実 .env 環境で起動時ビルド確認(3カテゴリ各1回 warn・既定フォールバック・33エントリ build OK)

[2026-07-28] - MiniMaxモデル名表記の不統一是正(MiniMax-M3 PascalCase統一)

Fixed

  • MiniMaxモデル名の表記揺れ(minimax-m3小文字 / MiniMax-M3PascalCase)を MiniMax-M3 に統一。実API(.env の MINIMAX_MODEL=MiniMax-M3)と整合しない小文字表記が残存し、_call_minimax がenv未設定時に小文字を送ってAPIで弾かれるリスクがあった
  • src/nexuscore/llm/llm_profiles.py: minimax_default/minimax_analytical の model を minimax-m3→MiniMax-M3 に是正
  • src/nexuscore/utils/test_generator.py: _call_minimax のデフォルト(env未設定時フォールバック)を MiniMax-M2.7(旧モデル)→MiniMax-M3 に更新
  • tests/llm/test_llm_profiles_comprehensive.py・tests/utils/test_test_generator_comprehensive.py: 上記に追従。test_call_minimax_sends_correct_payload は MINIMAX_MODEL env を明示セットして .env 流入を防ぐ堅牢化(従来はenv未隔离でフルスイート時のみ1件FAIL)
  • 検証: LLM系 681 passed / フルスイート 4905 passed・0 failed(従来 4904 passed, 1 failed から失敗ゼロ化)

[2026-07-26] - 未完成エントリポイントの棚卸し(main_cli.py以外)

Removed

  • src/main_ui.py を削除 — 2025-01「4.5 UI統合」で unified_gradio_ui.py に統合された後の抜け殻。フォールバック先の app_ui.py/revision_loop.py/streamlit_migrated_tab.py/interactive_generator.py(src/gradio_app/・src/modules/ 配下)は db0424d8(no imports found確認済み・archive/ごと削除)で既に消滅済みで、参照先自体が存在しないため到達不能。現行の起動経路は unified_gradio_ui.py 直接起動(AGENTS.md/CLAUDE.md記載)で完全代替済み
  • src/dev_tools/test_manager.py を削除 — code_generator/diff_viewer/tester/whisper_handler をimportするが、これらのモジュールはリポジトリ全体のどこにも存在せず、import時点で確実に ImportError → sys.exit(1)。他のどこからも参照されておらず、稼働実績なし
  • tests/ui/test_main_ui.py・tests/ui/test_main_ui_unit.py を削除 — main_ui.py 専用のカバレッジ稼ぎ用テスト(tkinterベースの存在しない関数をhasattrチェックするのみ・実体テストなし)。対象モジュール削除に伴い道連れ削除
  • 経緯: app.py:73(nexus CLI)の戻り値契約ズレバグ修正(2026-07-21・PR #106)を機に、「他のエントリポイントにも同種バグが眠っている可能性」を全経路棚卸し。nexus CLIの他コマンド・unified_gradio_ui.py(Dynamic Runタブ含む)・bootstrap_apikey.pyは契約ズレなしと確認、上記2ファイルのみ「デッド経路」として検出
  • 詳細: 01_DECISIONS/NexusCore/2026-07-26_未完成エントリポイントの棚卸し.md(※記録予定)

[2026-07-26] - CoderAgent説明文出力の根源改善(案X′・コードブロック必須化)

Changed

  • CoderAgent 説明文出力の根源改善(前回 2026-07-23 fail-safe化 の上流・問題③decision 案C実装):
    • ①implement_code プロンプトに「python 〜 マークダウンコードブロックで囲んで出力せよ」を明示(LLM側防波堤)
    • ②_extract_code_from_response: コードブロック未検出時の「レスポンス全文フォールバック」(説明文をコード扱いする経路)を廃止 → 空文字返却に変更
    • ③_validate_code: 冒頭に空ガード if not code.strip(): return False, "empty code" を追加(ast.parse("") が成功する仕様の穴対策・_validate_code 層=言語非依存に配置しSRP適合)。結果: コードブロック無し→空→AST不合格→RETRY継続でLLMに囲み直しを促し、説明文がコードとして紛れ込む経路を根源から排除
  • 設計経緯: sentaku L3弁証論(Gemini+MiniMax)で案X′(空+空AST不合格化)を採用。Z(空=AST合格のまま)はRETRYが死ぬ・Y(例外)は想定内失敗への例外濫用、をそれぞれ却下
  • TDD: RED 6件FAIL確認 → GREEN → 既存10テスト(コードブロック無しモック)を新仕様のコードブロック形式に更新 → agents 982 / core 908 全グリーン
  • 詳細: 01_DECISIONS/NexusCore/2026-07-26_CoderAgent説明文根源改善-案X′コードブロック必須化.md(※記録予定)

[2026-07-25] - 学習レイヤー実API検証スクリプト追加・python-patch導入

Added

  • scripts/verify_learning_e2e_real.py 新設(Stage3学習レイヤー実API E2E検証・Mock版単体テストの実LLM版・postmortem/knowledge_curatorのみ実LLM化・knowledge_baseはMock化でDB非汚染・5回実行で学習ルート完全マッピング)
  • python-patch(patch-1.16) を .venv に導入(KnowledgeCuratorAgent のサンドボックスパッチ適用に必要・requirements.txt/requirements.lock.txt 反映は別途)

Changed


[2026-07-24] - _INDEX案C再構成(SSOT体系化 P3-C Phase1)

Changed


[2026-07-22] - NexusCore実API動作確認(GLM主軸・ローカル設定調整)

Changed

  • 実API動作用のLLM設定調整(ローカル .env のみ・非commit): NexusCore CLIの実API呼出が全てstub-fallbackに落ちていた真因を3点で解消。①LLM SDK(openai/anthropic/google-generativeai/zhipuai)をvenvへ導入(requirements.txt最小→lock未適用が原因)②FORCE_CHEAP_FOR_TASKS+CHEAP_LLM_MODEL=glm:glm-5.1 で主要タスクをGLM寄せ(OpenAI429/Gemini無効モデル名404を回避)③NEXUS_DEFAULT_MAX_OUT_TOKENS/NEXUS_LLM_MAX_OUTPUT_TOKENS を1024→16384(glm-5.1推論モデルが推論だけで1024を使い切り出力0になる設計不整合)。結果: GLM(glm-5.1)実APIで要件→計画→実装パイプライン完走・フィボナチ関数3ファイル生成成功。詳細: 01_DECISIONS/NexusCore/2026-07-22_NexusCore実API動作確認-3壁解消.md

[Unreleased]

Added

  • Stage 3 学習レイヤー実配線(src/nexuscore/core/phase_runner_mixin.py): ①テスト失敗枯渇時に postmortem_agent.analyze_failure_and_suggest_fkb_entry() → knowledge_curator_agent.validate_fkb_suggestion() を実行し、サンドボックスで実際にテストが通ることを検証できた解のみ中央FKB(database.knowledge_base.add_knowledge())へ永続化(汚染防止・spec §5)。分析結果は検証の成敗に関わらず context.postmortem_report へ格納し、実装済みだが未発火だった _maybe_run_constitutional_review() を初めて起動 ②guardian APPROVE後に policy_agent.audit() の結果を allow_commit として guardian_agent.review_and_commit() に接続し、ポリシー違反時はコミットをブロック ③debugger⇔中央FKBの接続(_find_solution_from_kb)は既存実装のみで成立することを回帰テストで担保。spec: docs/superpowers/specs/2026-07-17-twelve-agent-pipeline-design.md §5。詳細: 01_DECISIONS/NexusCore/2026-07-21_Stage3学習レイヤー実装.md
  • コード生成系 Agent の層1(AST構文検査)共通ユーティリティ src/nexuscore/utils/syntax_validator.py 新設(validate_python_syntax(code) -> tuple[bool,str]・phase_runner が使用・CoderAgent は6d3fセッション完了後に移行)
  • 自己修復デバッグループの履歴 OrchestratorContext.debug_history・早期脱出閾値 AST_FAIL_LIMIT=2(env: NEXUS_AST_FAIL_LIMIT)・_clean_pytest_cache(CI flaky 回避)・_format_debug_history(NEEDS_HUMAN_REVIEW 時の人間可読要約)を追加

Fixed

  • DebuggerAgent 経由の LLM説明文による実装ファイル破損を根本防止(src/nexuscore/core/phase_runner_mixin.py::run_testing_phase デバッグループ)。A検証(dynamic完走・2026-07-24)で、DebuggerAgent が生成した fixed_code を適用前検査なしで書き込み→pytest失敗でも復元せず次ループ→破損ファイル(primes.py等)が残り悪化ループになる問題を解消。①層1 AST構文検査で説明文を適用前に弾く②層3 pytest実行検証で意味の正しさを担保③try-finally で例外時も含めループ脱出後に original_source へ復元(破損残存防止・悪化ループ根絶)④AST NG 連続 AST_FAIL_LIMIT 回で早期脱出(LLMが説明文しか返さない故障検知)⑤各試行を debug_history に記録し NEEDS_HUMAN_REVIEW 時に review_report へ添付。ユーザー指摘「AST検査は第一防線・根本対策でない」に対応(実行検証で意味の正しさを担保)。spec: docs/superpowers/specs/2026-07-24-nexuscore-debugger-patch破損根本防止-design.md・2巡 multi-llm-review(Gemini+MiniMax)経由。テスト8ケース追加(破損防止/早期脱出/連続判定/空fixed_code/例外安全/最終ロールバック/履歴蓄積)

Fixed

  • src/nexuscore/cli/app.py:73 — nexus run コマンドが orchestrator.run_full_project() の戻り値に .get("status") を呼んでいたが、同メソッドは OrchestratorContext | None(dataclass、.get() 無し)を返すため、成功時・停止時いずれも AttributeError で必ず落ちていた(nexus は pyproject.toml:9 [project.scripts] で公開される現役エントリポイント。CLIテスト未整備で露見せず)。result is None→interrupted、それ以外→completed (N phases)(phase_log 由来)に導出するよう修正。回帰防止に tests/cli/test_app.py へ context 返却/None 返却の2ケースを TDD で追加(監査「複数の未完成エントリポイント同居」パターンの一例)
  • CI修復: NexusCore CI/CD ワークフロー赤の3問題を解消。①test matrix から Python 3.9 除外(semgrep==1.166.0 / pip-audit==2.10.1 / bandit>=1.9.0 が Python 3.10+ 必須のため。3.9が落ちるとmatrix全体がキャンセル連鎖で全バージョン赤になる構造的問題でもあった)②Bandit スキャンが src/sandbox_logs/(72ファイルの修復ログ・AST parse失敗する自然言語テキストを.py拡張で持つ)を除外するよう pyproject.toml [tool.bandit].exclude_dirs 追加 — Check for critical vulnerabilities ステップは -lll (High only) でB104 Mediumは元から通過するため、High:0で緑化 ③actions/upload-artifact@v3 → @v4(2箇所・v3はGitHubで削除済・Node20 deprecated警告解消)④Codecov 連携ステップ削除(CODECOV_TOKEN 未設定で fail_ci_if_error: true のため赤確実。CI緑化優先・後日Codecov.io登録&token設定で再有効化)⑤pytest を -n auto --dist=loadfile から直列実行に変更(5000件規模でグローバル状態リーク由来のフレーク確認。直列化でフレーク消失を確認。CI時間は+5-10分)⑥test_generator 周辺の3テスト(フルテスト時のみフレークする test_test_generator_creates_runnable_pytest_file / test_init_without_genai_library_falls_back_to_stub / test_generate_unit_tests_uses_default_config)に @pytest.mark.xfail 付与。test_generator 機能改善時に解消予定(別Issue)⑦ci.yml の bandit コマンドに --exclude src/sandbox_logs/ を明示(4箇所・pyproject.toml の exclude_dirs はCIで読まれず sandbox_logs がスキャンされていた問題を解消)⑧requirements-dev.txt に pytest-timeout 追加(pytest.ini の --timeout=120 がCI環境で unrecognized arguments エラーになる問題を解消)⑨ci.yml の display用 bandit -r src/ -ll に || true 追加(実コードのLow+ severity偽陽性でexit 1になりCI赤になる設計ミスを解消。厳密判定は Check for critical vulnerabilities ステップが -lll で担当)⑩ci.yml matrix を ["3.12"] のみに(pyproject.toml requires-python >=3.12 と整合・datetime.UTC(3.11+)のコア10箇所使用のため3.10以前は不可)⑪Bandit Medium+ 5件の実体解消(セキュリティレビュー指摘対応・|| true 後退を撤廃): B104/B608 は archive/ 配下(非現用)→ bandit --exclude に archive 2ディレクトリ追加で自然消滅・残る B108(/tmp偽陽性3件: run_lock/sandbox_config/dynamic_run_tab placeholder)は実コードに # nosec B108 明示・critical check を -lll(High only)→-ll(Medium+)に厳密化(ローカル実走で Medium:0 High:0 exit:0 確認)
  • v3レビュー P0「api/dependencies/orchestrator.py:62-63 空文字列認証フォールバック」— doubt-driven で検証した結果、api_key は GuardianAgent 内で使用されないデッド変数(実際のLLM認証は LLMRouter が env 経由で担う)と判明。真の論点は「3経路の cred 出所バラバリ + デッドコード」であり、cred 出所を GuardianAgent.__init__ 内 env 読込の1箇所に集約して解消(A’案)。placeholder 廃止・重複排除も達成
  • CI修復続き(Run Tests 3.12 gradio不整合解消)⑫: requirements.txt の gradio>=4.16.0,<5.0.0 → gradio>=4.16.0,<7.0.0 に制約緩和。gradio 4.x は古い huggingface_hub API(HfFolder)に依存し、CI が最新 huggingface_hub(1.x・HfFolder削除)を入れて ImportError になる問題を解消。gradio 6.x(HfFolder不使用)でローカル.venv実証済み。NexusCore は gradio を import gradio as gr の標準使用のみ(4.x固有APIなし)のため6.x互換
  • CI修復続き(Run Tests 3.12 TemplateNotFound解消)⑬: .gitignore の「# エージェント残骸 webapp/」が src/nexuscore/webapp/templates/ 配下のHTML10個(base.html/components×2/dashboard×2/logs×2/projects×3)を巻き込み除外していた。CI の git clone に含まれず jinja2.exceptions.TemplateNotFound: logs/project_logs.html で ci.yml 3連赤(gradio解消⑫で40%まで進むよう初めて顕在化した「過去緑CI履歴ゼロ」の真因)。「エージェント残骸 webapp」は現在実在しない(src=ソース必須/tests=テスト必須/mutants=別管理のみ)のため webapp/ ignore 行を削除し、テンプレート10個を git add。ローカル.venv は元々ファイルがあるので通過(tests/webapp/ 39 passed)・CI固有問題。ci.yml 両job(Run Tests 3.12 in 4m52s / Security Vulnerability Scan)緑化確認(run 29017144120)
  • CI修復続き(Release Drafter workflow削除)⑭: .github/workflows/release-drafter.yml を削除。Release Drafter は「マージされたPR」ベースでリリースノート生成するが、NexusCore は main 直push 運用(PR経由なし)のため変更一覧が空になり機能しない(doubt-drivenで気づき・A案設定追加からB案削除に訂正)。設定ファイル欠落で3s失敗し続けていた赤を解消。今後PR運用(チーム/OSS化)に変える場合は再導入可
  • CI修復続き(STIT approval-notification 構文解消・CI完全緑化)⑮: push毎0s赤の真因を actionlint 導入で特定→if:式のメソッド構文 github.event.issue.title.startsWith('...')(GitHub Actions式に非存在)を関数構文 startsWith(A,B) に修正(L23/L137)。job レベル schedule 削除(bbeb1c73)は副次・真因はif式(c550008f)。構文解消で on: トリガー通りに動き(push トリガー無し→pushで走らない→赤停止)。2LLMレビュー(Gemini B案/MiniMax E案)は「NexusCore開発停止中」文脈でD案(残す+赤だけ消す)に転換。STIT運用は保留・branch-validation/test-pipelineはpull_requestのみ(将来再開時修正点: codecov v3→v5・github.head_ref env経由)。これで ci.yml緑化+Release Drafter削除+STIT赤停止=CI完全緑化
  • CI修復続き(STIT PR ワークフロー Python 3.11→3.12 統一)⑯: stit-branch-validation.yml / stit-test-pipeline.yml が actions/setup-python で Python 3.11 をセットアップ後に pip install -e . していたが、pyproject.toml は requires-python >=3.12 のため ERROR: Package 'nexuscore' requires a different Python: 3.11.x not in '>=3.12' で必ずインストール失敗し、全PRで Validate branch name / STIT Process Validation が9s赤(ブランチ名・STIT本体の検証に到達すらしていなかった)。両ワークフローの python-version: "3.11" を "3.12" に統一(ci.yml⑩と同判断)し、stit-test-pipeline.yml の run-tests matrix ["3.9", "3.10", "3.11", "3.12"] を ["3.12"](coverage include も 3.12)に集約(3.12未満は nexuscore を入れられない)。stit-approval-notification.yml(PR では python セットアップ不要のジョブのみ起動・pip install -e . なし)と nexuscore-safe-tests.yml(3.11のまま緑・pip install -e . なし)は赤に無関与のため非変更。併せて、Python 3.12 化で stit-test-pipeline.yml の run-tests が初めて完走するようになった結果、最終 Upload coverage ステップ(codecov/codecov-action@v3 + fail_ci_if_error: true)が coverage.xml 不在(run-tests は --cov-report=xml を付与しないため生成されない)で exit 255 → 赤になる潜在不具合が顕在化したため、当該ステップを削除(ci.yml④ と同処置・テスト本体は pass)。

  • src/nexuscore/core/goal_spec.py:107 — has_implementation criterion のキー不整合修正(2026-07-23 問題②・dynamic完了判定ループの真因)。criterion が ctx.implementation.get("code") のみ見ていたが、通常パイプライン(phase_runner_mixin.py:350)は {"files": generated} を設定するため .get("code")=None→永遠 unsatisfied→max_actions 枯渇(fast_lane({“code”:…})だけ動いて見えた)。criterion を _non_empty(get("code")) or _non_empty(get("files")) に修正(両経路対応・空 dict は _non_empty=bool で False=未達維持)。2LLMレビュー(Gemini+MiniMax)で真因肯定・MiniMax の空dict懸念は _non_empty=bool で解消・回帰テストで保険。TDD: RED(files形式で未達)→GREEN→空dict未達テスト追加。goal_spec/dynamic系 60件 全通過
  • src/nexuscore/agents/coder_agent.py:73 — implement_code の RETRY枯渇時挙動を fail-open → fail-safe に修正(2026-07-23 Smoke Test 破損事故の真因)。AST検査が RETRY_LIMIT(2回) 連続失敗した場合、従来は最後のAST不正コードをそのまま返していた(fail-open)。LLM(GLM)がコードでなく説明文を返した場合、それが説明文のまま _generate_one_file の空チェック(if not code)を潜り抜け、__init__.py に日本語説明文が保存されて破損(SyntaxError: invalid character '、')。RETRY枯渇時は空文字を返すようにし、phase_runner_mixin.py:383 の空チェックが保存を弾く構造に。バックログ旧案「python-patch導入」は systematic-debugging で無関係と確定(python-patch/patch_applier/self_healing はPR系修復の別系統・Phase4生成パイプラインと無関係・decision の因果誤認)。副修正(phase_runner保存前AST検査)は主修正+既存空チェックで不要と判断。TDD: RED(説明文返却で失敗確認)→GREEN(73行修正)→旧仕様固定テスト test_implement_code_max_retries_exceeded を新仕様化 + 新規 test_implement_code_returns_empty_when_all_retries_fail 追加。coder_agent系 39件 + phase_runner/orchestrator系 75件 全通過

Changed

  • tools/brownfield_orchestrator.py — God file 分割(v3レビュー P1): 485行単一ファイル → tools/brownfield/ パッケージ5モジュール(utils/core/ui/__main__/__init__)+ 18行 thin shim(後方互換)。python tools/brownfield_orchestrator.py --ui は変更なしで動作。baseline 前後比較テスト(normalize() でタイムスタンプ/tmp_path 正規化)で振る舞い保存を証明。依存方向 utils ← core ← ui ← __main__(循環なし)・__init__.py は lazy __getattr__(gradio 遅延読込)。セキュリティ指摘(B602 subprocess shell / B104 0.0.0.0 bind / path traversal 5件)は旧コード由来のため別Issue化(C案 scope-out)。詳細: docs/superpowers/specs/2026-07-01-brownfield-orchestrator-split-design.md・実装計画: docs/superpowers/plans/2026-07-01-brownfield-orchestrator-split.md
  • src/nexuscore/agents/guardian_agent.py — GuardianAgent.__init__ の model を GUARDIAN_MODEL 環境変数参照に変更(cred 出所の集約)。api_key 引数は後方互換のため残置。v3レビュー P0 対応
  • src/nexuscore/api/dependencies/orchestrator.py — get_orchestrator() を assemble_agent_team() ベースに統合(API 経路が最後の孤島)。_load_guardian_credentials() 廃止・3経路(CLI/webapp/UI)と同一パスに統一
  • src/nexuscore/core/agent_factory.py — assemble_agent_team() に language / knowledge_base_path 引数追加(既存呼出は default で非影響)
  • main_cli.py — _load_guardian_credentials()(placeholder 含む)廃止。GuardianAgent() 引数なしで cred を GuardianAgent 内 env 読込に統一
  • src/nexuscore/analyzer/context_analyzer.py — ハードコードフォールバック5箇所(requirements 解析/依存関係/標準ライブラリ/Pythonバージョン)を環境変数 NEXUSCORE_CONTEXT_FALLBACK_* で上書き可能に設定化。未設定時は従来のデフォルト値を維持(後方互換)。v3レビュー P1 対応
  • src/nexuscore/utils/cleaner.py — モジュールdocstring・各関数の型ヒント(get_error_header(traceback_str: str) -> str / clean_error_msg(error_str: str = "") -> str)・docstring追加。振る舞い変更なし(67テスト全PASSで回帰確認)

Security (Phase 2 脆弱性監査 — api/ 深掘り)

  • src/nexuscore/api/routes/execute.py:191-198 — /execute で payload.project_path を認証済みなら誰でも渡せて、Orchestrator が任意パスを操作可能 (H-1 HIGH)
  • src/nexuscore/api/routes/execute.py:191 — payload.requirement にサイズ制限なし → 巨大なプロンプトで Token DoS (OWASP LLM04)、コンテンツ検証なしで プロンプトインジェクション → PolicyAgent バイパスの可能性 (H-2 HIGH)
  • 副次: /run-records ページネーションなし (MEDIUM)、SessionMiddleware default secret_key (LOW、fastapi_app.py:124)
  • 修正方針: C 案 (project_id 化) + requirement: Field(..., max_length=2000)、ユーザー合意待ち
  • 詳細: 01_DECISIONS/nexuscore/2026-06-17_Phase2-api-任意コード実行とプロンプトインジェクション.md

Added (Security audit Phase 0 — ベースライン取得・計画策定)

  • セキュリティ監査ツール4種を requirements-dev.txt に pin: bandit==1.9.4 / semgrep==1.166.0 / pip-audit==2.10.1 / detect-secrets==1.5.0
  • ベースライン検出サマリ: bandit 10526件 (HIGH 8 / MEDIUM 150 / LOW 10368)、semgrep 12 WARNING、pip-audit 53件 (17 pkg、52 HAS_FIX / 1 NO_FIX=gradio)、detect-secrets 6件 (全件 .claude/settings.local.json 由来、gitignore 対象)
  • 脆弱性発見計画 v0.1 を docs/security/vulnerability_discovery_plan.md に追加 — Phase 1 でフィルタ最適化→真陽性抽出→修正のロードマップを明文化
  • ベースライン JSON 出力: docs/security/baseline/*.json および docs/security/baseline/phase0_baseline_report.md
  • High 候補 6件 (Phase 1 で均等に精査予定): tools/brownfield_orchestrator.py:111 shell=True (B602) / council_webui.py:124 SSTI 疑い / server.py:290 0.0.0.0 バインド (B104) / auth.py:47 Host ヘッダ依存 / archive/views_api_test.py:65 B608 f-string SQL / tools/ 配下 7箇所 SHA1 (B324)
  • 偽陽性として除外予定: bandit B101 assert × 9986 (テストでは許容)、B404/B603 subprocess × 90 (CLI ツールで必須、検証済なら安全)、semgrep python-logger-credential-disclosure (誤検知: ログは set/unset のみ)

Added (CR-NEXUS-054 Phase C — CLI/UI統合・完結)

  • main_cli.py: --dynamic / --dynamic-llm-routing / --max-actions / --skip-actions フラグ追加。run_dynamic_mode() でDecision Traceをログ出力、ゴール未達はexit code 1
  • ui/dynamic_run_tab.py: 統合UIに「Dynamic Run」タブ追加 — 要件・パス・予算・スキップ/LLMルーティング指定で動的実行し、結果とトレースを表示
  • テスト6件追加(GLM生成→Fable検証)。CR-NEXUS-054 全フェーズ完了(Spec → Completed)

Fixed

  • core/orchestrator.py: context_agent フィールド欠落を修正 — main_cli.py と agent_factory.assemble_agent_team() が渡す context_agent 引数をOrchestratorが受け取れずTypeErrorでCLIフルパイプラインが起動不能だった既存バグ

Added (CR-NEXUS-054 Phase B — LLM支援ルーティング・計測クライテリア)

  • core/llm_assisted_router.py: LLMAssistedRouter — 軽量ティアLLMが次アクションを提案、無効提案・LLM障害・予算超過は必ずRuleBasedRouterにフォールバック。リトライ判断は決定的ルールのまま。from_llm_router() で既存LLMRouterと統合可能
  • core/measured_criteria.py: coverage_criterion / lint_clean_criterion — カバレッジ%・lint警告の実測ベース成功条件。PhaseCachedCheckでphase_log変化時のみ再計測(pytest多重実行防止)
  • テスト18件追加(MiniMax生成→Fable検証。GLMタイムアウトのためフォールバック)

Added (CR-NEXUS-054 Phase A — ゴール駆動・動的オーケストレーション)

  • core/goal_spec.py: GoalSpec / SuccessCriterion / GoalEvaluator / standard_criteria — ゴール(達成条件・予算・スキップ)を宣言的に定義し決定的に採点
  • core/dynamic_router.py: ActionRegistry(既存 run_*_phase を自動登録)+ RuleBasedRouter(未達条件→次アクションをLLMコストゼロで選択)
  • core/dynamic_orchestrator.py: DynamicRunLoop — 既存Orchestrator無改変のコンポジションでゴール達成まで動的実行。失敗は全停止せずアクション単位リトライ、全判断をDecisionTraceに理由付き記録
  • テスト48件追加(test_goal_spec.py / test_dynamic_router.py / test_dynamic_orchestrator.py、MiniMax生成→Fable検証)
  • 仕様書: docs/spec/CR-NEXUS-054_Dynamic_Goal_Driven_Orchestration.md

Changed (UI分離完了 — Phase 1完遂)

  • config/policy_interface.py → ui/policy_interface.py に移設(Gradio UIコードをui/層へ集約、参照8ファイル更新)
  • docs/overview/03_Development_Roadmap.md v1.3: 実態に合わせて更新(カバレッジ81%・8プロバイダー・Phase 1のUI分離/DebuggerAgent自動PRを完了マーク)

Removed

  • utils/app.py を archive/legacy_flask_gradio_app.py へ移動(存在しない routes_ai_repair/gradio_ui をimportする死んだレガシーコード)、関連テスト3本削除
  • これにより ui/層外のGradio依存ゼロ を達成

Added

  • 退避ブランチからカバレッジテスト7ファイル・約200テストを回収(archive/* タグ監査の成果)
    • tests/agents/test_base_agent_fallback_paths.py(issue-86)
    • tests/api/test_api_keys_coverage.py(issue-90)
    • tests/api/test_fastapi_app_coverage.py(issue-92)
    • tests/api/test_auth_dependency.py(issue-96、モック記述ミス1件修正)
    • tests/agents/test_policy_interface_coverage_boost.py(import先を config.policy_interface に修正、print検証→loggerモック検証に更新)
    • tests/core/test_retry_policy.py / test_errors.py(feature/fail のミューテーションキルテスト、32→52テスト)
  • 回収見送り: test_api_auth.py(対象の api/auth.py はPhase 5で統合済み)、test_requirement_agent_fallback.py(対象のTextLocalizationは8.2.1で削除済み)

Fixed

  • api/routes/github_webhook.py: PRコメント投稿・Slack通知を asyncio.to_thread でバックグラウンド実行化(Webhookレスポンスのイベントループブロック解消)

Changed

  • .gitignore: デモGIF生成の中間ファイル(docs/demo/frames/, docs/demo/svgs/)を追跡対象外に
  • ローカルブランチ掃除: マージ済み9本を削除、未マージ13本は archive/* タグに退避して削除(Issue #50自動PR・Issue #75 CI並列化はmain取込済みを確認)

Added

  • ArchitectAgent.design_architecture(specs, plan) 新設。coderへの設計方針(design_directive)注入用(Stage 2・spec §4-1)
  • Phase 5(testing)を全面書き換え: テストファイルをplanのtarget_files(role=test)へ書き出し、run_in_sandboxでpytest実行、失敗時はDebuggerAgent.debug_and_patchで最大3回(NEXUS_DEBUG_MAX_RETRIES)まで自動修正ループ(Stage 2・spec §4-2)
  • Phase 6(review)を全面書き換え: GuardianAgent.reviewでコードレビュー、REJECT時はフィードバックを添えて最大2回(NEXUS_REVIEW_MAX_RETRIES)まで再実装→再テストのループ、終端は3値(APPROVED/NEEDS_HUMAN_REVIEW/ERROR)のfail-closed設計。NEEDS_HUMAN_REVIEW時はreview_report.mdを生成(Stage 2・spec §4-3/4-4)
  • OrchestratorContextにdebug_retries/review_retries/terminal_state/review_reportフィールド追加(ループ状態の明示管理・spec §6-2)

Changed

  • main_cli.py: terminal_stateがNEEDS_HUMAN_REVIEWの場合、終了コードを2にマッピング(Stage 2・spec §4-4)

2026-07-18

Added

  • core/plan_contract.py: plan JSON の target_files 契約(検証・劣化モードフォールバック・パストラバーサル防止)
  • planner プロンプトに target_files 生成指示(path/role 契約)
  • main_cli.run_smoke_gate: 成果物の実在+py_compile 構文検査

Changed

  • 実装フェーズ: hello.py 固定書き込みを廃止し、target_files に基づく複数ファイル生成に変更(生成済みファイルを existing_code で伝搬・空出力は RuntimeError)
  • Smoke Test: hello.py 存在+”Hello”出力 → target_files 全実在+py_compile 構文チェックに再定義
  • run_full_project が OrchestratorContext を返すように変更(既存呼び出しは非破壊)
  • README 自動生成: 固定文言を廃止し実際の生成ファイル一覧から組み立て
  • plan パース堅牢化: dict / JSON文字列 / fence付き / 非JSON / None / 空文字 の各形態に対応(_coerce_plan)

Fixed

  • CLAUDE.md のエージェント数 14→12(監査 C-1 関連のドキュメント整合)
  • test_plan_contract の caplog 分離問題(フルスイート実行時の取りこぼし)

[8.2.5] - 2026-05-27

Changed

  • 100行超関数の分割リファクタリング(36件→8件、78%削減)
    • Phase 1: test_generator_prompt.py, _builder.py, pr_comments.py, run_report_generator.py, code_prompt_tab.py
    • Phase 2: fastapi_app.py, auth.py, github_self_healing_webhook.py, celery_app.py, views_logs.py
    • Phase 3: github_pr_summary.py, notifier.py, views_projects.py, self_healing_service.py, orchestrator.py, semantic_diff.py, retry_utils.py, postmortem_agent.py, knowledge_curator_agent.py, unified_analyzer.py
  • 各関数からヘルパー関数・定数を抽出し、メイン関数をオーケストレーター化

[8.2.4] - 2026-05-26

Fixed

  • fastapi_app.py: 本番環境でSESSION_SECRET未設定時にRuntimeErrorで起動拒否
  • auth.py: OAuth例外時のエラー詳細をレスポンスに露出しないよう修正 + ロギング追加
  • github_webhook_handler.py: repo_full_name の形式検証追加(SSRF防止)
  • fastapi_app.py: 汎用例外ハンドラにロギング追加
  • graph_builder.py: リストアクセス時の境界チェック追加
  • whisper_handler.py: 本番でエラー詳細を返さないよう修正(空文字列を返す)
  • errors.py: classify_error() をテーブル駆動にリファクタリング(125行→55行)

Changed

  • errors.py: convert_http_error_to_nexus_error() を辞書マップ化(if-elifチェーン排除)
  • 211件の # noqa: BLE001 を精査 — 全て正当な広範キャッチと確認

Removed

  • sandbox_executor.py: 未使用import 3件削除(_CPU_TIME_LIMIT_SEC, _MEMORY_LIMIT_MB, _check_forbidden_modules)
  • _checkers.py: 未使用import ProjectType 削除

[8.2.3] - 2026-05-26

Fixed

  • file_utils.py: "\\n" → "\n" バグ修正(エスケープ済み改行の二重エスケープ)
  • unified_gradio_ui.py: run_test_handler 重複定義削除
  • context_analyzer.py: パストラバーサルガード追加(rel_path.startswith("..") チェック)
  • _engine.py: .decode("utf8") → .decode("utf8", errors="replace")(デコードエラー保護)
  • test_runner.py: コマンドインジェクション修正(shell=True → shlex.split() + リスト形式)
  • council_webui.py: Flask secret_key未設定時にRuntimeErrorで起動拒否
  • unified_config.py: 本番secret_keyフォールバック無効化
  • github_webhook.py: 本番Webhook署名スキップ拒否

Changed

  • 125ファイルの bare except 全廃: except Exception: → 具体的例外型((json.JSONDecodeError, ValueError), (OSError, UnicodeDecodeError) 等)または # noqa: BLE001
  • webapp/db_helpers.py: N+1クエリ解消(DB集計クエリ化)
  • webapp/views_logs.py: メトリクス計算のインライン化
  • webapp/views_dashboard.py: LLM統計のクエリ最適化
  • 為替レート 150.0 → os.getenv("NEXUS_USD_JPY_RATE", "150.0")
  • Gradio URL → os.getenv("NEXUS_GRADIO_HOST", "http://localhost:7860")
  • HTTP timeout 10 → os.getenv("NEXUS_HTTP_TIMEOUT", "10")

Removed

  • views_dashboard.py: 未使用 import(PatchRecord, Project)
  • views_logs.py: 未使用 import(desc)
  • graph_builder.py: 未使用 import(sys)
  • planner_agent.py, debugger_agent.py, _cache.py: 未使用 import(logging)

[8.2.2] - 2026-05-12

Fixed

  • テストスイートハング修正: pytest.ini の addopts に -m "not integration" --timeout=120 を追加 — test_integration_llm.py(実際のLLM API呼び出し)をデフォルトで除外

Changed

  • P1-1: APIルートのHTTPException判定を isinstance(e, HTTPException) に統一、バックグラウンドタスクのエラー分類を追加(ValueError/ConnectionError/ImportError)
  • P1-2: authority_runner.py を3モジュールに分割(context.py, state.py, phase_logging.py)— 428→293行
  • P1-3: LLMリトライロジック共通化 — BaseLLM.execute_real_or_fallback() 抽出、3プロバイダーを _build_real_call() クロージャパターンに統一
  • P1-5: GuardianAgent を2モジュールに分割(commit_workflow.py, review_executor.py)— 388→317行

[8.2.1] - 2026-05-11

Added

  • P2-2: Settings UI Gradioタブ追加(ui/settings_tab.py) — LLM プロバイダー状態・プロファイル情報・タスクルーティングの読み取り専用ダッシュボード
  • P2-3: フェーズ実行に tqdm 進捗バーとタイミングログを追加(orchestrator/authority_runner.py)
  • P2-5: webapp/db_helpers.py 新規作成 — Webapp DBクエリ共通ヘルパー(13関数)
  • P2-1: subqueryload でN+1クエリ解消、DB count()クエリでPython集計排除

Changed

  • P2-6: 12ファイルの未使用import除去(28→12、残りは意図的re-export)
  • P2-4: 15ファイル160件の print()→logger 移行(残り37件は意図的)
  • P2-5: views_projects/dashboard/logs の重複クエリパターンを共通ヘルパー化

Removed

  • orchestrator_inline.py: 5行スタブファイル削除(orchestrator_helper.pyに直接インポート)
  • run_view.py deprecated_router: 非推奨3エンドポイント(93行)削除、canonical_routerのみ残存
  • requirement_agent.py: Gradio UI依存除去(TextLocalization / StateMachine / launch_gradio_ui / use_ui パラメータ)
  • phase_runner_mixin.py: use_ui 分岐(Gradio UI起動パス)削除
  • dependencies/orchestrator.py: use_ui=False パラメータ除去
  • fastapi_app.py: deprecated_router マウント除去

[8.2.0] - 2026-05-10

Added

  • P1-1: GitHub OAuth認証ルーター(api/routes/auth.py)をFastAPIで新規実装 — Starlette OAuthクライアント、SessionMiddleware対応

Changed

  • P0-1: _get_user_id_from_auth() のDRY解消 — 3ファイルの重複定義を dependencies/auth.py に統合
  • P0-1: sandbox_executor.py のハードコード値(メモリ/CPU制限)を環境変数化
  • P0-2: npe/budget.py, gemini_provider.py の broad except Exception: を具体的例外型に修正
  • P0-3: deps/orchestrator.py → dependencies/orchestrator.py に統合、deps/ ディレクトリ削除
  • P0-3(v2): self_healing_service.py(1,006行)を3モジュールに分割(git_operations, test_runner, patch_workflow)
  • P0-4: ProjectCreateRequest にパストラバーサル防止・URL検証のPydantic validator追加
  • P1-2: unified_gradio_ui.py(826行)を6モジュールに分割(_state, _llm_init, code_prompt_tab, ai_revision_tab, test_runner_tab, history_diff_tab)
  • P1-3: orchestrator_inline.py を orchestrator_helper.py に統合、inline.py は後方互換re-exportのみ
  • P2-1: orchestrator/explainability.py にモジュール・関数docstringを追加
  • P2-3: utils/clean_output.py にモジュール・関数docstringを追加
  • P2-4: api/utils/run_view.py → run_view_adapter.py にリネーム(役割明確化)

Removed

  • P0-2: api/server.py(非推奨Flask 303行)を archive/ に移動。execute.py の tasks 参照をローカル変数に変更
  • P2-2: utils/math_ops.py(add() のみ、未使用)および関連テストを削除
  • P1-1: views_api_test.py(シミュレーションのみ)を archive/ に移動

This site uses Just the Docs, a documentation theme for Jekyll.