2026年7月26日日曜日

iPhone14 がお亡くなりになりました

iPhone14 がお亡くなりになりました

火気厳禁
戒めのために軽く残しておきます

経緯

  • バッテリー交換時に出火
  • 消防および警察にお世話になる

原因

  • おそらく iPhone のバッテリーを無理矢理両面テープから剥がたことによるバッテリーの被膜破れ
  • バッテリーは正規品
  • そのまま科学反応で出火

発火後

  • 10-20分で自然鎮火
  • 大きな炎は出ずに火花のみ
  • すぐに 119 番
  • 鎮火後も煙と匂いがすごい
  • 常に換気したほうがいい

現場検証

  • 通報後20分程で到着
  • 消防、警察立会いの元状況確認/質問/説明
  • 各種写真撮影
  • 現場の寸法測定

証拠品回収

  • バッテリーは iPhone14 ごと回収
  • 鑑識後に返却
  • おそらく壊れているので破棄予定

罹災証明

  • 罹災申告書を記載し近くの消防署に持っていく
  • 代わりに罹災証明申請書をもらう
  • 記載し罹災証明申請書を提出
  • 後日罹災証明申請書をもらう
  • それを保険会社に提出
  • スマホの場合は家財が対象の火災保険ではほぼ降りないため保険会社への申請が不要な場合は罹災証明関係の申請は不要

学び

  • iPhone のバッテリー交換は本当に慎重に行う
  • 両面テープから剥がすときは特に慎重に行う
  • 特にヒータでの温め系はやめたほうがいい
  • バッテリー交換の紹介動画などでは iPhone14 のバッテリー交換時にケースを使って温めてテープ系を剥がれやすくする
  • しかしそれによる出火の可能性が高まる可能性があるのでやめたほうがいい
  • 一番安心なのは Apple Store に持ち込むこと

代替

  • とりあえず即日中古の iPhone15 (6万) 購入
  • 証拠品として iPhone も持っていかれたため SIM カードがない
  • なので SIM カードの再発行を申請
  • SIM カードは 3-7日程度で到着する
    • eSIM なら即日交換できるのかも
  • SIM カード到着後復元
  • SIM + iPhone15 到着で復元可能状態
  • それまでは手元にあった iPhoneXR を Wifi のみで使用して代用
  • ただし SMS 認証が絡むログインはできない (PayPay など)
  • 基本は Mac があったので Mac 側でカバーできた

各種到着までの期間

  • iPhone15 -> 購入から2日
  • SIMカード -> 再発行から2日
  • iPhone15ケース、フィルタ -> 購入から1日
  • 破損 iPhone14 -> 鑑識回収からN日

SIM は Nuro モバイルなのですが再発行が予想以上に早くてびっくりしました

復元作業

  • 当然 iPhone のクイックスタートは使えないため手動で復元
  • App Store の購入済みアプリを見て必要なアプリをピックアップ
  • 元の iPhone がないと引き継げないアプリがある場合は基本あきらめる
    • 可能な限りアプリ (Authenticator など) はクラウド同期しておく
    • 同期 + ログインで各アプリを復元
    • ダメな場合はすべて再登録 (パスキーなど)
    • 2Auth も SMS ではなくメールや復旧パスを使えるようにしておく
  • 新規でセットアップすると端末がまだ信頼されていないため以下の作業はできない (待つしか無い)
    • Apple ID のパスワード変更
    • 登録している端末の削除
    • ウォレットの同期 (一部のカード (Pasmo, Suica, Nanaco など) は不可)
    • 最大で1週間ほどすると権限がもらえるようになる
    • auじぶん銀行など金融系のアプリも一部即時利用の制限あり
  • セブンアプリなど金融系のアプリは実際に窓口 or ATMに行く必要あり
    • 金融系は全部厳しいイメージ

反省点

  • eSIM 切り替えを行い eSIM 対応端末を購入すれば即日復元可能だった
  • 焦って先に SIM 再発行をしてしまいその間 eSIM 切り替えができなかったので結局 SIM を待つことになってしまった
  • SIM 対応の iPhone を購入する羽目になってしまった
  • eSIM 切り替え + iPhone17 がベストだったかも

