Skip to content

スプリント lfactory3-6 - #2534

Merged
takemi-ohama merged 10 commits into
developfrom
sprint/lfactory3-6
Nov 5, 2026
Merged

takemi-ohama merged 10 commits into
developfrom
sprint/lfactory3-6

Conversation

@takemi-ohama

Copy link
Copy Markdown
Contributor

スプリント lfactory3-6 の課題を develop へ取り込む。

利用者向けの変化

  • 無し

移行の手順

  • 無し

課題と設計

コミット

変更の統計

 factory/web/src/pages/BacklogPage.tsx         |   8 +-
 factory/web/src/pages/DelegationsPage.tsx     |  40 ++--
 factory/web/src/pages/LoopDetailPage.tsx      |  32 ++--
 factory/web/src/pages/LoopsPage.tsx           |  22 +--
 factory/web/src/pages/ModelCredentialPage.tsx |  37 ++--
 factory/web/src/pages/NewSprintPage.tsx       |  16 +-
 factory/web/src/pages/NewTeamPage.tsx         |  23 +--
 factory/web/src/pages/RepositoriesPage.tsx    |  43 ++---
 factory/web/src/pages/SprintDetailPage.tsx    |   8 +-
 factory/web/src/pages/SprintsPage.tsx         |   8 +-
 factory/web/src/pages/TeamPage.tsx            |  36 ++--
 factory/web/src/pages/parts.tsx               |  23 ++-
 factory/web/src/poll.ts                       |   7 +-
 scripts/tests/test_check_markdown_links.py    | 141 +++++---------
 41 files changed, 654 insertions(+), 702 deletions(-)

テスト(supervise.py の run のステップ)

ステップ exit 最後の行
collect 0

集めた実装の PR

閉じる課題

Closes #2199

モード: standard / 通した工程: 実装 → Pull Request

🤖 Generated with Claude Code

takemi-ohama and others added 9 commits November 5, 2026 02:06
…er の配線だけにする(#2199 の R20・R02)

- requireEnv の 5 つの写しを src/env.ts へ寄せる
- createApiApp・jsonLogger・webOriginFromEnv を app.ts、depsFromEnv を auth/deps.ts、
  progressStoreFromEnv を progress/deps.ts へ移し、index.ts・runs/deps.ts・handlers/ どうしが
  handlers/ を読まない形にする
- テストは createApiApp の import 元だけを替える(期待値は変えない)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…9・R10・R11・R17・R18・R19)

- AccountStore・AccountPatch・ConditionFailedError と新しい AccountUpdate を accounts/port.ts へ移す
- updateAccount の 5 つの位置引数を AccountUpdate 1 つにする
- DynamoAccountStore.transact が履歴を受け取り、items → 履歴 → after の順に並べる
- AccountPatch の列を PATCH_COLUMNS の表で回す(プレースホルダは :plan・:mode のまま)
- 鍵の頭を USER_PREFIX・ACCOUNT_PREFIX と userPk・accountPk にまとめる
- AccountService の 4 つの再試行を retryOnConflict、3 つの条件の失敗の読み替えを writeOr にし、hist を消す
- store.test.ts は import 元と updateAccount の呼び出しの形だけを替える(期待値は変えない)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…13・R03・R12)

- validateSeatType を accounts/service.ts に置き、teams.ts と accounts.ts の 3 つの経路が使う(文言は同じ)
- 「チームなら席を読んで詳細の本文を作る」を views.ts の accountDetailBody にし、3 つの経路が使う
- github-oidc/app.ts の /token と /userinfo が githubUser を使う(判定の条件は同じ)
- auth/verify.ts の IdP の判定を idpFromUsername に出す(判定の順序は同じ)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- RequireLogin(context.tsx)で App.tsx のログインの後の枠を包み、12 画面の hasToken と /login への転送を消す
- usePolled の enabled の引数を消す(呼ぶ画面はすべて token の有無を渡していただけ)
- 「呼んで、失敗なら画面の文を出す」を useAttempt(context.tsx)にし、判定表の対象の try/catch を置き換える
- 席の種類の <option> を SeatTypeOptions(parts.tsx)にし、TeamPage と NewTeamPage が使う

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…の R16)

