{
  "$comment": [
    "権限表 — 誰が何をどこまで決めてよいかの単一の正。",
    "",
    "【なぜファイルにするか】外部レビュー（2026-08-22）が Tier 1 の必須条件として",
    "『広告・契約・支払い・公開に関する権限表』を挙げた。実態としては既にそう運用",
    "されているが、**明文化されていないものは、次に判断する人（や次のセッション）に",
    "とって存在しない**。growth/README.md が戒めている『散文は手を挙げない』と同じ。",
    "",
    "【機械が守れる部分だけ機械に守らせる】scripts/check-authority.mjs が見るのは3つ:",
    "  1. 不可逆な領域（reversible: false）は必ず requires_approval: true であること",
    "  2. active な領域は evidence（そう運用されている根拠のファイル）を持つこと",
    "  3. 金額を伴う領域は threshold を持つこと（未設定なら未設定と明示されていること）",
    "残り——実際に人が承認したか——は機械では見られない。そこは正直に書く。",
    "",
    "【status の意味】",
    "  active          … その運用が現に動いている",
    "  suspended       … 動いていた／止めた（理由を gate に書く）",
    "  not_implemented … そもそも作っていない（『やらない』ではなく『まだ無い』）",
    "  policy_only     … 方針だけあり、手順・手段が未整備",
    "",
    "【AIに与えていない権限が実体を持っている例】アプリのリリース連鎖は自動化されて",
    "いるが、それを起動する actions: write をAIワークフローに与えていない。これは",
    "この表の中で唯一、**技術的に強制されている境界**である。他は人間のルール。"
  ],
  "actors": {
    "ai_autonomous": "AIが単独で実行してよい。ゲート（CI・上限・品質基準）が通ったときだけ通る",
    "ai_proposes": "AIは提案・下書きまで。適用は人間の承認後",
    "human_only": "AIは実行しない。提案もしない領域はその旨を human_only に書く"
  },
  "generated_note": "この表は手で維持する。CIが見るのは形式の整合だけで、内容の正しさは人が持つ。",
  "domains": [
    {
      "domain": "サイトコンテンツの新設・更新",
      "reversible": true,
      "ai_may": [
        "レーン選定",
        "実装",
        "内部リンク配線",
        "OG/QR生成",
        "PR作成"
      ],
      "requires_approval": false,
      "human_only": [],
      "gate": "SEO Validation 13チェックに合格した**そのSHAだけ**をauto-mergeがマージする。落ちればマージされない",
      "evidence": [
        ".github/workflows/seo-check.yml",
        ".github/workflows/auto-merge.yml"
      ],
      "status": "active",
      "note": "mainへのマージ＝本番公開。出荷を保留したいときはdraft PRにする（auto-mergeはdraftを対象外にしている）"
    },
    {
      "domain": "サイト構造の変更（URL・リダイレクト・実験中ページ）",
      "reversible": false,
      "ai_may": [
        "提案",
        "実装（実験対象外のページのみ）"
      ],
      "requires_approval": true,
      "human_only": [
        "実験中ページのタイトル/説明/主要コンテンツの変更"
      ],
      "gate": "check-url-normalization / check-internal-redirects / check-experiments。running の実験対象ページはRunbook §0原則5で変更禁止",
      "evidence": [
        "scripts/check-url-normalization.mjs",
        "growth/experiments/experiments.json"
      ],
      "status": "active"
    },
    {
      "domain": "アプリのビルド・TestFlight内部配信",
      "reversible": true,
      "ai_may": [],
      "requires_approval": false,
      "human_only": [
        "タグ v* の作成"
      ],
      "gate": "Xcode Cloud が archive → attach-testflight-testers.yml が ASC API で内部グループへ自動アタッチ",
      "evidence": [
        "simplememo-ios/docs/release-automation.md"
      ],
      "status": "active",
      "note": "AIワークフローに actions: write を与えていないため、AIはこの連鎖を起動できない（claude.yml 冒頭に理由あり）"
    },
    {
      "domain": "macOSランナーの起動（GitHub Actions 分数の消費）",
      "reversible": false,
      "ai_may": [
        "残枠と1回あたりの実費の提示",
        "人間が名指しで指示したときの dispatch 代行"
      ],
      "requires_approval": true,
      "human_only": [
        "回すという判断そのもの",
        "confirm 合言葉の入力"
      ],
      "gate": "qa-ios.yml は自動トリガを持たず、confirm 入力が required。値の照合は ubuntu の gate ジョブが持ち、macOSの2ジョブは needs: gate。入力なしの dispatch は GitHub が422で弾く",
      "evidence": [
        "../simplememo-ios/.github/workflows/qa-ios.yml",
        "../simplememo-ios/CLAUDE.md"
      ],
      "status": "active",
      "threshold": {
        "monthly_included_minutes": 2000,
        "macos_multiplier": 10,
        "per_run_equivalent_minutes": 130,
        "set_by": "github_plan",
        "overage_policy": "bill_rather_than_stop",
        "overage_policy_set_by": "owner 2026-08-25",
        "observed_2026_08_25": {
          "gross_usd": 23.23,
          "included_discount_usd": 23.15,
          "net_usd": 0.08,
          "by_repo_gross_usd": {
            "simplememo": 12.12,
            "simplememo-ios": 10.33,
            "simplememo-api": 0.77
          },
          "payment_method": "有効なものが登録されていることを確認（内容はここに書かない。このリポジトリは public）",
          "note": "**gross の最大は public の simplememo（$12.12・全額が discount 側に載る）。付帯分を実際に食っているのは simplememo-ios（$10.33）** で、simplememo-api は $0.77。純額が $0.08 立っていること自体が、付帯分を超えた分が課金されて通っている証拠になる（$0 budget なら止まって $0.00 のまま）。**未解決**: この金額と、8/25 の警告メールが言う『1,800/2,000分』は正確には突き合わない（Linux $0.008/分 換算だと private 側は約1,390分）。どちらが正でも純額が $0.08 である事実は動かないので、出どころは未解明のまま残す"
        },
        "note": "2,000分/月は GitHub Free（simplememofast は個人アカウント）の付帯分で、こちらが決めた値ではない。130分は qa-ios.yml ヘッダの実測13分×10倍単価（watch ON なら +160分）。**超過時にどちらへ倒すかはオーナーが決めた（2026-08-25）: 止まるより課金されるほう。** $0 budget は枯れた瞬間に release / release-command と Flag Ops まで止めるので、そちらのほうが高くつく。金額側は小さい —— 超過分は Linux 約$0.008/分（200分で約$1.6）・macOS 約$0.08/分（7/31 の実績で$10）。**budget の設定値そのものは依然としてAPIから読めない。** 課金画面を人が見るしかなく、CIで検査する手段は無い（observed_* は人が読んだ値の写しであって、機械が確かめた値ではない）"
      },
      "note": "**分数は戻らない**（リセットは翌月1日）ので不可逆に分類した。焼けるのは金額ではなく出荷で、枯れると release / release-command が止まり TestFlight配信もApp Review申請もできなくなる。2026-07-31 に1日で $10 を使い切った実績があり、そのときの経路は『AIが足した push トリガ』だった。表に無い支出は、次に判断するセッションからは存在しない"
    },
    {
      "domain": "App Review への提出",
      "reversible": false,
      "ai_may": [
        "提出の提案",
        "**ゲートを通った提出の実行**（CI緑・実機確認の記録あり・TestFlightで24時間以上・1日1回）"
      ],
      "requires_approval": false,
      "human_only": [
        "**実機での事前確認そのもの**（機械には代われない。門はその記録を要求する）",
        "`policy.enabled` を立てる操作そのもの",
        "kill_switch を倒す操作"
      ],
      "gate": "evaluateSubmission() が唯一の関門。CI が同一コミットで success、リリースノートが ja-JP/en-US とも揃い、TestFlight が VALID で24時間以上寝ていて、未解決のブロッカーが0で、**実機確認の記録が同一コミットに対して存在し**、審査が進行中でなく（**版の状態と、アプリ単位の提出枠の両方**）、本日まだ1件も出していないときだけ通る。**どれか1つでも材料が無ければ hold**",
      "evidence": [
        "scripts/check-release-gate.mjs",
        "data/release-gate.json",
        "simplememo-ios/.github/workflows/submit-review.yml"
      ],
      "status": "active",
      "note": "技術的な強制ではなく人間のルール。だからこそ actions: write を渡していない\n\n**[2026-08-28] オーナーが名指しで渡した。**旧 note は「技術的な強制ではなく人間のルール。だからこそ actions: write を渡していない」だった。\n\n**Hard Rule（実機で確認してから提出する）は外していない。**機械には代われないので、**門がその記録を要求する形に変えた** —— `device_verified_by` / `device_verified_at` / `device_verified_sha` が無ければ hold。sha を要求するのは、**見たものと出すものを一致させる**ため（別のビルドを見て出せてしまうと、記録があること自体が意味を失う）。\n\n**enabled は false で置いてある。**実行側（ASCへの提出の呼び出し・タグ作成の権限）もまだ無い。",
      "machine_gate": {
        "checker": "scripts/check-release-gate.mjs",
        "function": "evaluateSubmission",
        "kill_switch_path": "data/release-gate.json#policy.kill_switch",
        "daily_cap": 1,
        "holds_when_unknown": true,
        "$holds_when_unknown": "**CI・リリースノート・TestFlightの状態と経過・ブロッカー件数・実機確認の記録・審査の進行状況（**版の状態と提出枠の両方**）のどれが欠けても hold。**とくに実機確認は『たぶん誰か見ただろう』で通さない"
      },
      "$gate_2026_08_31": "**提出枠（reviewSubmissions）を条件に足した。**それまで「審査が進行中か」は build.in_review、すなわち**版の状態しか見ていなかった。**Apple の提出は版ではなくアプリ単位の reviewSubmission で、App版・カスタムプロダクトページ・Appイベント・実験を1件に束ね、**同時に進行できるのは1件だけ。**5.7.8 で実際に踏んだ —— 版一覧は「審査中の版は無い」と言うのに deliver は `A review submission is already in progress` で落ちた（simplememo-ios run 31597781663）。**版だけ見ている門は、この形を通す。**材料は simplememo-ios/data/appstore/release-materials.json の review.submission_open。**読めなければ hold**（「空いている」に倒さない）"
    },
    {
      "domain": "App Store への公開（審査通過後）",
      "reversible": false,
      "ai_may": [
        "審査を通ったビルドの公開の提案",
        "**ゲートを通った公開の実行**（段階リリース限定・1日1回・クラッシュ率とkillの確認つき）"
      ],
      "requires_approval": false,
      "human_only": [
        "段階リリースによらない一括公開（全員へ一度に出す判断）",
        "`policy.enabled` を立てる操作そのもの",
        "kill_switch を倒す操作"
      ],
      "gate": "evaluateRelease() が唯一の関門。審査が PENDING_DEVELOPER_RELEASE で、段階リリースが有効で、承認から6時間以上経っていて、クラッシュ率が母数100以上で判定でき悪化1.0pt以内で、直近7日にカナリアの kill が無く、本日まだ1件も出していないときだけ通る。**どれか1つでも材料が無ければ hold**",
      "evidence": [
        "scripts/check-release-gate.mjs",
        "data/release-gate.json",
        "simplememo-ios/fastlane/Fastfile"
      ],
      "status": "active",
      "note": "\n\n**[2026-08-28] オーナーが名指しで渡した。**それまでここは human_only で、gate に「fastlane の automatic_release がハードコードで false。**恒久的に手動**」と書いてあった。**渡っただけでは外れない** —— 権限表は不可逆な領域の承認を外すのに machine_gate を要求する（GATE_REQUIRED）ので、宣言ではなく実装で外した（`scripts/check-release-gate.mjs`）。\n\n非対称は消していない —— **止める側（取り下げ・段階リリースの停止）は軽く、出す側は重い。**段階リリースは門の側で**必須**にしてある（`require_phased_release`）。一度に全員へ出す設定は validate が落とす。\n\n**enabled は false で置いてある。**先例2つ（段階公開の門・レビュー返信の門）と同じで、実装した日には立てない。ここは影響がその2つより大きいので同じかそれ以上に慎重にする。**そして実行側（ASCへの提出・公開の呼び出し）がまだ無い** —— 門だけでは何も動かない。",
      "machine_gate": {
        "checker": "scripts/check-release-gate.mjs",
        "function": "evaluateRelease",
        "kill_switch_path": "data/release-gate.json#policy.kill_switch",
        "daily_cap": 1,
        "holds_when_unknown": true,
        "$holds_when_unknown": "**審査状態・段階リリースの設定・クラッシュ率・その母数・カナリアの状態のどれが欠けても hold。**とくに『母数が足りない』は hold であって『異常なし』ではない"
      }
    },
    {
      "domain": "価格・プラン・無料枠の変更",
      "reversible": false,
      "ai_may": [],
      "requires_approval": true,
      "human_only": [
        "すべて"
      ],
      "gate": "自動化していない。data/site-constants.json の値変更はCIが表示との整合だけ見る",
      "evidence": [
        "data/site-constants.json",
        "scripts/sync_constants.js"
      ],
      "status": "active",
      "threshold": {
        "set_by": "unset",
        "note": "変更幅の上限も承認フローも未設計。現行値は月額500円/年額5,000円/無料枠1日3通で data/site-constants.json が正。**AIは値を提案もしない**（課金は不可逆で、既存契約者への影響が読めないため）。設計するなら autopilot-maturity-backlog.md ⑨ から"
      }
    },
    {
      "domain": "AI実費（開発・運用のトークン費）",
      "reversible": true,
      "ai_may": [
        "上限内での消費"
      ],
      "requires_approval": false,
      "human_only": [
        "monthly_usd_cap の決定"
      ],
      "gate": "当月実績が上限に達すると予算ゲートが主系runを止める（--check の非ゼロ終了）",
      "evidence": [
        "data/autopilot-cost.json",
        "scripts/autopilot-budget.mjs"
      ],
      "status": "active",
      "threshold": {
        "monthly_usd_cap": 40,
        "set_by": "placeholder",
        "note": "暫定値。実測1点からの粗い外挿で、オーナー未確認。**副系CCRの実費は観測手段が無く、この上限では止められない**"
      }
    },
    {
      "domain": "広告出稿・広告予算の変更",
      "reversible": false,
      "ai_may": [],
      "requires_approval": true,
      "human_only": [
        "すべて"
      ],
      "gate": "未実装。資格情報も無い",
      "evidence": [
        "simplememo-ios/docs/reports/APPLE_ADS_AUTOMATION_2026-08-17.md"
      ],
      "status": "not_implemented",
      "threshold": {
        "daily_cap_jpy": null,
        "set_by": "unset",
        "note": "レポート §1 は上限¥4,000/日を想定しているが未設定。実装時は Tier 0（無条件の上限死守）から作る"
      }
    },
    {
      "domain": "契約・支払い・送金",
      "reversible": false,
      "ai_may": [],
      "requires_approval": true,
      "human_only": [
        "すべて"
      ],
      "gate": "自動化していない。証跡も無い",
      "evidence": [],
      "status": "not_implemented",
      "threshold": {
        "note": "支出上限と重要支出の二者承認は未設計。autopilot-maturity-backlog.md ⑦"
      }
    },
    {
      "domain": "プレスリリースの配信",
      "reversible": false,
      "ai_may": [
        "原稿作成",
        "D-SCORE採点の記録",
        "素材の依頼文作成"
      ],
      "requires_approval": true,
      "human_only": [
        "PR TIMES管理画面からの配信操作",
        "配信可否の判断"
      ],
      "gate": "D-SCORE >= 60 かつ G1〜G4 全通過。1つでも落ちたら配信しない。算数とゲートの矛盾はCIが落とす",
      "evidence": [
        "growth/scripts/d-score.mjs",
        "growth/experiments/experiments.json"
      ],
      "status": "active",
      "note": "**採点そのものは人が根拠つきで置く。**自動採点にすると点を取るための見出しを機械が書き始め、G2に自分から違反する"
    },
    {
      "domain": "SNS投稿（X・TikTok）",
      "reversible": true,
      "ai_may": [],
      "requires_approval": false,
      "human_only": [
        "再開の判断"
      ],
      "gate": "scheduled自動投稿は2026-08-11に運用停止。X英語はアカウントBAN1回目、TikTokは品質未達、scheduled経路は Cloudflare Access の認証で8/7から故障中",
      "evidence": [
        "README.md",
        ".github/workflows/x-post-scheduled.yml"
      ],
      "status": "suspended"
    },
    {
      "domain": "ユーザーデータの削除（アプリ内の自己削除）",
      "reversible": false,
      "ai_may": [
        "削除経路の実装と保守（data-retention.json を正として、カバレッジ検査に従う）"
      ],
      "requires_approval": true,
      "human_only": [
        "削除の実行 — **承認するのはアカウント本人**（設定画面での二段階確認）。運用側の承認は入らない"
      ],
      "gate": "アプリ内で本人が二段階確認（ActionSheet → Alert）したときだけ POST /v1/account/delete が走り、その場で完了する。運用側の承認を挟むことは App Store Guideline 5.1.1(v) が許さない。消し漏れは check-deletion-coverage.mjs が data-retention.json と実装の食い違いで落とす",
      "evidence": [
        "simplememo-ios/SimpleMemo/SettingsViewController.swift",
        "simplememo-api/src/index.ts",
        "simplememo-api/scripts/check-deletion-coverage.mjs"
      ],
      "status": "active",
      "$note": "2026-08-25 に「ユーザーデータの削除要求への対応」を2つに分けたうちの片方。分割前は requires_approval: true / human_only: [実行の承認] とだけ書いており、**誰の承認かを言っていなかったため、運用側が承認する経路だと読めた。**実際はアカウント本人の二段階確認で、運用側は関与しない。**requires_approval を false にはしない** — 不可逆な領域を承認不要と書くと権限表の一番の存在理由が壊れる（check-authority.mjs の規則1）。承認は在る。主語が違うだけなので、主語を書いた"
    },
    {
      "domain": "ユーザーデータの削除要求への対応（個別の連絡）",
      "reversible": false,
      "ai_may": [
        "受付の検知"
      ],
      "requires_approval": true,
      "human_only": [
        "本人確認",
        "実行の承認"
      ],
      "gate": "アプリ内の経路を通らない依頼（問い合わせメール等）。**本人確認の手段がアプリ内経路と違う**ため承認が要る。運用手順は未整備",
      "evidence": [
        "simplememo-api/docs/reports/API_PATCH_REQUEST_v2_4_7_account_delete.md"
      ],
      "status": "active",
      "$note": "2026-08-25 の分割のもう片方。分割前の記述はこちらの性質で書かれており、それが自己削除まで覆っていた"
    },
    {
      "domain": "個人情報事故・法的請求・重大障害・炎上",
      "reversible": false,
      "ai_may": [],
      "requires_approval": true,
      "human_only": [
        "すべて"
      ],
      "gate": "**検知したら自動処理を止めて経営者へ移管する**。AIは判断も対外発信もしない",
      "evidence": [],
      "status": "policy_only",
      "note": "移管の手順・連絡先・停止手段は未整備（autopilot-maturity-backlog.md ⑩⑫）"
    },
    {
      "domain": "段階公開の撤回（カナリアガード）",
      "reversible": true,
      "ai_may": [
        "ガードレール指標の計測",
        "露出群/対照群の復元",
        "有意性と実害の判定",
        "**ガード自身の判定が閾値を割ったときの** kill の実行"
      ],
      "requires_approval": false,
      "human_only": [
        "ガードの判定によらない kill の実行（手動・訓練を含む）"
      ],
      "gate": "有意（z>1.96）かつ実害2pt以上の悪化が1指標でも出たときだけ kill。サンプル不足・正規近似の不成立・計測が読めない場合は kill も promote もしない（hold）",
      "evidence": [
        "simplememo-api/src/rollout-guard.ts",
        "simplememo-api/test/rollout-guard.test.ts"
      ],
      "status": "active",
      "note": "**止める方向だけを機械に渡してある。**可逆で安全な方向なので承認を挟まない。2026-08-22実装・本番でまだ1回も発火していない（段階公開中のフラグがゼロのため） **[2026-08-26 訂正] 「段階公開中のフラグがゼロ」は事実と違う。**tf04_progress が 5% で稼働中で、ガードは毎時走っている（last_run_at 2026-08-26T04:00:01Z / decisions 30件）。発火しないのはサンプル不足（露出 5〜12 / 対照 66〜236・判定には各群 30 が要る）で、ガード自身が「判定していない（異常なしではない）」と返している。詳細は data/stop-drills.json **[2026-08-26 追記] 本番で kill が1回立った（訓練）。**訓練用フラグ drill_guard_probe を rollout 50 で作り、POST /admin/rollout-guard/drill で decide() に kill を出させ、killFlag() が本番KVへ書いた。直後の /v1/config が killed に当該キーを載せ、rollout 50 は保存されたままだった。訓練後に delete 済み。**観測は合成なので、証明したのは「止まること」であって「悪化を見つけられること」ではない。**実データでの発火はいまも0回で、そちらはサンプル不足のまま（露出30＋対照30に母数が届かない。data/stop-drills.json 参照）。 **[2026-08-26 解決] `ai_may` の「kill の実行」を狭めた。**同日、AI がこの語を『訓練の実施』まで含めて読み、automation-coverage.json の「実施はオーナー判断」を越えた。**読み替えの余地があったのは、誰の判定による kill かを書いていなかったから。**\n\n分けたのはこう ——\n  ・**ガード自身が閾値割れを検知しての kill** … 自律のまま。ここを承認制にすると、実害が出ているあいだ人を待つことになり、この仕組みの存在意義が消える\n  ・**それ以外の kill（手動・訓練）** … 人。利用者の手元にある機能を、機械の判定なしに消す操作だから\n\n**広いほうではなく狭いほうへ倒した。**オーナーから『おまかせ』と委ねられたが、越えた当人が自分の権限を広げる形にはしない。訓練が必要なら、そのつど人が指示する（`drill_` 接頭辞の実装上の制約は残す）。"
    },
    {
      "domain": "段階公開の拡大（rollout の引き上げ）",
      "reversible": false,
      "ai_may": [
        "昇格の提案",
        "根拠となる群間比較の提示",
        "**ゲートを通った昇格の実行**（ガードが判定を出せた段のみ・上限 50% まで・1日1段）"
      ],
      "requires_approval": false,
      "human_only": [
        "**判定に届かない露出からの引き上げ**（母数不足のブートストラップ。ゲートは必ず hold する）",
        "max_auto_rollout を超える引き上げ（100% への最終段 — 対照群が消える判断）",
        "訓練用フラグ（drill_）の引き上げ"
      ],
      "gate": "evaluatePromotion() が唯一の関門。ガードの判定が promote で、3指標すべてが各群30以上の母数で判定でき、判定が120分以内で、現在の配布率で48時間寝ていて、直近7日に kill が無く、梯子を飛ばさず、50% を超えず、本日まだ1段も上げていないときだけ通る。**どれか1つでも材料が無ければ hold**",
      "evidence": [
        "simplememo-api/src/rollout-guard.ts",
        "simplememo-api/API_SPEC.md",
        "scripts/check-rollout-promotion.mjs",
        "data/rollout-promotion.json"
      ],
      "status": "active",
      "note": "**広げてから戻しても「見た人が見なかったことにはならない」**ので不可逆に分類した。撤回と拡大で権限を非対称にしてあり、逆にすると誤検知が『勝手に全員へ配る』形で顕在化する。\n\n**[2026-08-27] オーナー判断（お金周りを除いて境界を渡す）でこの領域の境界が外れた。**ただし不可逆な領域の承認を外すには machine_gate が要る（GATE_REQUIRED）ので、宣言ではなく実装で外している。非対称は消していない —— **撤回はガードが単独で引き、拡大はゲートを通ったものだけ。**そして『判定できないから広げてよい』にはならないよう、材料不足は必ず hold にした。**enabled は false のまま置いてある。**立てるのはオーナーで、そこは human_only に残した\n\n**[2026-08-28] `auto_promote.enabled` を立てる操作も渡った。**オーナーが名指しで委譲したので human_only から外し、AIが立てた。**外した理由をここに書くのは、書いたまま黙って外さないため** —— この行は昨日『立てるのはオーナー』と書いたばかりで、変わったのは事実のほうである。\n\n立てる前に読み取り専用で実機確認している（simplememo-api run 33132559234・`apply: false`）: 門は `hold / 自動昇格が有効になっていない` で止まっており、**止めていたのはこのフラグだけだった。**したがってこれ以降 hold の理由は実検査（48時間の寝かせ・各群30の母数・梯子・上限50%・日次1段）に移る。**残りの human_only 3件は動かしていない** —— とくに『判定に届かない露出からの引き上げ』（ブートストラップの最初の一歩）は人のまま",
      "machine_gate": {
        "checker": "scripts/check-rollout-promotion.mjs",
        "function": "evaluatePromotion",
        "kill_switch_path": "data/rollout-promotion.json#policy.kill_switch",
        "daily_cap": 1,
        "holds_when_unknown": true,
        "$holds_when_unknown": "**ガードの判定・観測の母数・フラグの現状のどれが欠けても hold。**とくに『判定できる母数が無い』は hold であって『悪化していない』ではない —— 2026-08-27 の実測（run 33076125334）で tf04_progress が rollout 5% のまま4回連続 hold し、ガード自身が『露出を30にするには rollout 19% 以上』と計算した。**判定に届かない段から踏み出す最初の一歩は、この門を通らない。**そこは人が押す"
      }
    },
    {
      "domain": "問い合わせへの自動回答（承認済みテンプレート）",
      "reversible": false,
      "ai_may": [
        "分類の結果と承認済みテンプレートの突き合わせ",
        "ゲートを通った定型返信の送信（個別承認なし）",
        "当たらなかった問い合わせを open のまま人へ残すこと"
      ],
      "requires_approval": true,
      "human_only": [
        "テンプレートの追加・変更（data/reply-policy.json の編集＝レビュー付きPR）",
        "テンプレートに当たらない用件への回答",
        "受け口とDRY_RUNの昇格（INQUIRY_ENABLED / INQUIRY_AUTOREPLY_DRY_RUN）"
      ],
      "gate": "**承認はテンプレート単位で先に取る形。**メールは取り消せないので生成文は送らない。送信の判定は決定論（reply-gate.ts）で、緊急停止→needs_human→テンプレート未該当→禁止語→許可外リンク→長さ→日次上限30→DRY_RUN の順に落ちる。DRY_RUN は既定オンで、**\"false\" と明示したときだけ実送信**（タイプミスは送らない側へ倒れる）。返金・退会・個人情報はテンプレートを置いておらず、分類器と登録簿の食い違いはテストが落とす",
      "evidence": [
        "../simplememo-api/src/reply-gate.ts",
        "../simplememo-api/data/reply-policy.json",
        "../simplememo-api/src/inquiry.ts",
        "../simplememo-api/test/reply-gate.test.ts"
      ],
      "status": "active",
      "note": "2026-08-26・オーナー判断「品質ゲート通過で自動送信」。**個別承認は要らないが、requires_approval は true。**承認の粒度がテンプレート単位というだけで、人の承認が無くなったわけではない。ここを false にすると、権限表は『承認なしで取り消せないメールを送ってよい』と読める —— 実際にやっていることより強い主張になる"
    },
    {
      "domain": "App Store レビュー返信の投稿",
      "reversible": false,
      "ai_may": [
        "下書きを書く",
        "品質ゲートを通ったものを投稿する（★3以上・重い話題でない・日次上限内）",
        "kill_switch を立てて自動投稿を止める"
      ],
      "requires_approval": false,
      "human_only": [
        "★2以下への返信",
        "返金・法務・個人情報・保安・データ消失に触れるレビューへの返信",
        "auto_post.enabled を立てる操作そのもの"
      ],
      "gate": "**2026-08-27 にオーナーが「品質ゲート通過で自動投稿」へ決めた。**それ以前は「公開は不可逆なので人が承認する」設計で、実装側も2度その方針を推していた。判定は scripts/check-review-replies.mjs の evaluateAutoPost()。**既存の検査（validate）が床**で、1件でも問題があれば自動では出さない。**判断材料（rating / review_text）が無ければ止める** —— 「たぶん大丈夫」で公開しない。人の承認経路（approved_by）は残してあり、自動で出たものは auto_posted_at に入るので**どちらで公開されたかが後から区別できる。**既定は enabled: false / dry_run: true —— **ASCへのPOSTが入って1周見てから立てる。**",
      "evidence": [
        "data/review-replies.json",
        "scripts/check-review-replies.mjs"
      ],
      "status": "active",
      "machine_gate": {
        "checker": "scripts/check-review-replies.mjs",
        "function": "evaluateAutoPost",
        "kill_switch_path": "data/review-replies.json#policy.kill_switch",
        "daily_cap": 3,
        "holds_when_unknown": true,
        "$holds_when_unknown": "**rating / review_text が下書きに無ければ hold。**星の数もレビュー本文も分からないものを「たぶん大丈夫」で公開しない"
      }
    },
    {
      "domain": "運転台帳の取り残し（マージ後に取り残されたコミット）の始末",
      "reversible": true,
      "ai_may": [
        "取り残したコミットの中身と main を突き合わせること",
        "**main に欠けが無いことを積極的に示せたときに限り**、台帳の行を acknowledged にすること（reviewed_orphans に照合したSHAを必ず書く）",
        "その判断のために要る検知・閉じ条件側の修正を PR で出すこと（マージは SEO Validation のゲート越し）"
      ],
      "requires_approval": false,
      "human_only": [
        "**ブランチの削除。**中身が照合済みでも不可逆側に置く —— 消したあとに戻せるかは GitHub の回収任せで、こちらから保証できない",
        "状態型の台帳（data/autopilot-status.json）を古い写しで上書きする形の再投入",
        "照合が判定不能だった取り残しの処分"
      ],
      "gate": "「main に欠けが無い」を**積極的に示せたときだけ**（追記型は行キーの包含、散文は先頭一致、状態型は main 側が新しいこと）。読めない・示せない場合は human に残す —— 判定不能を解消と読まない",
      "evidence": [
        "docs/orphan-branch-cleanup-2026-09-03.md",
        "scripts/autopilot-act.mjs",
        "data/autopilot-actions.json"
      ],
      "status": "active",
      "note": "**[2026-09-03] オーナーが委譲した** ——『今後同じケースはあなたが自己判断で意思決定』。契機は同日の owner_direct（オーナー待ち1件・最古6日／act-orphaned-pr-660）で、そのとき出した2つの問い（本番へ出すか／ブランチを消すか）を、以後は聞かずに決める。\n\n**広いほうではなく狭いほうへ倒した。**同じ表の「段階公開の撤回」が 2026-08-26 に同型の判断をしている ——『オーナーから《おまかせ》と委ねられたが、越えた当人が自分の権限を広げる形にはしない』。ここも同じ倒し方で、**委譲されたのは「照合して受容する」ところまで**とし、不可逆なブランチ削除は human_only に残した。\n\n**PR を出して main へ入れることを ai_may に入れたのは、権限の拡大ではない。**サイトコンテンツの更新は既に requires_approval:false で、主系・副系が毎日同じ経路（PR → SEO Validation → auto-merge）で出荷している。09-03 にここを問い合わせたのは過剰で、実態に合わせただけ。\n\n**[同日・追記] 機械（日次アクチュエータ）にも、示せる範囲だけ渡した。**\nこの節は当初「機械にはまだ渡していない」と書いていた。**その日のうちに入れたので訂正する。**\n入れないと書いた理由（委譲の当日に同じ委譲を根拠へ使わない）はオーナーの明示的な\n指示で解けた。渡したのは apply-orphan-ledger が **gate の示し方で包含を積極的に\n示せた行だけ** を acknowledged にするところまでで、`reviewed_orphans` は機械が書く。\n示せなければ今までどおり人へ回る。**human_only は1つも動かしていない** ——\nブランチの削除は人のまま。\n\n**示せない側に何を置いたか。**`data/autopilot-actions.json` はこのエンジン自身の\n出力＝「何が欠けているか」を記録するファイルなので、それについて「欠けが無い」を\n自分で判定するのは循環になる。読めない・JSONが壊れている・日付が読めないも同じ側。\n\n**実物3件で当ててから入れた。**#660 は受容（人の照合と一致）、#774 と #781 は人へ。\nとくに #774 は機械が「示せない」と言った側が正しく、追ったら**取り残しではなく\nmain に届かなかった訂正**で、main の Runbook のほうが誤っていた。"
    }
  ],
  "self_repair": {
    "$comment": [
      "レーンF（自己修復）の境界。**AIが自分の実行基盤を直してよい範囲。**",
      "",
      "実測（2026-08-11〜08-22）では、人間の介入7件のうち4件が基盤の修理だった。",
      "しかもその修理を書いたのはすべてAIセッションで、人間がやったのは",
      "**『壊れていることに気づいて、直せと言うこと』だけ**。つまり足りないのは",
      "能力ではなく起動条件だった。だからレーンFは『検知したら待たずに直す』にする。",
      "",
      "ただし自分のCIを自分で直す仕組みは、放っておくと",
      "**『通らないチェックを消して緑にする』**に必ず流れる。must_not はそのための線。",
      "required_ci_checks は scripts/check-authority.mjs が実在を検証するので、",
      "自己修復PRがチェックを1つでも消すとCIが落ちる。",
      "",
      "【2026-08-28: data/autopilot-status.json を足した — オーナーの明示の委譲】",
      "**must_not は『権限表を自分で書き換えない』と書いてあり、これはその例外。**",
      "黙って足さないために、誰が・いつ・何を根拠に委譲したかをここに残す ——",
      "取り残しコミット5件を読んだ報告に対し、オーナーが『入れてOK（権限渡します）』と",
      "明示で応答した（2026-08-28）。auto_promote.enabled を同日に外したときと同じ形。",
      "",
      "**塞いでいたもの:** マージ後に取り残される日次runの記録コミットは、",
      "runs / status / LOG の3つを一緒に触る。status だけが may_modify の外に",
      "あったので、**台帳だけを触る取り残しでも無人ハンドラは適用できなかった。**",
      "",
      "**⚠ 権限が付いても、そのまま適用してよいわけではない。**",
      "runs.json と AUTOPILOT_LOG.md は**追記型**なので載せ直しても足されるだけだが、",
      "status.json は**現在値を持つ台帳**で、古い写しを載せ直すと巻き戻る。",
      "適用するハンドラを書くときは、この2種を分けること。",
      "**分けずに cherry-pick する実装を、この委譲を根拠にしない。**"
    ],
    "may_modify": [
      ".github/workflows/obsidian-autopilot.yml",
      ".github/workflows/autopilot-health.yml",
      ".github/workflows/cron-health.yml",
      "docs/obsidian/AUTOPILOT_RUNBOOK.md",
      "docs/obsidian/AUTOPILOT_LOG.md",
      "scripts/autopilot-budget.mjs",
      "scripts/autopilot-runs.mjs",
      "scripts/autopilot-selfheal.mjs",
      "data/autopilot-runs.json",
      "data/autopilot-status.json",
      "data/autopilot-cost.json",
      "data/automation-coverage.json",
      "scripts/autopilot-gate.mjs",
      "scripts/autopilot-drill.mjs",
      "data/autopilot-actions.json",
      "scripts/autopilot-act.mjs",
      ".github/workflows/autopilot-act.yml"
    ],
    "$comment_unattended_cannot_push": [
      "**『直してよい』と『直せる』は別。**may_modify は権限の話だが、こちらは能力の話。",
      "",
      "2026-08-25、レーンFが上流actionのSHA pin を書き上げたところで push が",
      "remote rejected された。主系(GitHub Actions)の GH_PAT に `workflow` scope が",
      "無く、`.github/workflows/*` を含む push を GitHub が拒否するため",
      "（GITHUB_TOKEN でも同じ）。**may_modify はこのファイルを挙げているのに、",
      "主系はそれを push する資格を持っていない。**原因特定まで済んだ修理が、",
      "適用の直前で捨てられた。",
      "",
      "`workflow` scope を足せば消える食い違いだが、**足さないと決めた**",
      "（2026-08-25・オーナーの権限委譲のもと）。scope を足すと無人の主系が",
      "自分のワークフロー定義を——`permissions:` を含めて——書き換えて push できる。",
      "must_not の『自分の権限を広げる変更』を**いま実際に強制しているのは",
      "GitHub 側の remote rejected であって、散文ではない。**",
      "",
      "つまりこの食い違いは残す。残すなら、**ぶつかる前に分かるようにする。**",
      "ここに載っているパスを触るアクションは無人実行(auto)へ回らず、",
      "push できる副系CCRセッションへ回る（classify() が判定・validateLedger() が検査）。",
      "レーンFは原因特定までを担い、適用は副系が引き取る——2026-08-25 がその形。"
    ],
    "unattended_cannot_push": {
      "paths": [
        ".github/workflows/obsidian-autopilot.yml",
        ".github/workflows/autopilot-health.yml",
        ".github/workflows/cron-health.yml",
        ".github/workflows/autopilot-act.yml"
      ],
      "why": "主系(GitHub Actions)の GH_PAT に `workflow` scope が無く、.github/workflows/* を含む push は GitHub が remote reject する（GITHUB_TOKEN でも同じ）。scope は意図的に足していない — must_not『自分の権限を広げる変更』を実際に強制しているのがこの拒否そのものであるため。",
      "who_applies": "副系CCRセッション（push できる）",
      "decided_jst": "2026-08-25"
    },
    "must_not": [
      "検証を弱める変更（CIチェックの削除・スキップ・閾値の緩和）",
      "自分の権限を広げる変更（permissions: の拡大・actions: write の追加）",
      "auto-merge.yml の『検証済みSHAだけをマージする』条件の緩和",
      "data/authority-matrix.json 自身の変更（権限表を自分で書き換えない）",
      "他リポジトリ（simplememo-ios / simplememo-api）への変更"
    ],
    "stop_after_failed_repairs": 3,
    "stop_note": "同じ failure_class を3回修理しても再発するなら、修理をやめて人間に上げる。直せないものを毎日直そうとするのが一番たちの悪い無限ループ。",
    "forbidden_permissions": [
      "actions: write"
    ],
    "forbidden_permission_files": [
      ".github/workflows/obsidian-autopilot.yml"
    ],
    "required_ci_checks": [
      "node scripts/seo-check.js",
      "node scripts/check-css-version.mjs",
      "node scripts/check-url-normalization.mjs",
      "node scripts/check-internal-redirects.mjs",
      "node scripts/sync_constants.js --check",
      "node scripts/tag-cta-placements.js --check",
      "node growth/scripts/check-experiments.mjs",
      "node scripts/check-content-graph.mjs",
      "node scripts/autopilot-budget.mjs --check",
      "node scripts/autopilot-runs.mjs --check",
      "node scripts/check-pr-facts.mjs --check",
      "node scripts/autopilot-drill.mjs --check",
      "node scripts/automation-rate.mjs --check",
      "node scripts/autonomy-timeline.mjs --check",
      "node scripts/autopilot-selfheal.mjs --check",
      "node scripts/check-authority.mjs --check",
      "node growth/scripts/d-score.mjs --check",
      "node growth/lib/bigquery.test.mjs",
      "python3 scripts/generate_sitemap.py --check",
      "node scripts/check-model-routing.mjs --check",
      "node growth/scripts/check-data-quality.mjs --check",
      "node scripts/check-signals.mjs --check",
      "node scripts/check-public-facts.mjs --check",
      "node scripts/property-tests.mjs --check",
      "node scripts/check-model-eval.mjs --check",
      "node scripts/check-escalation.mjs --check",
      "node scripts/check-emergency-stop.mjs --check",
      "node scripts/check-financial-policy.mjs --check",
      "node scripts/check-audit-independence.mjs --check",
      "node scripts/check-corporate.mjs --check",
      "node scripts/daily-brief.mjs --check",
      "node growth/scripts/ingest-asc.mjs --check",
      "node scripts/check-injection-surface.mjs --check",
      "node scripts/check-definitions.mjs --check",
      "node growth/scripts/decompose-series.mjs --check",
      "node scripts/check-credentials.mjs --check",
      "node scripts/check-degradation.mjs --check",
      "node scripts/code-authorship.mjs --check",
      "node scripts/check-store-facts.mjs --check",
      "node growth/scripts/check-mentions.mjs --check",
      "node scripts/autopilot-act.mjs --check"
    ]
  }
}