戻ってきた iPhone14

  • 真っ黒
  • 居住地域所定の廃棄方法で廃棄
  • サルベージ等のデータ復元や修理はそもそもやりませんでした、諦めていました

最後に

もしリチウム系のバッテリーが発火した場合は焦らず落ち着いて対処しましょう
すぐに水をかけたりすると反応が激しくなり延焼広げることもあるのでやめましょう
そしてすぐに 119 番して消防を呼びましょう

2026年7月25日土曜日

ドラクエウォーク オルゴデミーラLv99 討伐メモ

ドラクエウォーク オルゴデミーラLv99 討伐メモ

パクリだけどしんどい
考えた人すごい

討伐日時

  • 2026/07/25 時点

装備

ばくれつけん大神官

領域レベル上げ要因なので神喰らいじゃなくてもいいかも
基本は会心モリモリ

時渡り

錬成済みのクレセントムーン
最遅にすること

魔剣士

クロノスx銀河
会心ダメージ盛りが理想

時流し大神官

ほむらは「ラーミアの祝福」要因なのでゼシカに装備させている「聖なるマヒャド」のやまびこ要因なので他で代用できるかも
2回時流しして2回ラーミアの祝福を撃ったあとは何もすることがない
装備は正直何でも OK

ゼシカ

ダーマの神杖
基本は聖なるマヒャドを連打してテンションダウンを狙いまくる

こころ

ばくれつけん大神官

バリゲーンでばくれつけんを撃つので必須
あとは会心モリモリ
こころ道は右寄せ

時渡り

右隣強化

魔剣士

ヒャド盛り + はめつゴーレム
はめつのゴーレムは「きあいため」要因
心珠は「覇王斬ダメージ30%」と「会心ダメージ5%」 (なぜか持っていた)

時流し大神官

ミカヅチは必須
すばやさ重視
あとは MP 枯渇を考えるといいかも (長期戦になることもあるので)

でも後々考えるとミカヅチもほむらも不要で別のサポートでもいいのかもしれない
ミカヅチはばくれつけんで対応できるしラーミアの祝福も結局ゼシカの聖なるマヒャドのやまびこ用 (テンションダウン狙い) なのでテンションダウンができれば別にいらない

ゼシカ

一応ヒャド盛り
すばやさは時渡りより速ければ OK

すばやさ

  • 時流し大神官 -> 1326
  • ばくれつけん大神官 -> 940
  • 魔剣士 -> 1032
  • ゼシカ -> 947
  • 時渡り -> 554

流れ

  • 1ターン目に時渡りの時間レベル3まで行かなかったらリセット
  • ばくれつけん or 時戻しでオルゴデミーラが我に返らないときはリセット

1ターン目

  1. 大神官 魔剣士をゼシカに入れ替え -> アンコール -> 闘魂
  2. ゼシカ 魔境の詠唱 -> 聖なるマヒャド
  3. 大神官 アンコール -> 闘魂
  4. 時渡り しおさい

2ターン目

1.大神官 ざざんぱ時流し
2.大神官 アンコール -> タイムチャージ
3.ゼシカ 聖なるマヒャド
4.時渡り ゼシカを魔剣士に入れ替え -> 闘魂 -> 闘魂 -> しおさい

3ターン目

  1. 大神官 大神官をゼシカ入れ替え -> ざざんぱ時流し
  2. ゼシカ 聖なるマヒャド
  3. 魔剣士 因果
  4. 時渡り 闘魂 -> 闘魂 -> しおさい

4ターン目

  1. 大神官 ラーミアの祝福 -> ゼシカ or 時戻しで魅了が解除されないなら大神官を大神官に入れ替えばくれつけん
  2. ゼシカ 聖なるマヒャド
  3. 魔剣士 時戻し
  4. 時渡り 闘魂 -> 闘魂 -> しおさい

