Skip to content

feat(logger): Logger拡張・JSTタイムスタンプ追加・スクリプトTS化 - #7

Merged
aloekun merged 1 commit into
masterfrom
feat/logger-enhancement
Mar 30, 2026
Merged

feat(logger): Logger拡張・JSTタイムスタンプ追加・スクリプトTS化#7
aloekun merged 1 commit into
masterfrom
feat/logger-enhancement

Conversation

@aloekun

@aloekun aloekun commented Mar 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • Logger に JST タイムスタンプ出力を追加(2026/03/30 14:45:43 [INFO] ... 形式)
  • scripts/deploy-hooks.js.ts に変換、全 console.log を Logger に置換
  • scripts/e2e.mjs.ts に変換、console.log を Logger に置換
  • package.jsondeploy:hooks / test:e2enpx tsx 実行に変更

Why

  • カスタムリンター (no-console-log) との一貫性: プロジェクト内のすべての出力を Logger 経由に統一
  • TypeScript 化により静的解析の恩恵を受けられる(型安全性・AIコーディングとの親和性向上)
  • タイムスタンプ追加でデプロイ失敗時の時系列追跡が容易に

Test plan

  • pnpm deploy:hooks — 2ターゲットに正常デプロイ、JSTタイムスタンプ付きログ出力を確認
  • pnpm test:e2e.env.e2e なしで正常スキップを確認
  • sample.tsconsole.log は意図的なリントテスト用として維持

🤖 Generated with Claude Code

Summary by CodeRabbit

リリースノート

  • 改善

    • ログ出力にJST形式のタイムスタンプが追加され、ログ可読性が向上しました
    • E2Eランナーの起動ログが統一ロガー経由になり、スキップ通知などが一貫して記録されます
  • Chores

    • テスト/運用スクリプトをTypeScriptで実行するよう移行し、実行方法をモダン化しました
    • フックの一括展開処理を更新し、各プロジェクトへのフック配布と設定ファイル生成が改善されました

@coderabbitai

coderabbitai Bot commented Mar 30, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5efac996-1039-4564-a625-ba74016757b1

📥 Commits

Reviewing files that changed from the base of the PR and between 44c2cde and 9e4f2ea.

📒 Files selected for processing (5)
  • package.json
  • scripts/deploy-hooks.js
  • scripts/deploy-hooks.ts
  • scripts/e2e.ts
  • src/logger.ts
💤 Files with no reviewable changes (1)
  • scripts/deploy-hooks.js
✅ Files skipped from review due to trivial changes (2)
  • scripts/e2e.ts
  • package.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/logger.ts
  • scripts/deploy-hooks.ts

📝 Walkthrough

Walkthrough

TypeScript化と実行コマンド更新:deploy-hooksをJS→TSに移植し、test:e2e/deploy:hooksnpx tsx 経由で実行するように変更。ログにJSTタイムスタンプを追加し、E2Eスクリプトの初期スキップ出力を logger.info に変更した。

Changes