11 のテストに写っていた読み込みの 4 行を関数スコープの fixture check_module にする。
テストの関数の数と、確かめる入力・期待値の組は変えない(46 passed のまま)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2199 を実装する(スプリント lfactory3-6)
…positoryNames

どこからも呼ばれていない repositoryNames と、それだけが使っていた Repository の
型の読み込みを消す。一覧は SprintRunRow.repo を表示しており振る舞いは変わらない。

Item-Id: I-002
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tService.seatHistory

createTeam・addSeat・changeSeat・removeSeat で手で組んでいた席の履歴の行を
seatHistory に寄せる。null の側は before / after を null にし、行の中身は変わらない。

Item-Id: I-003
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Service

席の操作(requireTeamOwner・addSeat・changeSeat・removeSeat)を SeatService
(accounts/seat-service.ts)へ切り出し、AccountService は委譲だけにした。
席の履歴の行を作る seatHistory は createTeam と共有するため同じファイルの関数にし、
retryOnConflict・writeOr は両方が使うため accounts/conflict.ts へ移した。
AccountService の公開メソッドは変えていないので、呼び出し元は書き換えていない。

Item-Id: I-004
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

改修計画 — devbasex/ai-plugins #2534

/ndf:cross-refactoring が提案し、改修計画し、適用した改善項目の記録である。
理由と手順は提案の時点でしか残らないため、公開の直前に書き出している。

  • 件数: 採用 3・未確認 0・取り消し 1・見送り 8(うち時間 8)(最終ゲート: passed)
  • 公開: 3b36afb を push した
  • 書き直した時刻: 2026-11-05T03:07:30
  • 対象範囲: factory/api/src/accounts/memory-store.ts, factory/api/src/accounts/port.ts, factory/api/src/accounts/service.ts, factory/api/src/accounts/store.test.ts, factory/api/src/accounts/store.ts, factory/api/src/app.ts, factory/api/src/auth/deps.ts, factory/api/src/auth/verify.ts, factory/api/src/env.ts, factory/api/src/github-oidc/app.ts, factory/api/src/handlers/api.test.ts, factory/api/src/handlers/api.ts, factory/api/src/handlers/github-oidc.ts, factory/api/src/handlers/ingest.ts, factory/api/src/handlers/issue-requests.ts, factory/api/src/index.ts, factory/api/src/progress/deps.ts, factory/api/src/routes/accounts.ts, factory/api/src/routes/factory.test.ts, factory/api/src/routes/sprint-views.test.ts, factory/api/src/routes/teams.ts, factory/api/src/routes/views.ts, factory/api/src/runs/deps.ts, factory/api/src/testing/app.ts, factory/web/src/App.tsx, factory/web/src/context.tsx, factory/web/src/pages/AccountPage.tsx, factory/web/src/pages/BacklogPage.tsx, factory/web/src/pages/DelegationsPage.tsx, factory/web/src/pages/LoopDetailPage.tsx, factory/web/src/pages/LoopsPage.tsx, factory/web/src/pages/ModelCredentialPage.tsx, factory/web/src/pages/NewSprintPage.tsx, factory/web/src/pages/NewTeamPage.tsx, factory/web/src/pages/RepositoriesPage.tsx, factory/web/src/pages/SprintDetailPage.tsx, factory/web/src/pages/SprintsPage.tsx, factory/web/src/pages/TeamPage.tsx, factory/web/src/pages/parts.tsx, factory/web/src/poll.ts, scripts/tests/test_check_markdown_links.py, tests
  • テストの戦略: local-scoped-ci-whole(根拠 derived:test_duration)
  • 範囲テストの雛形: uv run --frozen --project . --all-extras pytest {paths} -q -n 4 -o junit_family=xunit1 --junitxml=.ndf/tmp/junit.xml / npm --prefix factory ci --no-audit --no-fund --silent && factory/node_modules/.bin/vitest run --root factory {paths} / python3 scripts/check-script-structure.py {paths}(静的解析) / python3 scripts/check-ndf-contracts.py {paths}(静的解析) / bash scripts/check-lint.sh -- {paths}(静的解析)
  • 最終ゲートへ寄せた危険フラグ: D1, D3, D4, D5(項目 I-003, I-002, I-004)
  • 着手前のテスト: npm --prefix factory ci --no-audit --no-fund --silent && factory/node_modules/.bin/vitest run --root factory factory/api/src/accounts/store.test.ts factory/api/src/handlers/api.test.ts factory/api/src/routes/factory.test.ts factory/api/src/routes/sprint-views.test.ts factory/api/src/testing/app.ts && uv run --frozen --project . --all-extras pytest scripts/tests/test_check_markdown_links.py tests -q -n 4 -o junit_family=xunit1 --junitxml=.ndf/tmp/junit.xml && python3 scripts/check-script-structure.py && python3 scripts/check-ndf-contracts.py && bash scripts/check-lint.sh(scope)
  • 着手前のテストの結果: 通過(40.6 秒 / HEAD f7c9a4d)
  • 既存失敗の件数: 0
  • 想定最大時間: 30 分 / 改修計画の時点で使えた時間: 5.37 分
  • 実装担当: claude

