LivingrimoireでAIにストップウォッチを1行で追加した(企業は1年必要だと言うけど)

Dev.to / 2026/4/19

💬 オピニオンDeveloper Stack & InfrastructureSignals & Early TrendsIdeas & Deep AnalysisTools & Practical UsageModels & Research

要点

  • この記事は、大手AI企業がタイマーのような単純機能でも遅れるのは、UI/バックエンド/コンプライアンス等と多チームにまたがる「グルーコード」型の密結合アーキテクチャに依存しているからだと主張します。
  • Livingrimoireは、スキルを分離・モジュール化し、決定論的に動作させつつ、トリガーされるまで休眠させ、ホットスワップできる“プラグ&プレイ”なAIスキル構成だと紹介します。
  • 著者はLivingrimoireの考え方を使って、音声操作のストップウォッチ機能をAIに追加するデモを行い、スキル追加の有効化がワンラインのコード呼び出しで済むことを示しています。
  • ストップウォッチは開始/一時停止/再開/リセット、経過時間と状態の報告、さらに毎分のマイルストーンを自動で告知する機能を持ち、専用のスキルクラスにすべて内包されています。
  • 全体として「コーダーパンク的なモジュール設計で素早く出す」ことを、「来年」などと遅れて発表されがちな企業のロードマップとの差として位置づけています。

大手AI企業は、まるで新しい粒子加速器を公開するかのように、たった小さな機能を発表するのが大好きです。

“タイマーが来ます…たぶん来年のどこかで。”

タイマー

ストップウォッチ

もう$5のキッチンガジェットでも付いているような機能です。

一方で、コーダーパンクの地下では、企業のロードマップの読み込みが終わる前に、こっちは腕まくりして機能を出荷しています。

Livingrimoire modular software design pattern を使って、私のAIに 音声操作のストップウォッチスキル を追加する方法をお見せします。そしてそれを たった1行のコード で有効化しました。

はい。1行。

なぜコーポレートAIは動きが遅いのか

タイマーが難しいからではありません。

gluecodeモノリス だからです。

あらゆる「シンプルな」機能は、次のものに触れます:

  • プロダクト層
  • 安全性の層
  • UI層
  • バックエンドサービス
  • テレメトリ
  • コンプライアンス
  • エンタープライズ要件
  • 国際化
  • アクセシビリティ
  • そして、全員がミーティングを必要とする十数のチーム

キックオフの計画が終わる頃には、私はその機能をもう出荷しています。

⚡ 入る:Livingrimoireパターン

Livingrimoire は プラグ&プレイのAIスキルアーキテクチャ です。

各スキルは:

  • 隔離されている
  • モジュール化されている
  • 決定論的である
  • トリガーされるまで休眠状態
  • ホットスワップ可能
  • 1 LOC で有効化される

これはコーポレートのgluecodeとは真逆です。

これは コーダーパンクのエンジニアリング です。

ストップウォッチスキル(はい、今や私のAIにもあります)

できることは次のとおりです:

  • 「ストップウォッチを開始」→ 計測を開始
  • 「ストップウォッチを一時停止」→ 時間を止める
  • 「ストップウォッチを再開」→ 続きを進める
  • 「ストップウォッチをリセット」→ クリアする
  • 「ストップウォッチの時間」→ 経過時間を報告
  • 「ストップウォッチの状態」→ 動作中/一時停止中を知らせる
  • 毎分の節目を自動でアナウンス

すべて Livingrimoireスキルクラス の中にまとめています。

そして、次のように有効化します:

ai.add_skill(DiStopWatch())

これで統合は完了です。

ここにスキルコードを貼り付けてください

(このマーカーが、dev.toの記事内であなたのフルのDiStopWatch+Timerコードブロックを差し込む正確な位置です。)

import time