5ターン目

  1. 大神官 ラーミアの祝福 -> ゼシカ or 時戻しで魅了が解除されないなら大神官を大神官に入れ替えばくれつけん
  2. ゼシカ 聖なるマヒャド
  3. 魔剣士 時戻し
  4. 時渡り 闘魂 -> 闘魂 -> しおさい

6ターン目

  1. 大神官 大神官を大神官に入れ替えばくれつけん
  2. ゼシカ 魔境の詠唱 -> 聖なるマヒャド
  3. 魔剣士 きあいため
  4. 時渡り 闘魂 -> 闘魂 -> しおさい

7ターン目

  1. 大神官 ばくれつけん
  2. ゼシカ 聖なるマヒャド
  3. 魔剣士 会心必中
  4. 時渡り 闘魂 -> 闘魂 -> しおさい

8ターン目

  1. 大神官 ばくれつけん
  2. ゼシカ 聖なるマヒャド
  3. 魔剣士 覇王斬
  4. 時渡り 闘魂 -> 闘魂 -> しおさい

もしここで倒せなくてもMPが尽きるまで6ターン以降を繰り返せばいいだけ

最後に

そもそも装備もこころもレベルもないとクリアできないので狭き門です
なぜか全部揃ってたのでクリアしてみました

まだドラクエウォークが続いていることにビックリ

参考サイト

2026年7月3日金曜日

Issue を作成したらあとは AI 先生に修正してもらえばいいじゃない

Issue を作成したらあとは AI 先生に修正してもらえばいいじゃない

Codex Skills 編

環境

  • Ubuntu 24.04
  • codex 0.142.5
  • Gitlab 18.11.6

仕組み

目的: GitLab の Issue を自動検知し、AI(Codex)を使ってコード修正〜MR作成までを自動化するエージェント。


構成要素

ファイル 役割
main.py エントリポイント。初期化してスケジューラを起動
scheduler.py 定期ポーリングループ。Issue の処理を制御
mygitlab.py GitLab API から agent ラベルの Issue を取得
state.py SQLite で処理済み Issue を管理(二重処理防止)
codex.py Codex CLI をサブプロセスで起動し AI エージェントを実行
codex_skills/ Codex に渡すスキル定義(修正・テスト・コミット・MR作成)
config.py 全設定値の一元管理

動作の流れ(概要)

  1. Issue 検知: POLL_INTERVAL(60秒)おきに GitLab をポーリングし、agent ラベルの付いた Issue を取得
  2. 重複防止: 取得した Issue が SQLite に記録済みかチェックし、処理済みならスキップ
  3. AI 修正: 未処理の Issue に対して Codex CLI を起動。gitlab-issue-agent スキルに Issue の情報(ID・タイトル・説明)を渡す
  4. Codex の自律作業: Codex がスキルの指示に従い、コード修正 → テスト実行 → コミット → MR 作成を自律的に実施
  5. 完了記録: 処理が終わった Issue ID を SQLite に保存し、次のサイクルへ

ポイント

  • 冪等性: SQLite による処理済み管理で同じ Issue を何度も処理しない
  • 疎結合: Codex とのやり取りは環境変数とプロンプトのみで、スキルの追加・変更が容易
  • 自律性: MR 作成まで人手不要。レビューアー・アサインも自動設定済み

流れ

基本は対象の Issue 分ループして次々修正し MR を作成します

サンプルコード

ツリー

.
├── codex_skills
│   ├── create-mr
│   │   ├── scripts
│   │   │   └── create_mr.py
│   │   └── SKILL.md
│   ├── git-commit
│   │   └── SKILL.md
│   ├── gitlab-issue-agent
│   │   └── SKILL.md
│   └── run-tests
│       └── SKILL.md
├── codex.py
├── config.py
├── logger.py
├── main.py
├── mygitlab.py
├── README.md
├── scheduler.py
├── state.db
├── state.py
└── systemd
    └── codex-agent.service

main.py

import logging

from logger import setup_logger
from scheduler import run
from state import init_db

logger = logging.getLogger(__name__)