改善項目

I-001 — factory/api/src/testing/app.ts#createTestApi

兆候 手法 重要度 等級 提案元 状態 コミット
duplication extract_test_helper major high claude / codex 取り消し 0

なぜ: FactoryDeps の組み立て(RepositoryService・CredentialService・LoopControl・memoryProgressReader など 9 項目)が testing/app.ts:93-101・routes/factory.test.ts:82-90・routes/sprint-views.test.ts:100-110 の 3 か所に写されている(jscpd が 9 行を検出)。連番の newId(00000000-0000-4000-8000-…)も同じ 3 か所、FakeSecrets は testing/app.ts と factory.test.ts に 2 つあり、後者は fail を足しただけ。FactoryDeps に項目が増えるたびに 3 か所を直すことになる

手順: 1. testing/app.ts に sequentialIds(): () => string を足し、3 か所の newId を置き換える
2. testing/app.ts に testFactoryDeps(h, { secrets, github?, proofKey?, candidateModel? }): FactoryDeps を足し、createTestApi の組み立てをこれへ置き換える
3. testing/app.ts の FakeSecrets に fail = false を足して create/put/delete で投げるようにし、factory.test.ts の写しを消して import する
4. factory.test.ts と sprint-views.test.ts の beforeEach の組み立てを testFactoryDeps へ置き換える(sprint-views は github に呼び出しを数える Proxy、proofKey に new Uint8Array(32)、secrets に noSecrets を渡す)
5. factory.test.ts・sprint-views.test.ts・api.test.ts を実行する

取り消した理由: テストの期待する振る舞いが変わっています(factory/api/src/routes/factory.test.ts, factory/api/src/routes/sprint-views.test.ts)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください

I-002 — factory/web/src/pages/SprintsPage.tsx#repositoryNames

兆候 手法 重要度 等級 提案元 状態 コミット
dead_code remove_dead_code minor medium codex 採用 1

なぜ: リポジトリ全体で repositoryNames を検索すると定義だけが見つかる。一覧は既に SprintRunRow.repo を表示し、名前がない場合は repository_id の文へフォールバックしているため、一覧とは別に名前を取得するこの関数と Repository 型の import は使われていない。web は private のブラウザアプリで、この関数を配布用の公開 API として使う入口もない。

手順: 1. 参照検索を再確認し、repositoryNames の定義とその説明コメントを削除する。
2. Repository の型 import だけを削除し、SprintRunRow と SprintsPage の表示処理は維持する。
3. 既存の pages/sprints.test.tsx と TypeScript の型検査を実行し、一覧のリポジトリ表示・状態のタブ・読み直しが変わらないことを確認する。呼び出しを新設して関数を生かす変更は行わない。

I-003 — factory/api/src/accounts/service.ts#AccountService

兆候 手法 重要度 等級 提案元 状態 コミット
duplication extract_method minor medium claude 採用 1