class DiStopWatch(Skill):
    """
    音声操作のためのストップウォッチスキル。
    動作中は、毎分の節目で自動アナウンスします。
    """

    def __init__(self):
        super()__init__()
        self.timer = Timer()
        self.last_announced_minute = 0

    # Override
    def input(self, ear: str, skin: str, eye: str):
        # ear は上流で既に小文字化され、前後の空白も取り除かれています
        if ear == "start stopwatch":
            self.timer.start_timer()
            self.last_announced_minute = 0
            self.setSimpleAlg("Stopwatch started from zero")
            return

        if ear == "pause stopwatch":
            self.timer.pause_timer()
            self.setSimpleAlg("Stopwatch paused")
            return

        if ear == "resume stopwatch":
            self.timer.resume_timer()
            self.setSimpleAlg("Stopwatch resumed")
            return

        if ear == "reset stopwatch":
            self.timer.reset_timer()
            self.last_announced_minute = 0
            self.setSimpleAlg("Stopwatch reset to zero")
            returnif ear == "stopwatch time":
            elapsed = self.timer.get_time_elapsed()
            self.setSimpleAlg(f"経過時間: {elapsed}")
            return

        if ear == "stopwatch status":
            if not self.timer._is_running:
                status = "not running"
            elif self.timer._is_paused:
                status = "paused"
            else:
                status = "running"
                self._check_and_announce_minute()
            self.setSimpleAlg(f"ストップウォッチは {status} です")
            return

        # 実行中は、入力のたびに分の節目を自動チェック
        if self.timer._is_running and not self.timer._is_paused:
            self._check_and_announce_minute()

    def _check_and_announce_minute(self):
        """新しい分が経過したかどうかを確認し、その旨を読み上げます。"""
        current_seconds = self.timer.get_current_seconds()
        current_minute = int(current_seconds // 60)

        if current_minute > self.last_announced_minute and current_minute > 0:
            self.last_announced_minute = current_minute
            minute_word = "minute" if current_minute == 1 else "minutes"
            self.setSimpleAlg(f"{current_minute} {minute_word} 分経過")

    def skillNotes(self, param: str) -> str:
        if param == "notes":
            return "音声操作のストップウォッチ。分ごとに自動で読み上げます"
        if param == "triggers":
            return "start stopwatch, pause stopwatch, resume stopwatch, reset stopwatch, stopwatch time, stopwatch status"
        return "Note unavailable"

class Timer:
    """高精度な計測。冗長性なし。"""

    def __init__(self):
        self._start_time = None
        self._paused_elapsed = 0.0
        self._is_paused = False
        self._is_running = Falsedef start_timer(self):
        self._start_time = time.perf_counter()
        self._paused_elapsed = 0.0
        self._is_paused = False
        self._is_running = True

    def pause_timer(self):
        if self._is_running and not self._is_paused:
            self._paused_elapsed += time.perf_counter() - self._start_time
            self._is_paused = True

    def resume_timer(self):
        if self._is_running and self._is_paused:
            self._start_time = time.perf_counter()
            self._is_paused = False

    def reset_timer(self):
        self._is_running = False
        self._is_paused = False
        self._paused_elapsed = 0.0
        self._start_time = None

    def get_current_seconds(self):
        """経過した総秒数(生値)を取得します。"""
        if not self._is_running:
            return 0

        if self._is_paused:
            return self._paused_elapsed

        return self._paused_elapsed + (time.perf_counter() - self._start_time)

    def get_time_elapsed(self):
        """経過時間を文字列として取得します。"""
        total_seconds = self.get_current_seconds()

        hours = int(total_seconds // 3600)
        minutes = int((total_seconds % 3600) // 60)
        seconds = int(total_seconds % 60)

        parts = []
        if hours > 0:
            parts.append(f"{hours} 時間{'s'} if hours != 1 else ''}")
        if minutes > 0:
            parts.append(f"{minutes}{'s'} if minutes != 1 else ''}")
        if seconds > 0 or not parts:
            parts.append(f"{seconds}{'s'} if seconds != 1 else ''}")

        return " ".join(parts)

これはなぜ重要か

これはストップウォッチの話ではありません。

これはアーキテクチャの話です。

企業のAI:

「タイマーを統合するのに1年必要だ。」

Livingrimoire AI:

「私のキーボードを握って。」

システムがモジュール化されていれば、許可を待つ必要はありません。

ロードマップも待ちません。

四半期ごとのOKR(目標と主要成果)も待ちません。

あとは作るだけです。

コーダーパンクの哲学

Livingrimoireのパターンは、単なるフレームワークではありません。

これはマインドセットです:

  • 小さく作る
  • モジュールとして作る
  • 素早く作る
  • 機能をスキルとして構築する
  • 新しい能力を差し込んでAIを進化させる
  • つなぎコードは作らない
  • モノリスは作らない
  • 企業的なお作法は踏まない

これが、巨人たちに先んじる方法です。

より大きくなることではありません。

より軽くなることです。

自分で試してみたいですか?

Livingrimoireプロジェクトはオープンで、進化し続けています。

リポジトリを確認し、パターンを探求して、自分だけのAIスキルを作り始めてください:

https://github.com/yotamarker/LivinGrimoire

クラスを書けるなら、スキルも書けます。

スキルを書けるなら、AIを進化させられます。

AIを進化させられるなら、あなたはすでに企業のロードマップより先にいます。