if __name__ == "__main__":
    setup_logger()
    init_db()
    logger.info("Starting gitlab bug fix agent")
    try:
        run()
    except Exception:
        logger.exception("Agent stopped due to an unhandled exception")
        raise

scheduler.py

import logging
import time

from codex import run_codex
from config import POLL_INTERVAL
from mygitlab import get_issues
from state import is_processed, mark_processed

logger = logging.getLogger(__name__)


def run():
    logger.info("Scheduler started")
    while True:
        logger.info("Polling GitLab issues")
        issues = get_issues()
        logger.info("Fetched %d issues", len(issues))

        for issue in issues:
            iid = issue["iid"]

            if is_processed(iid):
                logger.info("Skipping already processed issue %s", iid)
                continue

            logger.info("Processing issue %s: %s", iid, issue.get("title", ""))
            run_codex(issue)

            mark_processed(iid)
            logger.info("Marked issue %s as processed", iid)

        logger.info("Polling complete; sleeping for %s seconds", POLL_INTERVAL)
        time.sleep(POLL_INTERVAL)

codex.py

import logging
import os
import subprocess

from config import (
    CODEX_PATH,
    GITLAB_TOKEN,
    GITLAB_URL,
    MR_ASSIGNEE_ID,
    MR_REVIEWER_IDS,
    PROFILE,
    PROJECT_ID,
    REPO_PATH,
    SANDBOX,
    SONNET_API_KEY,
)

logger = logging.getLogger(__name__)


def run_codex(issue):
    env = os.environ.copy()
    issue_id = issue["iid"]

    # 環境変数設定(codex_skills/create-mr/scripts/create_mr.py で使用)
    env["ISSUE_ID"] = str(issue_id)  # MR のブランチ名生成に使用
    env["ISSUE_TITLE"] = issue["title"]  # MR のタイトル生成に使用
    env["GITLAB_URL"] = GITLAB_URL  # GitLab API エンドポイント
    env["GITLAB_TOKEN"] = GITLAB_TOKEN  # GitLab API 認証
    env["PROJECT_ID"] = str(PROJECT_ID)  # MR 作成対象プロジェクト
    env["MR_ASSIGNEE_ID"] = str(MR_ASSIGNEE_ID)  # MR アサイン対象ユーザー
    env["MR_REVIEWER_IDS"] = ",".join(map(str, MR_REVIEWER_IDS))  # MR レビュアー
    env["SONNET_API_KEY"] = SONNET_API_KEY  # Codex CLI が使用する LLM API キー

    logger.info("Launching Codex for issue %s", issue_id)

    prompt = f"""
Use the skill gitlab-issue-agent.

Issue ID: {issue_id}
Title: {issue['title']}
Description: {issue['description']}
"""

    result = subprocess.run(
        [
            CODEX_PATH,
            "exec",
            "--cd",
            REPO_PATH,
            "--profile",
            PROFILE,
            "--sandbox",
            SANDBOX,
            prompt,
        ],
        env=env,
        check=True,
        capture_output=True,
        text=True,
    )

    if result.stdout:
        logger.info("Codex stdout:\n%s", result.stdout)
    if result.stderr:
        logger.warning("Codex stderr:\n%s", result.stderr)

    logger.info("Codex finished for issue %s", issue_id)

config.py

GITLAB_URL = "https://your-gitlab-url"
GITLAB_TOKEN = "glpat-xxx"
PROJECT_ID = 12345
TARGET_LABEL = "agent"

REPO_PATH = "/home/user/target"
CODEX_PATH = "/home/user/.local/bin/codex"
PROFILE = "sonnet"
SONNET_API_KEY = "dummy"
SANDBOX = "danger-full-access"

POLL_INTERVAL = 60

MR_ASSIGNEE_ID = 1
MR_REVIEWER_IDS = [2]

DB_PATH = "./path/to/state.db"
LOG_PATH = "./path/to/agent.log"

state.py

import logging
import sqlite3

from config import DB_PATH

logger = logging.getLogger(__name__)


def init_db():
    logger.info("Initializing state database at %s", DB_PATH)
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    c.execute("""
    CREATE TABLE IF NOT EXISTS processed_issues (
        issue_id INTEGER PRIMARY KEY
    )
    """)
    conn.commit()
    conn.close()
    logger.info("State database is ready")


def is_processed(issue_id: int) -> bool:
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    c.execute("SELECT 1 FROM processed_issues WHERE issue_id=?", (issue_id,))
    result = c.fetchone()
    conn.close()
    return result is not None


def mark_processed(issue_id: int):
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    c.execute("INSERT INTO processed_issues(issue_id) VALUES(?)", (issue_id,))
    conn.commit()
    conn.close()
    logger.info("Persisted processed issue %s", issue_id)

logger.py

import logging

from config import LOG_PATH


def setup_logger():
    logging.basicConfig(
        filename=LOG_PATH,
        level=logging.INFO,
        format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
    )

mygitlab.py

import logging

import requests
from config import GITLAB_TOKEN, GITLAB_URL, PROJECT_ID, TARGET_LABEL

HEADERS = {"PRIVATE-TOKEN": GITLAB_TOKEN}

logger = logging.getLogger(__name__)


def get_issues():
    url = f"{GITLAB_URL}/api/v4/projects/{PROJECT_ID}/issues"
    params = {"labels": TARGET_LABEL, "state": "opened"}
    logger.info(
        "Fetching issues from GitLab project %s with label %s", PROJECT_ID, TARGET_LABEL
    )
    response = requests.get(url, headers=HEADERS, params=params)
    issues = response.json()
    logger.info("GitLab issues fetch completed with status %s", response.status_code)
    return issues

codex_skills/create-mr/SKILL.md

---
name: create-mr
description: Create a GitLab merge request.
---

Run the script:

python .codex/skills/create-mr/scripts/create_mr.py

codex_skills/create-mr/scripts/create_mr.py

import logging
import os
import subprocess
import sys
from pathlib import Path

import requests

SCRIPT_ROOT = Path(__file__).resolve().parents[3]
if str(SCRIPT_ROOT) not in sys.path:
    sys.path.append(str(SCRIPT_ROOT))

from logger import setup_logger

setup_logger()
logger = logging.getLogger(__name__)

issue_id = os.environ.get("ISSUE_ID")

branch = f"agent/issue-{issue_id}"

GITLAB_URL = os.environ["GITLAB_URL"]
TOKEN = os.environ["GITLAB_TOKEN"]
PROJECT_ID = os.environ["PROJECT_ID"]
MR_ASSIGNEE_ID = int(os.environ["MR_ASSIGNEE_ID"])
MR_REVIEWER_IDS = [int(x) for x in os.environ["MR_REVIEWER_IDS"].split(",")]

url = f"{GITLAB_URL}/api/v4/projects/{PROJECT_ID}/merge_requests"

headers = {"PRIVATE-TOKEN": TOKEN}

issue_title = os.environ.get("ISSUE_TITLE", f"Issue {issue_id}")

data = {
    "source_branch": branch,
    "target_branch": "main",
    "title": f"修正: {issue_title}",
    "assigned_to_id": MR_ASSIGNEE_ID,
    "reviewer_ids": MR_REVIEWER_IDS,
}

logger.info("Creating merge request for issue %s on branch %s", issue_id, branch)
response = requests.post(url, headers=headers, json=data)
logger.info("Merge request creation completed with status %s", response.status_code)

codex_skills/git-commit/SKILL.md

---
name: git-commit
description: Commit and push changes to a new branch.
---

Steps:

1. Create branch:
   agent/issue-<ISSUE_ID>

2. Commit:
   git add .
   git commit -m "fix: issue <ISSUE_ID>"

3. Push:
   git push -u origin <branch>

codex_skills/gitlab-issue-agent/SKILL.md

---
name: gitlab-issue-agent
description: End-to-end agent that processes a GitLab issue, applies fixes, runs tests, and creates a merge request.
---

You are an autonomous software engineering agent.

You will be given:

- Issue ID
- Title
- Description

# Your job

## Step 1: Understand the issue