なぜ: 席の履歴の行(accountId・type・at・actor・before/after の { user_id, seat_type })が createTeam・addSeat・changeSeat・removeSeat の 4 か所で手で組まれている。account.created には accountCreated があるのに、席の履歴だけ共通化されていない

手順: 1. accountCreated の隣に private seatHistory(type: 'seat.added' | 'seat.changed' | 'seat.removed', accountId, at, actor, userId, before: SeatType | null, after: SeatType | null): HistoryRecord を足す(null の側は before/after を null にする)
2. createTeam と addSeat の seat.added を seatHistory へ置き換える
3. changeSeat と removeSeat の history の組み立てを置き換える
4. handlers/api.test.ts(履歴の type と中身を見るテスト)を実行する

I-004 — factory/api/src/accounts/service.ts#AccountService

兆候 手法 重要度 等級 提案元 状態 コミット
divergent_change extract_class major low kiro 採用 1

なぜ: AccountService(340 行・36 関数)が、利用者と文脈の解決(ensureUser/resolveFor/context/listAccounts)・席の管理(addSeat/changeSeat/removeSeat/requireTeamOwner)・料金プランと実行形態(setPlan/setExecutionMode)の 3 つの関心を 1 クラスに持ち、別々の理由で変わる

手順: 1. 席の操作(requireTeamOwner/addSeat/changeSeat/removeSeat)を SeatService として切り出し、store と retryOnConflict を共有して注入
2. AccountService は席の操作をその型へ委譲する
3. 呼び出し元(routes/teams.ts・testing/app.ts)の参照を新しい型へ合わせる
4. store.test.ts / api.test.ts / factory.test.ts を実行して公開の振る舞いが不変であることを確認

指標の測定

  • 状態: written / 言語とツールの対応: 既定(.ndf/code-metrics.json は無い) / 所要: 3.8 秒(使えた時間 90 秒 / 上限 90 秒)
  • 指標のファイル: /tmp/ndf-worktrees/devbasex--ai-plugins/rf2534/work/.cross_refactoring/code-metrics-rf2534.md
言語 ツール 版 ランナー ファイル 秒 結果
python ruff-complexipy ruff 0.16.9 / complexipy 8.0.1 uvx 4 0.4 測った
shell — — — 10 — unsupported_language
typescript lizard lizard 1.24.0 uvx 40 0.4 測った
重複: python symilar pylint 4.0.9 uvx 4 0.7 測った(0 箇所)
重複: shell, typescript jscpd jscpd 4.3.0 npx 50 2.3 測った(6 箇所)

時間の上限

値 中身
提案の枠の終わり(監視の上限 = 残り + 余裕) 2026-11-05T02:48:19+00:00
改修計画の枠の終わり(同上) 2026-11-05T02:51:19+00:00
テストの追加の終わり = 実装の終わり − Σ(採っていて未検証の項目の実装の見積り) 2026-11-05T02:52:26+00:00
実装の終わり = 最終ゲートの修正の打ち切り − バッファ − Σ(採っていて未検証の項目の検証の見積り) 2026-11-05T02:53:04+00:00
直しの試行の打ち切り 2026-11-05T02:55:00+00:00
想定最大時間の終わり H(子プロセスはすべてここまでに止まる) 2026-11-05T03:11:39+00:00
確かめの開始の締め切り = H − 確かめの見込み(最終ゲート修正と打ち切りの後の取り消しもここまで) 2026-11-05T02:56:17+00:00
確かめの見込み(秒。最終ゲートの確かめ 1 回。バッファの最終ゲートの全体テスト) 922
最終ゲート修正 1 回の見込み(秒。バッファの final_fix。起動は今 + この値が確かめの開始の締め切り以前のときだけ) 77
指標の測定の上限(秒。提案の枠の中から割く) 90
着手前のテスト 1 回の上限(秒) 4644
範囲テスト 1 回の上限(秒) 122
手元の全体テスト 1 回の上限(秒) 4644
CI の待ちの上限(秒) 2766
余裕(秒。手順の上限と CLI の上限に足す) 90