Cohort / File(s) Summary
スクリプト実行設定更新
package.json
test:e2edeploy:hooks スクリプトを node 実行から npx tsx を使った TypeScript 実行に変更。
デプロイスクリプト移行
scripts/deploy-hooks.js, scripts/deploy-hooks.ts, scripts/deploy-targets.json
scripts/deploy-hooks.js を削除し、同等のロジックを持つ scripts/deploy-hooks.ts を追加。ターゲット読み取り、各ターゲットへの .claude ディレクトリ作成、フック実行ファイルのコピー、hooks-config.toml の存在チェック、settings.local.json.template の展開・検証・既存ファイルへの hooks フィールドマージまたは上書きを行う。scripts/deploy-targets.json を参照する挙動を維持。
E2Eランナー更新
scripts/e2e.ts
.env.e2e がない場合のスキップ出力を console.log から logger.info に変更し、ファイル上部に JSDoc コメントを追加。動作フローは変更なし。
ロガー強化
src/logger.ts
JST(Asia/Tokyo)のタイムスタンプを生成する jstTimestamp() を追加し、各ログ出力で YYYY/MM/DD ... [LEVEL] のプリフィクスを付与するようにフォーマットを変更。ログレベル判定やAPIはそのまま。

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Runner as deploy-hooks.ts
    participant Repo as repo/.claude + template
    participant Targets as target projects (each)
    participant FS as filesystem
    participant Logger as logger/console

    Runner->>FS: read scripts/deploy-targets.json
    alt valid targets
        Runner->>Targets: for each target -> check dir exists
        Targets-->>Runner: exists / missing
        alt exists
            Runner->>FS: ensure <target>/.claude/ exists
            Runner->>Repo: read repo/.claude/* hook binaries
            Repo-->>Runner: hook files (or missing)
            Runner->>FS: copy hook binaries into <target>/.claude/
            Runner->>FS: check <target>/.claude/hooks-config.toml
            Runner->>Repo: read settings.local.json.template (if exists)
            Repo-->>Runner: template content
            Runner->>Runner: replace {{PROJECT_DIR}} -> resolved JSON
            Runner->>FS: read existing <target>/.claude/settings.local.json (if any)
            alt existing valid JSON
                Runner->>Runner: merge only "hooks" field
            else
                Runner->>FS: write resolved settings.local.json (overwrite)
            end
            Runner->>Logger: log per-target result
        end
    end
    Runner->>Logger: log final success/total summary
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed このPRのタイトルは、Logger拡張、JSTタイムスタンプ追加、スクリプトのTypeScript化という3つの主要な変更を簡潔に要約しており、変更セットの主な目的と完全に関連しています。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/deploy-hooks.ts`:
- Around line 87-100: The template parsing branch in scripts/deploy-hooks.ts
treats a JSON parse failure as success by returning true; change the failure
return to false so the caller correctly counts failures—specifically inside the
block that reads templateSrc/SETTINGS_TEMPLATE where you catch the JSON.parse
error (the catch that calls logger.warn) replace the current return true with
return false; also update the similar return at the other occurrence around the
later template resolution (the analogous catch/return near lines 149–151) so
both failure paths return false and the success++ aggregation reflects real
successes.
- Around line 43-44: The code currently returns data.targets directly
(DeployTargets → data.targets) which can be a wrong type at runtime; add a
runtime validation after parsing (using targetsPath/readFileSync result) to
ensure data.targets is an array of strings (string[]) and if not, log an error
via processLogger (or console.error) with the file/field and exit(1) so the
later loop cannot misbehave; locate the JSON parse area where DeployTargets is
read and replace the direct return of data.targets ?? [] with a check like:
ensure Array.isArray(data.targets) && data.targets.every(t => typeof t ===
"string"), otherwise abort.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 27e8bd1f-daf8-4066-bbb4-094b91c4d239

📥 Commits

Reviewing files that changed from the base of the PR and between fa2f186 and 44c2cde.

📒 Files selected for processing (5)
  • package.json
  • scripts/deploy-hooks.js
  • scripts/deploy-hooks.ts
  • scripts/e2e.ts
  • src/logger.ts
💤 Files with no reviewable changes (1)
  • scripts/deploy-hooks.js

Comment thread scripts/deploy-hooks.ts Outdated
Comment thread scripts/deploy-hooks.ts
- Logger に JST タイムスタンプ出力を追加
- scripts/deploy-hooks.js → .ts に変換、console.log を Logger に置換
- scripts/e2e.mjs → .ts に変換、console.log を Logger に置換
- package.json の deploy:hooks / test:e2e を npx tsx 実行に変更
- CodeRabbitレビュー反映:
  - deploy-targets.json の targets を実行時に string[] 検証
  - テンプレート解決失敗時に false を返すよう修正

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@aloekun
aloekun force-pushed the feat/logger-enhancement branch from 44c2cde to 9e4f2ea Compare March 30, 2026 06:24
@aloekun
aloekun merged commit cdd1551 into master Mar 30, 2026
1 check passed
@aloekun
aloekun deleted the feat/logger-enhancement branch March 30, 2026 07:33
aloekun added a commit that referenced this pull request Apr 18, 2026
… 更新)

docs/todo.md の「セッション 247510ea 由来: 整備タスク群 (PR-A)」を反映。

- ADR-028 (新規): 外部可視成果物の生成コマンド (pnpm create-pr / pnpm merge-pr 等) の実行ゲート
- ADR-021 (原則 5 追加): bookmark 検出標準 (BOOKMARK_SEARCH_REVSETS / TRUNK_BOOKMARKS) + option A/B/C 比較
- ADR-024 (本採用に格上げ): 3 箇所 port 完了 (cli-push-runner / cli-merge-pipeline / cli-pr-monitor) により早期達成
- ADR-019 (制約・可換性追記): CodeRabbit 無料枠 1h 3 回制約、ハイブリッド再定義、M5 不採用論拠
- CLAUDE.md: ADR-028 追加、ADR-024 試験運用マーカー除去
- docs/todo.md: PR-A タスク削除 + 後続リナンバー (PR-B/C/D → #7/8/9)

refs: PR #54, PR #55, セッション 247510ea-3f24-4b87-8f68-3c860e1b1b4e
aloekun added a commit that referenced this pull request Apr 18, 2026
… 更新)

docs/todo.md の「セッション 247510ea 由来: 整備タスク群 (PR-A)」を反映。

- ADR-028 (新規): 外部可視成果物の生成コマンド (pnpm create-pr / pnpm merge-pr 等) の実行ゲート
- ADR-021 (原則 5 追加): bookmark 検出標準 (BOOKMARK_SEARCH_REVSETS / TRUNK_BOOKMARKS) + option A/B/C 比較
- ADR-024 (本採用に格上げ): 3 箇所 port 完了 (cli-push-runner / cli-merge-pipeline / cli-pr-monitor) により早期達成
- ADR-019 (制約・可換性追記): CodeRabbit 無料枠 1h 3 回制約、ハイブリッド再定義、M5 不採用論拠
- CLAUDE.md: ADR-028 追加、ADR-024 試験運用マーカー除去
- docs/todo.md: PR-A タスク削除 + 後続リナンバー (PR-B/C/D → #7/8/9)

refs: PR #54, PR #55, セッション 247510ea-3f24-4b87-8f68-3c860e1b1b4e
aloekun added a commit that referenced this pull request Apr 18, 2026
… 更新) (#56)

docs/todo.md の「セッション 247510ea 由来: 整備タスク群 (PR-A)」を反映。

- ADR-028 (新規): 外部可視成果物の生成コマンド (pnpm create-pr / pnpm merge-pr 等) の実行ゲート
- ADR-021 (原則 5 追加): bookmark 検出標準 (BOOKMARK_SEARCH_REVSETS / TRUNK_BOOKMARKS) + option A/B/C 比較
- ADR-024 (本採用に格上げ): 3 箇所 port 完了 (cli-push-runner / cli-merge-pipeline / cli-pr-monitor) により早期達成
- ADR-019 (制約・可換性追記): CodeRabbit 無料枠 1h 3 回制約、ハイブリッド再定義、M5 不採用論拠
- CLAUDE.md: ADR-028 追加、ADR-024 試験運用マーカー除去
- docs/todo.md: PR-A タスク削除 + 後続リナンバー (PR-B/C/D → #7/8/9)

refs: PR #54, PR #55, セッション 247510ea-3f24-4b87-8f68-3c860e1b1b4e
aloekun added a commit that referenced this pull request Apr 18, 2026
…プト化 + prepare-pr-body helper 新設 (PR-B)

ADR-028 の二次防衛層を実装。`permissions.ask` の "ask > allow" precedence により、auto mode でも毎回確認プロンプトが発火するようになる。

- `.claude/settings.json`: `permissions.ask` に 4 パターン追加
  - `Bash(pnpm create-pr*)`, `Bash(pnpm merge-pr*)`
  - `Bash(*cli-pr-monitor.exe*)`, `Bash(*cli-merge-pipeline.exe*)`
- `.claude/settings.local.json.template`: `pnpm create-pr` / `merge-pr` の allow 登録を削除 (ADR-028 の二層防衛と矛盾する誤解を招くため)
- `scripts/prepare-pr-body.ps1` 新規: stdin から PR body を受け取り `.tmp-pr-body.md` に UTF-8 (BOM なし) で書き出す helper。`-Cleanup` で削除
- `package.json`: `prepare-pr-body` / `prepare-pr-body:cleanup` スクリプト追加
- `.gitignore`: `.tmp-pr-body.md` を除外 (一時ファイル)
- `docs/adr/adr-028-pnpm-create-pr-gate.md`: PR-B 実装済みに反映、PR-D 参照番号を更新
- `docs/todo.md`: PR-B タスク削除 + 後続リナンバー (PR-C → #7, PR-D → #8)

smoke test:
- `echo "日本語" | pnpm prepare-pr-body` で UTF-8 が保持されることを確認
- `pnpm prepare-pr-body:cleanup` で `.tmp-pr-body.md` 削除動作を確認

refs: ADR-028, PR #56 (PR-A, ADR 集約)
aloekun added a commit that referenced this pull request Apr 18, 2026
…プト化 + prepare-pr-body helper 新設 (PR-B)

ADR-028 の二次防衛層を実装。`permissions.ask` の "ask > allow" precedence により、auto mode でも毎回確認プロンプトが発火するようになる。

- `.claude/settings.json`: `permissions.ask` に 4 パターン追加
  - `Bash(pnpm create-pr*)`, `Bash(pnpm merge-pr*)`
  - `Bash(*cli-pr-monitor.exe*)`, `Bash(*cli-merge-pipeline.exe*)`
- `.claude/settings.local.json.template`: `pnpm create-pr` / `merge-pr` の allow 登録を削除 (ADR-028 の二層防衛と矛盾する誤解を招くため)
- `scripts/prepare-pr-body.ps1` 新規: stdin から PR body を受け取り `.tmp-pr-body.md` に UTF-8 (BOM なし) で書き出す helper。`-Cleanup` で削除
- `package.json`: `prepare-pr-body` / `prepare-pr-body:cleanup` スクリプト追加
- `.gitignore`: `.tmp-pr-body.md` を除外 (一時ファイル)
- `docs/adr/adr-028-pnpm-create-pr-gate.md`: PR-B 実装済みに反映、PR-D 参照番号を更新
- `docs/todo.md`: PR-B タスク削除 + 後続リナンバー (PR-C → #7, PR-D → #8)

smoke test:
- `echo "日本語" | pnpm prepare-pr-body` で UTF-8 が保持されることを確認
- `pnpm prepare-pr-body:cleanup` で `.tmp-pr-body.md` 削除動作を確認

refs: ADR-028, PR #56 (PR-A, ADR 集約)
aloekun added a commit that referenced this pull request Apr 18, 2026
…プト化 + prepare-pr-body helper 新設 (PR-B) (#57)

ADR-028 の二次防衛層を実装。`permissions.ask` の "ask > allow" precedence により、auto mode でも毎回確認プロンプトが発火するようになる。

- `.claude/settings.json`: `permissions.ask` に 4 パターン追加
  - `Bash(pnpm create-pr*)`, `Bash(pnpm merge-pr*)`
  - `Bash(*cli-pr-monitor.exe*)`, `Bash(*cli-merge-pipeline.exe*)`
- `.claude/settings.local.json.template`: `pnpm create-pr` / `merge-pr` の allow 登録を削除 (ADR-028 の二層防衛と矛盾する誤解を招くため)
- `scripts/prepare-pr-body.ps1` 新規: stdin から PR body を受け取り `.tmp-pr-body.md` に UTF-8 (BOM なし) で書き出す helper。`-Cleanup` で削除
- `package.json`: `prepare-pr-body` / `prepare-pr-body:cleanup` スクリプト追加
- `.gitignore`: `.tmp-pr-body.md` を除外 (一時ファイル)
- `docs/adr/adr-028-pnpm-create-pr-gate.md`: PR-B 実装済みに反映、PR-D 参照番号を更新
- `docs/todo.md`: PR-B タスク削除 + 後続リナンバー (PR-C → #7, PR-D → #8)

smoke test:
- `echo "日本語" | pnpm prepare-pr-body` で UTF-8 が保持されることを確認
- `pnpm prepare-pr-body:cleanup` で `.tmp-pr-body.md` 削除動作を確認

refs: ADR-028, PR #56 (PR-A, ADR 集約)
aloekun added a commit that referenced this pull request Apr 18, 2026
cli-pr-monitor / cli-merge-pipeline / cli-push-runner の 3 クレートで重複していた bookmark 検出ロジックを ADR-024 (本採用) に従い `src/lib-jj-helpers/` に集約。

## 新クレート

- `src/lib-jj-helpers/` 新設 (ADR-012 命名規約、ADR-026 workspace 準拠)
- 公開 API:
  - 定数: `TRUNK_BOOKMARKS`, `BOOKMARK_SEARCH_REVSETS`
  - 関数: `is_trunk_bookmark`, `parse_bookmark_list_output`, `query_bookmarks_at`, `select_from_revsets`, `get_jj_bookmarks`
  - 型: `StderrMode { Silent, Piped(fn(&str)) }`
- 14 unit tests (fallback_log コールバック検証 2 件を新規追加)

## 設計方針

- **stderr ハンドリングを `StderrMode` で選択**: cli-pr-monitor は `Silent` (CI ログ汚染回避)、cli-merge-pipeline は `Piped(log_info)` (診断情報を出す)
- **log 関数は `fn(&str)` ポインタで注入**: 各クレート固有 prefix (`[post-pr-monitor]` / `[merge-pipeline]`) を崩さない
- **fallback_log は `Option<fn(&str)>`**: `@-` や `@--` で hit した場合のみ通知 (noise 抑制)

## 呼び出し側差し替え

- cli-pr-monitor (`util.rs`): `get_jj_bookmarks()` を lib 呼び出しに置換、重複テスト削除
- cli-merge-pipeline (`main.rs`): 同上、stderr は `Piped` で継続
- cli-push-runner (`push_jj_bookmark.rs`): `is_trunk_bookmark` のみ lib 借用、他ロジックは crate-local 保持 (`parse_bookmark_list_output` は `jj bookmark list` 出力用で semantics が異なる)

## 検証

- cargo test --workspace: 363 tests PASS (1 ignored)
- pnpm build:all: 全 9 exe ビルド成功
- cargo clippy: modified 4 クレートに warning なし
- 行数インパクト: +425 / -492 = net -67 行 (重複テスト集約効果)

## ADR 更新

- ADR-024: 実装フェーズを「実施済」に反映、`capture_commit_id` / `diff_is_empty` は将来 PR で段階的移設と明記
- ADR-021 原則 5: 「3 クレートで重複 → lib-jj-helpers に集約済」と完了反映
- ADR-028: PR-D 参照番号を #7 に更新 (PR-B/PR-C 完了で docs/todo.md がリナンバー)

refs: ADR-024, ADR-021, PR #56 (PR-A), PR #57 (PR-B), PR #54, PR #55
aloekun added a commit that referenced this pull request Apr 19, 2026
cli-pr-monitor / cli-merge-pipeline / cli-push-runner の 3 クレートで重複していた bookmark 検出ロジックを ADR-024 (本採用) に従い `src/lib-jj-helpers/` に集約。

## 新クレート

- `src/lib-jj-helpers/` 新設 (ADR-012 命名規約、ADR-026 workspace 準拠)
- 公開 API:
  - 定数: `TRUNK_BOOKMARKS`, `BOOKMARK_SEARCH_REVSETS`
  - 関数: `is_trunk_bookmark`, `parse_bookmark_list_output`, `query_bookmarks_at`, `select_from_revsets`, `get_jj_bookmarks`
  - 型: `StderrMode { Silent, Piped(fn(&str)) }`
- 14 unit tests (fallback_log コールバック検証 2 件を新規追加)

## 設計方針

- **stderr ハンドリングを `StderrMode` で選択**: cli-pr-monitor は `Silent` (CI ログ汚染回避)、cli-merge-pipeline は `Piped(log_info)` (診断情報を出す)
- **log 関数は `fn(&str)` ポインタで注入**: 各クレート固有 prefix (`[post-pr-monitor]` / `[merge-pipeline]`) を崩さない
- **fallback_log は `Option<fn(&str)>`**: `@-` や `@--` で hit した場合のみ通知 (noise 抑制)

## 呼び出し側差し替え

- cli-pr-monitor (`util.rs`): `get_jj_bookmarks()` を lib 呼び出しに置換、重複テスト削除
- cli-merge-pipeline (`main.rs`): 同上、stderr は `Piped` で継続
- cli-push-runner (`push_jj_bookmark.rs`): `is_trunk_bookmark` のみ lib 借用、他ロジックは crate-local 保持 (`parse_bookmark_list_output` は `jj bookmark list` 出力用で semantics が異なる)

## 検証

- cargo test --workspace: 363 tests PASS (1 ignored)
- pnpm build:all: 全 9 exe ビルド成功
- cargo clippy: modified 4 クレートに warning なし
- 行数インパクト: +425 / -492 = net -67 行 (重複テスト集約効果)

## ADR 更新

- ADR-024: 実装フェーズを「実施済」に反映、`capture_commit_id` / `diff_is_empty` は将来 PR で段階的移設と明記
- ADR-021 原則 5: 「3 クレートで重複 → lib-jj-helpers に集約済」と完了反映
- ADR-028: PR-D 参照番号を #7 に更新 (PR-B/PR-C 完了で docs/todo.md がリナンバー)

refs: ADR-024, ADR-021, PR #56 (PR-A), PR #57 (PR-B), PR #54, PR #55
aloekun added a commit that referenced this pull request Apr 19, 2026
cli-pr-monitor / cli-merge-pipeline / cli-push-runner の 3 クレートで重複していた bookmark 検出ロジックを ADR-024 (本採用) に従い `src/lib-jj-helpers/` に集約。

## 新クレート

- `src/lib-jj-helpers/` 新設 (ADR-012 命名規約、ADR-026 workspace 準拠)
- 公開 API:
  - 定数: `TRUNK_BOOKMARKS`, `BOOKMARK_SEARCH_REVSETS`
  - 関数: `is_trunk_bookmark`, `parse_bookmark_list_output`, `query_bookmarks_at`, `select_from_revsets`, `get_jj_bookmarks`
  - 型: `StderrMode { Silent, Piped(fn(&str)) }`
- 14 unit tests (fallback_log コールバック検証 2 件を新規追加)

## 設計方針

- **stderr ハンドリングを `StderrMode` で選択**: cli-pr-monitor は `Silent` (CI ログ汚染回避)、cli-merge-pipeline は `Piped(log_info)` (診断情報を出す)
- **log 関数は `fn(&str)` ポインタで注入**: 各クレート固有 prefix (`[post-pr-monitor]` / `[merge-pipeline]`) を崩さない
- **fallback_log は `Option<fn(&str)>`**: `@-` や `@--` で hit した場合のみ通知 (noise 抑制)

## 呼び出し側差し替え

- cli-pr-monitor (`util.rs`): `get_jj_bookmarks()` を lib 呼び出しに置換、重複テスト削除
- cli-merge-pipeline (`main.rs`): 同上、stderr は `Piped` で継続
- cli-push-runner (`push_jj_bookmark.rs`): `is_trunk_bookmark` のみ lib 借用、他ロジックは crate-local 保持 (`parse_bookmark_list_output` は `jj bookmark list` 出力用で semantics が異なる)

## 検証

- cargo test --workspace: 363 tests PASS (1 ignored)
- pnpm build:all: 全 9 exe ビルド成功
- cargo clippy: modified 4 クレートに warning なし
- 行数インパクト: +425 / -492 = net -67 行 (重複テスト集約効果)

## ADR 更新

- ADR-024: 実装フェーズを「実施済」に反映、`capture_commit_id` / `diff_is_empty` は将来 PR で段階的移設と明記
- ADR-021 原則 5: 「3 クレートで重複 → lib-jj-helpers に集約済」と完了反映
- ADR-028: PR-D 参照番号を #7 に更新 (PR-B/PR-C 完了で docs/todo.md がリナンバー)

refs: ADR-024, ADR-021, PR #56 (PR-A), PR #57 (PR-B), PR #54, PR #55
aloekun added a commit that referenced this pull request Apr 19, 2026
ADR-028 (外部可視成果物の生成コマンドの実行ゲート) の運用フローを skill として明文化。

`pnpm push` 完了後の PR 作成で以下の 7 ステップを標準化する:

1. jj status + jj log -r master..@ で差分/bookmark 確認
2. commit description から PR title 初稿生成 (70 文字超は短縮、conventional prefix 維持)
3. diff + commit log から PR body 初稿生成 (Summary/Context/Validation/References)
4. Claude が提示 → AskUserQuestion で明示承認 (auto mode でも必須)
5. `pnpm prepare-pr-body` 経由で `.tmp-pr-body.md` に書き出し
6. `pnpm create-pr --title ... --body-file ...` foreground 実行 (permissions.ask で再確認)
7. `pnpm prepare-pr-body:cleanup` で一時ファイル削除

## 設計ハイライト

- **ADR-028 二層防衛の活用**: skill 内の AskUserQuestion (一次) + permissions.ask (二次)
- **user-supplied text の尊重** (ADR-022): 承認済 draft の二重書き換えを禁止
- **body は必ず一時ファイル経由**: `--body "..."` 引数経由の切り詰めリスク回避 (PR #51 / memory `feedback_pnpm_create_pr_body.md`)
- **automated actor から独立**: takt / cli-* の自律ループはこの skill を呼ばない

## ステータス

試験運用 (2026-04-19〜)。発火頻度・UX を半年観察して正式採用 / 改良 / 廃止を判断する。

## ファイル

- `.claude/skills/prepare-pr/SKILL.md` 新設 (178 行)

## docs/todo.md

- PR-D 完了に伴い「セッション 247510ea 由来: 整備タスク群」ブロック全体を削除
- 雑務 task をリナンバー (#8#7)

refs: ADR-028, ADR-022, PR #57 (PR-B body helper), memory `feedback_bookmark_auto_naming.md`
aloekun added a commit that referenced this pull request Apr 19, 2026
ADR-028 (外部可視成果物の生成コマンドの実行ゲート) の運用フローを skill として明文化。

`pnpm push` 完了後の PR 作成で以下の 7 ステップを標準化する:

1. jj status + jj log -r master..@ で差分/bookmark 確認
2. commit description から PR title 初稿生成 (70 文字超は短縮、conventional prefix 維持)
3. diff + commit log から PR body 初稿生成 (Summary/Context/Validation/References)
4. Claude が提示 → AskUserQuestion で明示承認 (auto mode でも必須)
5. `pnpm prepare-pr-body` 経由で `.tmp-pr-body.md` に書き出し
6. `pnpm create-pr --title ... --body-file ...` foreground 実行 (permissions.ask で再確認)
7. `pnpm prepare-pr-body:cleanup` で一時ファイル削除

## 設計ハイライト

- **ADR-028 二層防衛の活用**: skill 内の AskUserQuestion (一次) + permissions.ask (二次)
- **user-supplied text の尊重** (ADR-022): 承認済 draft の二重書き換えを禁止
- **body は必ず一時ファイル経由**: `--body "..."` 引数経由の切り詰めリスク回避 (PR #51 / memory `feedback_pnpm_create_pr_body.md`)
- **automated actor から独立**: takt / cli-* の自律ループはこの skill を呼ばない

## ステータス

試験運用 (2026-04-19〜)。発火頻度・UX を半年観察して正式採用 / 改良 / 廃止を判断する。

## ファイル

- `.claude/skills/prepare-pr/SKILL.md` 新設 (178 行)

## docs/todo.md

- PR-D 完了に伴い「セッション 247510ea 由来: 整備タスク群」ブロック全体を削除
- 雑務 task をリナンバー (#8#7)

refs: ADR-028, ADR-022, PR #57 (PR-B body helper), memory `feedback_bookmark_auto_naming.md`
aloekun added a commit that referenced this pull request Apr 19, 2026
ADR-028 (外部可視成果物の生成コマンドの実行ゲート) の運用フローを skill として明文化。

`pnpm push` 完了後の PR 作成で以下の 7 ステップを標準化する:

1. jj status + jj log -r master..@ で差分/bookmark 確認
2. commit description から PR title 初稿生成 (70 文字超は短縮、conventional prefix 維持)
3. diff + commit log から PR body 初稿生成 (Summary/Context/Validation/References)
4. Claude が提示 → AskUserQuestion で明示承認 (auto mode でも必須)
5. `pnpm prepare-pr-body` 経由で `.tmp-pr-body.md` に書き出し
6. `pnpm create-pr --title ... --body-file ...` foreground 実行 (permissions.ask で再確認)
7. `pnpm prepare-pr-body:cleanup` で一時ファイル削除

## 設計ハイライト

- **ADR-028 二層防衛の活用**: skill 内の AskUserQuestion (一次) + permissions.ask (二次)
- **user-supplied text の尊重** (ADR-022): 承認済 draft の二重書き換えを禁止
- **body は必ず一時ファイル経由**: `--body "..."` 引数経由の切り詰めリスク回避 (PR #51 / memory `feedback_pnpm_create_pr_body.md`)
- **automated actor から独立**: takt / cli-* の自律ループはこの skill を呼ばない

## ステータス

試験運用 (2026-04-19〜)。発火頻度・UX を半年観察して正式採用 / 改良 / 廃止を判断する。

## ファイル

- `.claude/skills/prepare-pr/SKILL.md` 新設 (178 行)

## docs/todo.md

- PR-D 完了に伴い「セッション 247510ea 由来: 整備タスク群」ブロック全体を削除
- 雑務 task をリナンバー (#8#7)

refs: ADR-028, ADR-022, PR #57 (PR-B body helper), memory `feedback_bookmark_auto_naming.md`
aloekun added a commit that referenced this pull request Apr 19, 2026
ADR-028 (外部可視成果物の生成コマンドの実行ゲート) の運用フローを skill として明文化。

`pnpm push` 完了後の PR 作成で以下の 7 ステップを標準化する:

1. jj status + jj log -r master..@ で差分/bookmark 確認
2. commit description から PR title 初稿生成 (70 文字超は短縮、conventional prefix 維持)
3. diff + commit log から PR body 初稿生成 (Summary/Context/Validation/References)
4. Claude が提示 → AskUserQuestion で明示承認 (auto mode でも必須)
5. `pnpm prepare-pr-body` 経由で `.tmp-pr-body.md` に書き出し
6. `pnpm create-pr --title ... --body-file ...` foreground 実行 (permissions.ask で再確認)
7. `pnpm prepare-pr-body:cleanup` で一時ファイル削除

## 設計ハイライト

- **ADR-028 二層防衛の活用**: skill 内の AskUserQuestion (一次) + permissions.ask (二次)
- **user-supplied text の尊重** (ADR-022): 承認済 draft の二重書き換えを禁止
- **body は必ず一時ファイル経由**: `--body "..."` 引数経由の切り詰めリスク回避 (PR #51 / memory `feedback_pnpm_create_pr_body.md`)
- **automated actor から独立**: takt / cli-* の自律ループはこの skill を呼ばない

## ステータス

試験運用 (2026-04-19〜)。発火頻度・UX を半年観察して正式採用 / 改良 / 廃止を判断する。

## ファイル

- `.claude/skills/prepare-pr/SKILL.md` 新設 (178 行)

## docs/todo.md

- PR-D 完了に伴い「セッション 247510ea 由来: 整備タスク群」ブロック全体を削除
- 雑務 task をリナンバー (#8#7)

refs: ADR-028, ADR-022, PR #57 (PR-B body helper), memory `feedback_bookmark_auto_naming.md`
aloekun added a commit that referenced this pull request Apr 28, 2026
* docs(todo): PR #88 post-merge-feedback の Tier 1/2 finding を採用

PR #88 post-merge-feedback (.claude/feedback-reports/88.md) で生成された 7 件の
finding のうち、ユーザー判断により #1-5 を採用、#6-7 を見送り。

採用 finding (5 件):
- T1 #1 (順位 5): Stop hook の `pnpm lint:md` 統合 — XS、順位 1 完了済の gap closure
- T1 #2 (順位 6): AI 生成一時スクリプト pattern の pre-push 検出 — Small、順位 1 と関連
- T2 #3 (順位 13): `vitest` を devDependencies に固定 — Small
- T2 #4 (順位 12): `cli-pr-monitor` ポーリング延長 + 重複起動ロック — Medium、★ rate-limit critical
- T2 #5 (順位 14): `pnpm create-pr` 必須引数ヘルプ改善 — Small

見送り finding:
- T3 #6: hook 統合時の commit 分割基準 → グローバルルール (~/.claude/) 編集は permission denied、要別経路
- T3 #7: jj rebase conflict 解消手順 → 同上

変更:
- docs/todo3.md 新設 (todo2.md が 50KB に到達したため、PR #88 以降の新規エントリは todo3.md へ)
- docs/todo.md 推奨実行順序サマリーに 5 件を Tier 別に挿入し、20 → 24 タスクへ全 renumber
- 戦略テキストと cross-reference を全面更新
- todo2.md / todo3.md 内の 順位 N 参照を新採番へ追従
- 順位 1 (markdownlint hook 統合) は merged 済として削除参照を merged context に書き換え

* fix(review): apply CodeRabbit fixes for #89

Resolved findings:
- [Minor] docs/todo.md:49 順位参照の文言が現行テーブルと不整合です
- [Major] docs/todo3.md:7 見出しリンクのアンカーが壊れる可能性があります
aloekun added a commit that referenced this pull request Apr 29, 2026
…Bundle 1) (#91)

* feat(lint): add PowerShell + Markdown anchor rules to ADR-007 layer

Bundle 1 (post-merge-feedback の旧順位 3 + 7 を 1 PR に統合):

- no-empty-powershell-catch (error): 空 `catch {}` ブロックでの swallowed error
  検出 (PR #85 T1-2 finding)
- no-silent-error-action (warning): `-ErrorAction SilentlyContinue` の検出
  (PR #85 T1-2 finding、片方単独 warning)
- no-mutable-anchor (warning): Markdown link の non-ASCII GFM fragment 検出
  (PR #89 T1-1 finding)

実装:
- .claude/custom-lint-rules.toml に 3 rule 追加
- src/hooks-post-tool-linter/src/main.rs に 13 unit test 追加
  (#7 の 4 edge case + ps1 / extension filter 全網羅)
- cargo test: 58 passed
- dogfood で 3 rule すべて発火確認

設計判断:
- ADR-007 既存 pattern (regex 層 / file 単位) に適合、ADR 更新不要
- #3 の "片方単独 warning / 組合せ error" spec は engine の per-line 設計で
  実現できないため、severity を rule 別に分離 (empty catch=error /
  SilentlyContinue=warning) で精神を保つ
- #7 は ADR-007 Q2 (string literal 誤検出) が borderline だが、MVP として
  regex 層採用。lookbehind 非対応のため backtick 内例は誤検出するが、
  task entry 削除で clean baseline 達成

Bundle 戦略 (post-merge-feedback ループ収束のため):
- 個別 PR なら 2 件 → 1 PR に統合 (50% 削減)
- summary table を 27 → 25 行に renumber、Tier breakdown 全更新

Closes feedback: PR #85 T1-2, PR #89 T1-1

* fix(lint): apply CodeRabbit findings on PR #91

PR #91 で受けた CodeRabbit findings 2 件を child commit として修正。

1. Major: PowerShell rule case-insensitivity (.claude/custom-lint-rules.toml:115-118)
   - PowerShell の `catch` keyword と `-ErrorAction` parameter は case-insensitive
     なので、`Catch {}` / `CATCH {}` / `-erroraction silentlycontinue` /
     `-ErrorAction SILENTLYCONTINUE` などの大文字バリアントは現 regex で見逃していた
   - 両 rule の pattern に Rust regex `(?i)` inline flag を追加して case-insensitive
     マッチに変更
   - test helper (ps_empty_catch_rule / ps_silent_error_rule) も同様に更新

2. Minor: docs/todo.md stale references (lines 68 / 250 / 264)
   - Bundle 1 の renumber (27 \u2192 25) で本文内の cross-reference が追従漏れ
   - line 68: `Tier 4 (順位 25/26)` \u2192 `24/25`
   - line 250: `Tier 5 (順位 26/26)` \u2192 `25/25`、`順位 25` \u2192 `順位 24`
   - line 264: `Tier 2 (順位 9/26)` \u2192 `7/25`、`順位 17 (ADR-032 PR-β)` \u2192 `順位 16`

実装 (TDD):
- 先に case-insensitive variant の 4 unit test を追加し、cargo test で FAIL を実証 (RED)
- (?i) flag 追加で GREEN \u2192 62 tests pass (旧 58 + 新 4)
- bad/good example も大文字混在ケースで影響なしを確認 (regex は (?i) 範囲)

順位 23 (todo.md 採番管理の簡素化 ADR 起案、PR #86 T3-3) で構造的解決予定。
本 fix は当面の対症療法として cross-ref を手作業で同期。

* fix(lint): detect multi-line empty catch blocks (file-level regex)

PR #91 の 2nd CodeRabbit review で指摘された Major finding を修正。

問題:
- run_custom_rules() が `for line in content.lines()` で行ごとに regex.find() を
  呼ぶ実装だったため、PowerShell 慣用形 `} catch {\n}` の複数行空ブロックが
  検出できなかった (no-empty-powershell-catch は error severity なのに false
  negative)。
- 既存パターン (console.log( / no-personal-paths / no-mutable-anchor 等) は
  すべて行内完結のため挙動変化なし。SilentlyContinue は \s+ で改行を跨ぎ得るが、
  PowerShell の backtick 行継続を含む正当な使用も検出対象として妥当。

修正:
- run_custom_rules() を file-level マッチに変更
  (`compiled.regex.find_iter(&content)` でファイル全体を走査)
- match の byte offset から改行カウントで line 番号を逆算
  (`content[..m.start()].bytes().filter(|b| *b == b'\n').count() + 1`)
- MAX_CUSTOM_VIOLATIONS の上限と既存テスト挙動はそのまま維持

実装 (TDD):
- ps_empty_catch_detects_multiline_block test を追加し RED 確認
  (既存実装で 0 件検出 → 1 件期待で FAIL)
- 修正後 GREEN \u2192 63 tests pass (旧 62 + 新 1)

* fix(lint): exclude external URLs from no-mutable-anchor (path `:` exclusion)

PR #91 の 3rd CodeRabbit review で指摘された Minor finding を修正。

問題:
- regex `\]\([^)#]*#[^\x00-\x7F)]+` は path 部に `:` を許容するため、
  `[link](https://example.com/#日本語)` のような外部 URL の fragment を
  GFM anchor と誤判定 (false positive)。
- 外部 URL の fragment は GFM anchor ではないため、warning rule の
  alert fatigue を招く。

修正:
- regex を `\]\([^)#:]*#[^\x00-\x7F)]+` に変更 (path 部から `:` を除外)。
  http(s):// を含む URL は path 部マッチで止まるため対象外になる。
- protocol-relative URL (`//example.com/...`) は `:` を含まないため除外
  できないが、Markdown 文書では稀なので許容。
- CodeRabbit 提案の negative lookahead は Rust regex 非対応なので、
  character class 否定 1 文字追加で同等効果を実現。

実装 (TDD):
- md_mutable_anchor_skips_external_url_with_fragment test を追加 → RED
  (`[spec](https://example.com/#日本語)` で 1 件検出 → 0 件期待で FAIL)
- pattern 修正後 GREEN \u2192 64 tests pass (旧 63 + 新 1)
aloekun added a commit that referenced this pull request May 29, 2026
…ndle CR-RL 採用 3 件 (#183)

* docs(todo): PR #182 post-merge-feedback Bundle CR-RL 採用 3 件 + 順位 165 補足追記

採用: PR #182 post-merge-feedback (2026-05-29 ユーザー承認):
- 順位 167 (T1-#1): check-ci-coderabbit の RATE_LIMIT_MARKER を新フォーマット対応に更新
- 順位 168 (T2-#1): CR rate-limit detection integration test の新旧 fixture
- 順位 169 (T3-#1): ADR-018 / ADR-034 に CR rate-limit format evolution 同期戦略 codify

3 件は Bundle CR-RL タグで同 PR land 推奨 (機械強制 + test 層 + 永続 ADR 層の 3 層補強)。

順位 165 補足追記:
- PR #182 T2-#2 採用候補 (pnpm-create-pr-body-guard hook test) は本 165 と scope 重複のため独立 entry 化せず本 entry に集約
- supplementary fact: PR #134 で pnpm-create-pr-body-guard hook 採用判定されたが未実装の state (= stale unfulfilled adoption、feedback-reports/134.md Tier 1 #1)
- 165 着手時に hook 実装済なら test 範囲を 2 層 (--body-file workaround verify + guard hook 動作 verify) に拡張

* docs(adr): 8 ADR の ephemeral todo 参照を permanent reference に置換 (A01 fix、Cross-File Reference Lifecycle 違反修正)

PR #182 Phase B dogfood で検出された finding WR-2026-05-29-A01 (Severity High、Category adr-alignment) の修正。
8 永続 ADR が docs/todo*.md の section / 順位 N / Phase A-F 等の ephemeral artifact を直接参照しており、
docs-governance.md § Retirement Workflow で todo entry が削除された際に silent dead pointer 化する
systemic documentation drift の構造修正。

修正方針 (analyzer 推奨 3 strategy):
1. ADR cross-references — 別 ADR に decision がある場合
2. PR # references — git log で origin が trackable な場合
3. Inlined constraints — detail が小さい場合

各 ADR の修正:
- ADR-022 line 197: parenthetical pointer 削除 (operational guideline は self-contained で完結)
- ADR-023 lines 54, 86: "docs/todo.md or PR description" → "PR description" (permanent artifact のみに集約)
- ADR-028 line 186: "docs/todo.md #7" → "PR #59 で land、PR #62 で global skill 移管"
- ADR-029 lines 191, 240, 266: task pointer 削除 + ADR-030 supersede note
  (本 ADR は ADR-030 partial supersede 対象、実装系譜は ADR-030 に集約)
- ADR-030 line 417: Phase B-F section pointer → 各 Phase の land 済 PR # (PR #75/77/80/154) を直接列挙、
  Phase E/F は priority table 参照 (specific 順位 番号は避ける)
- ADR-031 line 270: Phase A-F section pointer → PR #182 + priority table (順位 8 は trackable level の言及)
- ADR-033 line 111: grep procedure hardcoded list (todo.md/2/3) → glob (todo*.md)
  本 ADR land 時から todo4-9 が追加されており hardcode list は既に stale
- ADR-034: "todo-summary.md / todo4.md エントリ" section + "新セッションで最初に確認すべきこと"
  を全面再構成、4 component の land 状況を PR # primary table 化 (旧 順位 42 = PR #113 等)、
  新セッション checklist を ADR-018 + memory + grep ベースに置換

修正外 (operational reference として保持):
- ADR-031 lines 79, 84, 96, 121, 185, 189-191, 205, 207, 240, 242, 251, 302: workflow が
  todo.md に書き込む / セクション作成する behavior 記述 (pointer ではない operational description)
- ADR-033 lines 1, 11, 24, 93, 100, 130, 131: ADR 本体が todo.md 管理がテーマのため intrinsic
- ADR-034 lines 195-198 (Bundle b との関係 table): 順位 N と PR # / Bb-N が pair で書かれているため
  permanent reference (PR #) が常にあり、dead pointer リスクなし
aloekun added a commit that referenced this pull request Jun 24, 2026
…順位 222 採用 (#219)

* docs(todo): 順位 222 採用 (PR #218 post-merge-feedback #5)

PR #218 (docs PR、ファイルサイズチェックフロー改善計画 + 順位 220/221 採用)
の post-merge-feedback で承認された #5 を採用:

順位 222 (💎 Tier 3、Effort XS):
`~/.claude/CLAUDE.md` に「複数セッション跨ぎの計画文書作成時は AI が
先走らずユーザー確認後に方針報告し GO/NO-GO を得る」ルール追加

由来: PR #218 session 内で Plan file 作成完了報告後、AI がユーザー承認
なしに PR-W0 着手しようとして `[Request interrupted by user]` で停止
された実観測 (Severity Medium、Frequency Low 初観測、Effort XS、
Adoption Risk None)。memory `feedback_no_unauthorized_reorder` の補強
として「planning doc 作成のような大きな task 完了時は GO/NO-GO 確認待ち」
を明文化、派生プロジェクトへ `~/.claude/CLAUDE.md` 経由で自動波及。

採用しなかった項目:
- #1 (weekly audit を feedback entry にも明示): 計画書 PR-W0 で既に管理
- #3 (lib-subprocess stress test): 順位 220 と完全重複
- #4 (Agent template PMF entry): 計画書 Appendix A で既に capture、却下
- #2/#6/#7: 様子見継続

* feat(weekly-review): file_length scan を pre-LLM step として追加 (PR-W0)

ADR-031 weekly-review pipeline に deterministic Rust pre-step として
800 行超 file の scan を追加。LLM facet 不要、純機械測定。

順位 147 (file_length lint) は touch-trigger ratchet で「触られた file の
編集時のみ警告」設計のため、未触り state の violation を可視化できない。
本 step は毎週 1 回 master HEAD に対して 800 行超 file を全件列挙し、
aggregate-weekly facet の input に注入して watchlist として report 化する。

PR-3a (PR #217) で 7 件の 800 行超 file が判明した経緯から、Phase 1
(file split work、PR-W1 〜 W4) の進捗 dashboard としても機能する。
全 file ≤ 800 行に到達後も恒久的に監視継続。

由来: docs/file-length-enforcement-plan.md PR-W0 (PR #218 で land)、
severity = warning (block しない、健康診断目的)。
aloekun added a commit that referenced this pull request Aug 6, 2026
…DR-071) (#361)

* feat(autonomy-policy): 未マージ draft 数の背圧を判定コアの入力にする

WP-18 PR 1 (1/5)。ADR-052 原則 5 が自動実行可クラスの前提条件とする背圧を、
判定コア `lib-autonomy-policy` が入力として受け取れるようにする。

## 変更の要点

`Operation::backpressure_connected()` の `DraftPr => false` 固定を廃し、背圧の
**指標の要求**と**指標の実測値**を別の層へ分けた:

- `Operation::requires_draft_backpressure()` — 操作クラスが「未マージ draft 数」を
  要求するかだけを持つ静的分類。状態は持たない
- `GateInputs::open_draft_prs` / `max_open_draft_prs` — 実測値と閾値。どちらか一方でも
  `None` なら `backpressure-unavailable` で deny (fail-closed)

背圧の状態を enum 側にも持たせると `GateInputs` と二重管理になり判定経路が分岐するため、
状態の保持先は `GateInputs` 1 箇所に限定した (計画書 WP-18 PR 1 の明示要件)。

`FixPush` が draft 数を要求しないのは背圧が無いからではなく、その背圧が cli-pr-monitor の
有界 retry (`max_retries`) で、呼び出しごとに gate へ渡す状態を持たないため。この非対称を
doc コメントとテスト (`fix_push_is_unaffected_by_draft_backpressure_inputs`) の両方で固定した。

## 追加した deny 理由

`DenyReason::BackpressureSaturated { open, limit }` (code = `backpressure-saturated`)。
飽和判定は `>=`。閾値は「これ以上は積まない」上限であり、`limit = 0` は「draft を 1 件も
作らない」= 実質停止を意味する。

`describe_sources` の背圧表記は `structural` / `ok(N/M)` / `saturated(N/M)` / `unavailable`
の 4 状態で、実数を必ず併記する。run log 1 行で「数え損ねて止まった」と「積み過ぎて
止まった」を切り分けられるようにするため。

## テスト

判定コアのテストを 16 → 22 件へ。網羅走査テストは背圧 4 パターンを軸に加えて 54 → 216
組合せになり、許可される組合せ数も式で固定した (truthy 表記数 × (fix-push 4 + draft-pr 1))。
境界 (`open == limit` で止まる)、`limit = 0`、kill-switch が背圧より先に効くこと、
背圧入力の欠落 3 パターンをそれぞれ独立に pin している。

## 本コミットの範囲

呼び手 2 件 (`cli-autonomy-gate` / `cli-fix-push-gate`) は本コミットでは `None` を渡す。
`draft-pr` は従来どおり deny のままで、運用挙動は変わらない。config からの閾値読み取りは
2/5、実測 draft 数の受け口は 3/5 で接続する。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(autonomy-policy): 背圧閾値 max_open_draft_prs を config から 1 回の read で取り込む

WP-18 PR 1 (2/5)。背圧の閾値を `autonomy-config.toml` の `[autonomy]
max_open_draft_prs` に置き、kill-switch フラグと同じ信頼境界 (master ref の写し) と
同じ「欠損 → 停止」極性に乗せる。

## read を 1 回に集約した理由

`read_repo_config_enabled(path) -> Option<bool>` を `read_repo_config(path) -> RepoConfig`
へ置き換えた。キーごとに読み取り関数を生やすとファイルを 2 回読むことになり、2 回の read の
間に config が差し替わると「kill-switch は旧世代・閾値は新世代」という混成状態で判定しうる。
1 回の read から派生した値だけを使う。

## 半壊 config は全フィールドが停止側へ倒れる

toml の parse はファイル単位なので、`max_open_draft_prs` が型違い (文字列 / 負値 / 小数) だと
`enabled` も含めて全フィールドが `None` になる。これは意図した挙動で、config の一部が壊れた
状態を「kill-switch だけ有効」で運転させない (ADR-043 fail-closed)。テストで明示的に固定した。

閾値キー欠落時に既定値 (3 など) へ倒さないのも同じ理由。書き忘れが「勝手に 3 件まで作る」
という fail-open にならないよう、欠落は背圧未接続 = draft PR deny とする。

一方で未知キーは無視する (`unknown_keys_are_ignored`)。config に新しい設定を足したときに、
未更新のバイナリが parse 失敗で全停止するのは安全側に振りすぎるため。

## テスト

sources のテストを 6 → 11 件へ。閾値の正常読み取り (0 を含む)、キー欠落が既定値でないこと、
型違い 3 種が kill-switch フラグごと停止側へ倒すこと、未知キー無視を追加した。

## 本コミットの範囲

`cli-autonomy-gate` は閾値を `GateInputs` へ渡すようになったが、実測 draft 数の受け口
(`--open-draft-prs`) はまだ無いため `draft-pr` は `backpressure-unavailable` で deny のまま。
接続は 3/5 で行う。`cli-fix-push-gate` は `enabled` しか使わないため呼び出し形の追従のみ。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(autonomy-gate): --open-draft-prs で実測 draft 数を受け取り背圧を接続する

WP-18 PR 1 (3/5)。判定コア (1/5) と閾値 (2/5) に続き、背圧の残り 1 入力である
**実測件数**の受け口を CLI に開ける。これで `draft-pr` が構造的 deny を脱し、
ADR-052 原則 5 の契約を満たした状態でのみ許可されるようになる。

## 引数の扱い

`--open-draft-prs <count>` は省略可能。`fix-push` では判定に使わないためで、`draft-pr` で
省略した場合は `None` = 背圧未接続として deny に倒れる。**省略が許可へ倒れる経路は無い**。

値のパースは `u32` で、空文字 / 負値 / 小数 / 非数値 / 末尾空白は引数不正 (exit 2) として
弾く。呼び手の `gh api` が失敗したときの出力 (空文字など) を 0 件と読み違えて「draft が
1 件も無いので作ってよい」に倒れるのが最悪の failure mode なので、ここは黙って `None` へ
潰さず loud に落とす。

`--config` / `--operation` の必須性は従来どおり。引数ループは値取得を各 arm へ寄せ、
未知フラグの判定を値の有無より先に行う既存の順序を保った。

## テスト

引数解析のテストを 4 → 7 件へ。省略時が `None` であること、`0` が正しく `Some(0)` として
読まれること (「0 件」と「数えられなかった」を型で区別する契約)、不正値 5 種が引数不正で
あることを固定した。

## 本コミットの範囲

exe 単体では背圧が接続された。実測値を渡す呼び手 (夜間 workflow の `gh api` step) は
**本 PR には含まれず PR 3 で追加する** (ADR-069 chain 宣言 → 計画書 § WP-18 と ADR-071 を
5/5 で更新)。実 exe による drill は 4/5。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(adr-071): 未マージ draft PR 数による背圧を起票し drill 12 シナリオを記録

WP-18 PR 1 (4/5)。1/5〜3/5 で実装した背圧の設計判断・試験運用条件・実測を永続化する。

## 記録した決定 5 件

1. 指標は「未マージ draft PR 数 (claude/ prefix)」。run 回数や経過時間のような代理指標
   ではなく、止めたい事象 (人間が捌けない量の未処理成果物) を直接数える
2. 背圧の状態は GateInputs だけが持つ。enum 側にも状態を置くと判定経路が二股に分かれ、
   「テストは通るが実運用では別の枝を通る」drift を生む
3. 閾値は autonomy-config.toml の max_open_draft_prs、判定は >=。0 は draft-pr クラス
   だけの停止、キー欠落は既定値ではなく deny
4. 数えるのは呼び手 (workflow step の gh api)、判断するのは gate。exe が gh に依存すると
   ローカル drill が GitHub 到達性に依存し、安全装置の再現可能な検証ができなくなる
5. 数えられなかったことは 0 件ではない。不正値は exit 2 で loud に落とす

決定 4 の「呼び手が数を偽れる」問題は、schedule イベントが default branch の workflow 定義を
使うという GitHub の仕様で担保される (ADR-066 の config master ref 契約と同じ信頼境界)。

## 外部 SaaS の課金・上限事実を移管 (計画書 § 2 の退役条件 2)

2026-08-06 に最新値を再確認して永続化した。

- public リポジトリ + standard runner の Actions 実行は無料・分数無制限 (GitHub 公式 docs で
  原文確認)。GitHub Free の 2,000 分/月は private のみ
- claude-code-action@v1 は claude_code_oauth_token で Max 枠を消費。OAuth token は個人
  サブスクに紐づき、自動化の消費が対話作業のレート枠を圧迫しうる

要約: Actions の実行時間は無料だが Max 枠は有限。背圧の経済的根拠はここにある。

## 検証記録

release build の実 exe で drill 12 シナリオを実施し全て設計どおりを確認した。#6/#7 の対で
>= 境界、#8 で limit=0 の停止、#9 で fix push が draft 数から独立していること、#10 で
半壊 config が enabled ごと停止することを実バイナリ上で確認している。

unit test は判定コア 22 / sources 11 / 引数解析 7 件。網羅走査 1 件が 216 組合せを走査する。

## bounded lifetime

decision trigger (b)「閾値到達で実際に次の run が止まること」は本 ADR 固有の観測点で、
exe 単体 drill では作れない状態 (夜間ループが実際に 3 件積む必要がある)。期限は 2026-11-06。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(harness-plan): WP-18 PR 1 の完了を記帳し PR 3 への chain 宣言と SaaS 事実の移管を行う

WP-18 PR 1 (5/5)。計画書側の 3 種類の更新。

## 1. PR 1 完了の記帳

- WP-18 節の見出しと全体像表を「着手可」→「着手中(PR 1 実装済み)」へ
- PR 構成 1 に実装時の設計判断を確定記録: 閾値判定の層は (a) gate 内を採用。
  backpressure_connected() は廃し requires_draft_backpressure()(指標の要求のみ)と
  GateInputs の 2 フィールド(状態)へ分離した
- 着手前決定 2 の記述を過去形へ(backpressure_connected() は既に存在しない名前のため、
  現在形のまま残すと ADR-069 決定 1 の「名前一致」要件に反する)
- WP-19 ステップ 2 を「前倒し済み」→「land 済み」へ

## 2. PR chain 宣言(ADR-069 決定 1)

PR 1 が導入した 3 点(--open-draft-prs フラグ / max_open_draft_prs キー / DraftPr の許可
経路)は PR 3 まで呼び手を持たない。抽出↔呼び手のペアリングを表で具体名指定した。

順序を逆にできない根拠も明記した — ADR-052 原則 5 が背圧の接続を draft-pr クラス有効化の
前提条件としているため、背圧が先に land する必要がある(WP-17 の kill-switch 先行と同構造)。

なお PR 1 単体では draft-pr は deny のままで運用挙動は変わらない。

## 3. SaaS 課金・上限事実の移管(退役条件 2 / 順位 117 の 3 ステップ原則)

permanent 側(ADR-071 § 外部 SaaS の課金・上限事実)を先に作成 → 本ファイルの § 2 から
GitHub Actions 課金 2 点と claude-code-action の OAuth 認証を削除し ADR-071 への参照へ
置き換えた。cloud routines の事実群は WP-19 / ADR-070 の担当範囲のため本節に残している。
runner 単価の相対比も private 化時のみ関係するため移管対象外とした。

pnpm lint:docs / markdownlint ともに green。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: CodeRabbit 指摘 2 件に対応 (主張の適用範囲を限定 / 移管済み方針の更新)

PR #361 への CodeRabbit レビュー (Minor 2 件) の反映。どちらも「書いた内容が実態より
広い/古い」型の指摘で、妥当。

## 1. 「draft-pr は deny のまま」の適用範囲を限定 (2 箇所)

指摘は「**両文書**が PR 3 まで draft-pr に許可経路が無いように読める」というもの。実際には
ADR-071 § 検証記録の drill #6 が示すとおり、--open-draft-prs と有効な config を渡せば exe は
allow になる。

正確には**リポジトリ内の自動化経路に --open-draft-prs を渡す呼び手が 1 つも無いため** deny に
なる、が正しい。「運用挙動は変わらない」の根拠を exe の挙動ではなく呼び手の不在へ置き直した。
根拠を取り違えたまま PR 3 で呼び手が入ると、主張だけが stale に残る。

修正箇所は 2 つ:

- docs/adr/adr-071-*.md § 残課題
- docs/harness-improvement-plan.md § WP-18 の PR chain 宣言

計画書側から ADR-071 § 残課題への参照も付け、同じ限定が 1 箇所に集約されるようにした。

## 2. 計画書 § 2 preamble: 移管済みの事実と矛盾する旧方針を更新

旧文は「現時点では ADR 化せず本ファイルに保持する」と書いていたが、同じ blockquote の
次の行で「ADR-071 へ移管済み」と述べており矛盾していた。

方針文を「担当 WP の ADR 起票時に移管し本節から削除する」という恒常ルールへ書き換え、
移管済み / 未移管を別項目に分けた。未移管の内訳 (cloud routines の daily cap / webhook
上限 / GitHub App 必須 / 緑ステータスの意味) も具体名で列挙し、次の担当 WP が何を移管
すべきか読み取れるようにした。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
aloekun added a commit that referenced this pull request Aug 8, 2026
* docs(todo): WP-18 で検出した問題を 4 エントリへ登録 (順位 374-377)

WP-18 (夜間 todo 消化ループ、#361 / #362 / #363) の実装中に pre-push review・
CodeRabbit・ユーザー指摘で検出した問題 9 件のうち、todo 登録が要る 8 件を **実装時の
PR 粒度**で 4 エントリへまとめる。切り分けは 2026-08-06 にユーザー確認済み。

## 評価時の #1 を検証し、todo 登録が不要になった

#1 は「Bash prefix 許可の悪用可能性検証と全経路への横展開」として登録予定だった。
ユーザー指示により登録前に検証したところ、**前提が誤りだった**。

#363 の security review は「`Bash(cargo test:*)` は前方一致でシェルを解釈しないため
`cargo test` に任意コマンドを連結すると通過する」と主張していた。公式ドキュメントは
これを明確に否定している:

  Claude Code is aware of shell operators, so a rule like `Bash(safe-cmd *)` won't give
  it permission to run the command `safe-cmd && other-cmd`. The recognized command
  separators are `&&`, `||`, `;`, `|`, `|&`, `&`, and newlines. A rule must match each
  subcommand independently.

`--allowedTools` も同じルール体系に属する (managed settings の deny を --allowedTools で
上書きできない、と明記されている)。

結果:

- `pr-monitor.yml` の Phase A 分析 agent に**当該の穴は無く、対処不要**。production の
  live な穴という当初の見立ては誤りだった
- 残作業は `ADR-072` 決定 5 の根拠記述の訂正のみで、#363 が open のうちに同 PR へ直接
  反映する。よって todo エントリを立てない

検証結果と経緯はセクション冒頭の対応表に残した。

## この一件自体を教訓として取り込んだ

「レビュー指摘への対応時チェックリスト」エントリに 4 項目目を追加した — **指摘が技術的
前提 (ツールの挙動・仕様) に依拠しているなら、対処より先にその前提を検証する**。とくに
設計変更や他経路への横展開を伴う場合。

今回は未検証の前提のまま (a) agent から Bash を落とす設計変更を行い、(b) それを ADR の
決定として記録し、(c) さらに「同じ形が production にもある」と横展開の警告まで出していた。
一次情報に当たれば 1 回の WebFetch で否定できた。

## 内訳

- 順位 374: WP-18 夜間ループの実走スモーク実施 (Tier 1、評価時の #2/#3)
- 順位 375: レビュー指摘への対応時チェックリスト (Tier 2、評価時の #4/#5/#6 + 今回の #1)
- 順位 376: push-runner の bookmark 自動前進がスタック境界を壊す (Tier 2、評価時の #7)
- 順位 377: 夜間ループの防御を検知から防止へ格上げする判断 (Tier 3、評価時の #8/#9)

## まとめ方の方針

リポジトリの既存バッチ登録 (#350#357 の 24 件を 8 エントリへ) と同じく実装時の PR 粒度で
まとめた。評価時の番号との対応はセクション冒頭に表で残してある。

順位 374 (スモーク) の観測項目は `ADR-072` の実走スモーク節に表があるため、todo 側は
スケジューリングの掛かりだけを持ちチェックリストを複製しない。同じ表を 2 箇所で管理すると
必ず drift する (#362 の post-merge feedback が指摘した single source-of-truth 問題と同型)。

ADR-033 (絶対番号は table のみに保持) に従い、エントリ本文には順位番号を書いていない。
todo20.md は 50KB 閾値内。pnpm lint:docs / markdownlint ともに green。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(todo): #363 post-merge feedback の採用 6 件を登録 (順位 378-383)

WP-18 最終 PR (#363、ADR-072) のマージ後 feedback が Tier 1 に 4 件・Tier 2 に 2 件を
採用候補として挙げた。ユーザー承認 (2026-08-07) を得て登録する。

## 6 件は 1 本の根から出ている

台帳 (docs/claude-code-web-tasks.md) の 内容 / 対象ファイル / 注意 は自由記述のまま
無人 agent のプロンプトへ流入する。agent は $GITHUB_WORKSPACE 全体に書き込め、その
出力は draft PR 本文という公開面に出る。ADR-054 の信頼境界そのもの。

- 378 (XS) 台帳を ADR-035 の docs-only 除外パス表へ追加 — 他 3 件の前提。台帳だけを
  変える PR が緩い評価経路に乗ると、対策そのものを迂回する台帳 PR が通りうる
- 379 (S)  tool scope を work/** へ限定 — ADR-072 決定 7 の改ざん検知が必要になって
  いる根本原因。実装後も検知層は残す (防御を 1 枚に減らす変更ではない)
- 380 (M)  台帳フィールドを untrusted data として明示 framing
- 381 (S)  台帳由来 SUMMARY の draft PR 本文出力に screening
- 382 (M)  injection payload の regression test (380 に依存)
- 383 (S)  is_separator_row のパイプ検証欠落

## 期限を「定常運用開始前」に固定する

実効リスクは現時点では低い — 悪意ある台帳行を master へマージするのはユーザー自身で、
単独運用では外部からの注入経路が無い。ただし夜間ループが定常運用に入り draft PR の
流量が増えると前提が変わるため、無期限の Tier 積みにしない。

順位 374 (実走スモーク) は dry_run で PR を作らないため本件の実害が無く、待たせない。

## 383 は実コードで確認済み

is_table_row は行頭 | を要求するが、is_separator_row は split_cells の結果しか見ない。
split_cells("---") は ["---"] を返し全セルが '-' のみなので真になる。markdown の
水平線がセパレータ行として通る (todo ファイル自身が --- を使っている)。
ADR-072 決定 2 の fail-closed 設計の coverage hole。

## 併せて

順位 374 のスモーク観測項目数を 4 → 8 へ修正した (ADR-072 側の実測と不一致だった)。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(harness-plan): WP-18 を 3 PR マージ済へ更新し残作業 2 系統を明示する

#363 のマージ (2026-08-07) で WP-18 の実装 3 本がすべて land した。

## 「実装完了 = WP 完了」ではないことを表で残す

コードは全部 master にあるが、**夜間ループはまだ 1 度も走っていない**。この状態を
「実装済」の一語で片付けると、次のセッションが受け入れ基準を満たしたものと誤読する。
残作業を 2 系統に分けて表にした:

1. 実走スモーク (順位 374) — 受け入れ基準の中核
2. prompt injection 対策 4 件 (順位 378-381) — 定常運用開始前に必須

## スモークの前提が充足したことを記録

受け入れ基準の表は「(a) workflow が master にある (b) 台帳に無人可マークがある」を
未充足として書いていたが、**両方ともマージで解消した**。残る操作は GitHub UI 側の
AUTONOMY_ENABLED 設定のみなので、その 1 点へ書き換えた。

## 依存関係を明示する

378-381 は 1 本の根 (台帳の自由記述が無検証で agent プロンプトへ流入) から出ている。
一方スモークは dry_run で PR を作らないため本件の実害が無い。したがって
**スモークは 378-381 を待たずに着手してよい**と明記した。次セッションが順序で
迷わないようにするため。

## 未 push の改善 3 点の所在を残す

#363 の最終 push が security REJECT で止まったため、改ざん検知の red 化 / 決定 10 の
色分け表 / 決定 6 の列挙基準が master に載っていない。ローカル bookmark
wp18/unpushed-improvements (fc22403c) に保持していることを記録した。いずれも
可観測性と文書の改善で、fail-closed 自体は master 版でも成立している。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(todo): 外部設定 (GitHub App / variables / secrets) の実体記録を登録 (順位 384)

新セッションでの指摘 (2026-08-07): workflow は vars.NIGHTLY_APP_ID /
secrets.NIGHTLY_APP_PRIVATE_KEY を参照するが、App の作成・インストール・登録を
記録した文書がリポジトリ内に無い。

## 欠けているのは設計根拠ではなく運用実体

ADR-072 決定 8 は「なぜ App token か」「なぜ PAT ではないか (オーナー PAT は
Repository admin として ADR-067 の ruleset backstop を素通りする)」「どの権限を
付けるか (Workflows は付けない)」「なぜ publish 直前に発行するか (token 寿命
1 時間)」を厚く残している。

記録が無いのは以下:

- App を実際に作成した事実・日付・名称・インストール範囲
- NIGHTLY_APP_ID = variable / NIGHTLY_APP_PRIVATE_KEY = secret という登録先の別
- 既存の Claude GitHub App との区別 (あちらは Workflows を含む広い権限を持つ別物)
- 再構築手順 (鍵ローテーション・派生プロジェクト展開)

NIGHTLY_APP の文字列はリポジトリ全体で workflow の 2 行と ADR 残課題の 1 行にしか
現れない。

## これは ADR-051 違反

ADR-051 (クロスシステム設定 coupling) は内部設定と外部 SaaS 設定が論理結合する場合に
(1) 両設定ファイルへの相互参照コメント (2) 期待値の組み合わせ表の ADR 必須記載
(3) 変更は両側を同一 PR、の 3 点を規律として定めている。workflow ↔ GitHub App +
repository variables/secrets はこの型で、3 点とも未実施。

前例として ADR-067 段 0 は repository ruleset を ruleset 名つきで「設定済み」と
記録している。ADR-072 は同じ扱いをしていない。同型の欠落が AUTONOMY_ENABLED にも
あり (ADR-066 は「Actions variable を使う」とは書くが現状値を記録していない)、
本エントリで一緒に扱う。

## 順位 374 と同時実施にする理由

スモークでは AUTONOMY_ENABLED の設定と App token の実動確認のため GitHub UI を
触るので、その過程で実値がすべて揃う。先行して記録しようとすると値が確定せず
二度手間になる。

## 教訓を残す

App の作成手順・Expire user authorization tokens の扱い・既存 App との違いは
2026-08-07 のセッションでユーザーへ提示したが、リポジトリへ残さなかった。会話は
次のセッションに残らないが workflow は残る。参照だけが残って由来が消える状態を
作った。順位 375 と同じクラスの失敗としてエントリ本文に記録した。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(review): CodeRabbit Major 4 件を妥当性判定のうえ 3 件へ対応する (#364)

自動 fix 経路 (f698d19) が 1 件 (#4 台帳への非記録ルール追加) を対応済みで、
本コミットはその内容を含んだうえで残りを手で対応した結果である。同一ファイルの
近接行のため path 単位で分離できず 1 コミットに畳み込まれている。

## 妥当性の判定

severity ラベルではなく、プロジェクトの設計方針に照らして 1 件ずつ判定した。

- #1 adr-072:335 (秘密値を ADR に記録しない) — **妥当**。「実走スモークで実値を
  確認し ADR へ追記する」は秘密鍵本文まで書くと読める。ADR-051 が記録を課すのは
  結合の存在と期待値の組み合わせであって秘密の実値ではない。設定メタデータに
  限定し、鍵本文と token は ADR にも git 履歴にも残さないことを明記した
- #2 harness-improvement-plan:223 (受け入れ基準が成功経路だけ) — **妥当**。本
  プロジェクトは背圧 12 シナリオ・kill-switch 8 シナリオと停止側を drill で
  固めてきたが、夜間ループの停止側は実走未観測。WP-17 の残課題 (明示的 false と
  config 側 deny が実走未観測) と同じ穴。AUTONOMY_ENABLED の 3 状態を受け入れ
  基準へ追加した。指摘本文が名指しした 2 箇所 (計画書 L223 / todo20 L293-304) の
  両方に反映している
- #3 todo20:480 (prompt injection の回帰 fixture) — **妥当**。順位 382 の payload
  例 "; echo PWNED; #" は shell injection であって prompt injection ではない。
  台帳テキストが流れ込む先は shell ではなく LLM プロンプトなので、テストが目的と
  噛み合っていなかった。自然言語 adversarial payload (本命) と shell/パース形式
  payload (堅牢性) の 2 系統へ分離した

## 自動 fix の実測確認

f698d19 は 1 ファイル 2 行追加のみで範囲外の編集ゼロ。内容も妥当だったため
そのまま採用した (ADR-068 の後退検知の趣旨に沿って diff を実測で確認済み)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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