- Identify the root cause
- Determine what needs to be fixed

## Step 2: Create a plan

Break down into tasks:

- files to modify
- logic changes
- tests needed

## Step 3: Implement fix

- Modify the codebase
- Keep changes minimal and clean

## Step 4: Run tests

Use the skill:

- run-tests

If tests fail:

- fix the issue
- retry until success (max 3 times)

## Step 5: Commit changes

Use skill:

- git-commit

## Step 6: Create MR

Use skill:

- create-mr

# Rules

- Do not break existing functionality
- Follow project conventions
- Prefer small commits

codex_skills/run-tests/SKILL.md

---
name: run-tests
description: Run Go validation and test suite.
---

Execute:

- go fmt ./...
- go vet ./...
- go build ./...
- go test ./...

If any step fails:

- Analyze the error
- Fix the issue
- Re-run

使い方

  • codex のインストールと各種設定
  • codex_skills にある各種 skill を .codex/skills 配下にコピー
  • config.pyの編集
  • codex_skills/run-tests/SKILL.md の編集
  • un run python main.py
  • Issue を作成し適切なラベルを振る

課題

  • Issue にしっかりと TODO ややるべきこと課題を記載する必要がある
    • Issue の内容が適当すぎると MR の修正内容ももうまく行かない
    • Issue のタスクが大きすぎるとうまくいかない
    • 可能な限り細かく TODO を書きつつ粒度を細かくする必要がある
  • main ブランチの pull タイミングをどうするか
    • 次の Issue を捌く前に一旦 main に戻るかそのブランチから続きを開発したいか
    • 前に作成した MR がマージされるまで次の Issue を捌くのを待つか
  • サンドボックス環境なのでネットワークや書き込み権限をしっかり与える必要がある
    • Codex でネットワーク操作 (今回だと push と MR 作成) をする場合にはほぼほぼ danger-full-access が必須そう
    • デフォルトは workspace-write なので書き込めるだけ、コードを修正したりなど (参考)
    • ちなみに Ubuntu だと bubblewrap を使ってサンドボックス化するのでインストールと sysctl の設定が必要
    • sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
    • セキュリティ的なことを考えるとインタラクティブモードが一番良さそう
    • codex を実行する環境自体をサンドボックス(コンテナや特別なVM)にする
  • 現状は 1Issue - 1MR になっている
    • AI が捌けるタスクの粒度上 Issue は可能な限り小さなタスクにする必要がある
    • ただ実際の現場だと MR に複数の Issue 対応を追加したいケースがある
    • MR が大量になってしまうのでレビューが大変になる (これも AI にお任せでいいかもしれないが)
  • スケジューラ側から codex 側に値を渡すのに環境を使っているができれば別の仕組みを考えたい
  • 処理した Issue かどうかの判断を sqlite で行っているが sqlite を使わずに別のラベルに付け替えるだけでも良さそう
    • sqlite にしておけば履歴的なこともできるメリットはある

所感

  • インタラクティブモードでコマンドの許可や権限をいちいち与えるのも面倒ではあるがインタラクティブモードのほうがセキュアなのかもしれない
  • 小さいタスクならこれで十分だが大きなタスクはまだ厳しいそう
  • VSCode + Copilot でやる AI 開発と Codex + インタラクティブモードでやる AI 開発と Codex の自動化とどれがいいかではなく結局は使い分けな気がする
  • Skills は必須ではないと思うがあったほうが作業は正確になると思う
    • すべて Codex CLI 入力時のプロンプトでまかなえる可能性もある
    • Skills にするとその辺りのやりたいことがコード化されるので見える化できるのと作業の安定性が図れそう
  • Codex CLI 以外の CLI AI エージェントでも試してみたい

最後に

Codex CLI の世界だけですべてカバーできないだろうか
結局 Codex CLI はプロンプトに対するアウトプットを返してくれるだけなのでスケジューラなど他の仕組みは自分で作るしか無いのだろうか

Codex のデスクトップアプリは「定期実行して」というとやってくれるらしいがそれと同じでなくてもいいが CLI にもほしいところ