入力: 予算 30 分 / 全体テストの所要 w 1548.0(ci-steps) / 着手前の実測 x 40.6 / CI の壁時計 c 922.0 / 着手前のテストの所要の見込み s 1548.0(whole) / 戦略 local-scoped-ci-whole

無音の打ち切りは手順の監視の上限と同じ値である。項目ごとの期限は持たない(実装を止めるのは実装の終わりだけ)。

見送った提案

対象 兆候 理由 根拠(MVV) 補足
factory/web/src/pages/DelegationsPage.tsx#DelegationsPage long_method no_target Value 3 / C1 / Value 2 / Value 1 / Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/LoopsPage.tsx#LoopsPage.start conditional_chain no_target Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/LoopsPage.tsx#LoopsPage.start long_method no_target Value 3 / Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/api/src/github-oidc/app.ts#createGithubOidcApp divergent_change no_target C2 / Value 3 / Value 7 / Value 5 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/api/src/github-oidc/app.ts#createGithubOidcApp duplication no_target C2 / Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/SprintsPage.tsx#SprintsPage duplication no_target Value 7 / Value 5 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/api/src/handlers/ingest.ts#webhookSecretFromEnv duplication no_target C1 / Value 3 / Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/api/src/runs/deps.ts#factoryDepsFromEnv scattered_config no_target Value 3 / C1 / Value 7 / Value 6 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/LoopDetailPage.tsx#LoopDetailPage.act duplication no_target Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/LoopsPage.tsx#LoopsPage duplication no_target Value 3 / Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/ModelCredentialPage.tsx#save long_method no_target Value 3 / C1 / Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/NewSprintPage.tsx#NewSprintPage.start conditional_chain no_target Value 7 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/SprintDetailPage.tsx#StepPanel long_method no_target Value 3 / Value 2 / Value 1 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/web/src/pages/TeamPage.tsx#TeamPage.act duplication no_target Value 7 / Value 5 範囲テストを組み立てられない(test_targets が --scope のテストの置き場所に無いか、雛形を持つ suite が無い)
factory/api/src/accounts/service.ts#validateSeatType divergent_change budget Value 7 見積り 1.8 分が残りに入らない
factory/api/src/routes/factory.test.ts#FakeSecrets duplication budget Value 7 / Value 5 見積り 1.8 分が残りに入らない
scripts/tests/test_check_markdown_links.py#run duplication budget Value 7 見積り 1.8 分が残りに入らない
scripts/tests/test_check_markdown_links.py#test_heading_anchors_collision_with_explicit_numbered_heading inconsistent_naming budget Value 8 / Value 7 見積り 1.8 分が残りに入らない
factory/api/src/accounts/store.ts#DynamoAccountStore.createTeam magic_value budget Value 1 / C3 / Value 7 見積り 2.7 分が残りに入らない
factory/api/src/app.ts#createApiApp long_parameter_list budget Value 7 見積り 4.6 分が残りに入らない
factory/api/src/accounts/service.ts#resolveFor long_method budget Value 3 / C2 / Value 7 見積り 1.6 分が残りに入らない
factory/api/src/accounts/service.ts#AccountService.listAccounts one_by_one_iteration budget Value 4 / C2 / Value 7 見積り 1.8 分が残りに入らない

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | codex | APPROVE

指定基準に該当する修正指摘はありません。

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | kiro | APPROVE

43 ファイルを確認。アカウントの競合・再試行の切り出し(conflict.ts / SeatService)、app.ts と deps.ts の分離、web のログイン判定の RequireLogin への集約、useAttempt への例外処理の集約、dead code 削除、テストの fixture 化のいずれも、挙動を保つ構造改善であることを到達経路で確認した。setPlan/createTeam/ensureUser の条件失敗と非条件失敗の分岐、idempotency の勝者解決、認証経路の被覆、CORS、requireEnv、usePolled の呼び出し更新を追い、critical / major の基準に当たる食い違いは見つからなかった。指摘なし。

@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | commit (なし)

対応件数: critical=0 / major=0 / minor=0(合計 0 件)
決着: 0 件 / 見送り: 0 件 / 却下: 0 件
CI: NONE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant