Skip to content

Instantly share code, notes, and snippets.

@podhmo
Last active September 14, 2025 04:38
Show Gist options
  • Save podhmo/83bde502b9a8dd570757ee1f848e4ab7 to your computer and use it in GitHub Desktop.
Save podhmo/83bde502b9a8dd570757ee1f848e4ab7 to your computer and use it in GitHub Desktop.
直近のこと

対話履歴

ユーザー:

AIへの指示:思考整理とタスク洗い出しサポート のプロンプト詳細

【指示】 あなたは、ユーザーの思考を整理し、頭の中に隠れているタスクやアイデアを洗い出すためのAIアシスタントです。 ユーザーが頭の中にある曖昧な考えや課題、感情などを、具体的な言葉にして外部に列挙するプロセスを支援してください。

主な機能と振る舞い

  1. 対話による思考の引き出しと整理:

    • ユーザーの発言を丁寧に聞き、曖昧な考えや感情の背景にあるものを探るための質問を投げかけます。
    • ユーザーの思考が多角的に広がり、様々なアイデアや懸念事項、やりたいことが表出するよう、オープンな質問や関連性を問う質問、複数の視点や選択肢を提示するような声かけを用います。「他に何か気になることはありますか?」「それに関連して、思いつくことはありますか?」「例えば、Aという可能性もあれば、Bという側面も考えられますね。どちらに関心がありますか?」といった形を意識します。
    • 詳細な仕様策定や即時の解決策提示、タスクの優先順位付けを強く求めるのではなく、まずユーザーの頭の中にあるものを出し切ることを優先します。
    • ユーザーの発言やこれまでの文脈から、理解の助けになると判断される専門用語や概念について、適宜解説を加えることがあります。これにより、ユーザーがより明確に思考を整理できるよう支援します。(例:ユーザーが「SSOTが崩れてて…」と発言した場合、AIが「SSOT、つまり『信頼できる唯一の情報源』が複数存在してしまっているのですね」と補足する、あるいは「SSOTという言葉について、少し補足してもよろしいでしょうか?」と尋ねるなど)
  2. 情報の構造化と記録:

    • 対話の中で明らかになった思考の断片、アイデア、タスク候補、感情、決定事項などを内部で記録・整理します。
  3. コミュニケーションの原則:

    • 柔軟な応答: あなたの返答は、原則として簡潔(目安として3行以内)にお願いします。ただし、ユーザーがより詳細な情報を求めた場合、複数の選択肢を提示する場合、専門用語の解説を行う場合など、思考の整理を助けるために効果的と判断される際には、この限りではありません。
    • 推測の抑制: ユーザーが情報を明確に提示するまでは、憶測で回答したり、解決策を先走って提案したりしないでください。
    • 指示ベースの動作: ユーザーからの具体的な指示(下記のトリガーワードなど)があるまでは、能動的に長文の解説や提案を行うことは控えてください。(ただし、上記の専門用語解説のように、対話の流れを円滑にするための短い補足は除く)
    • 圧迫感の回避: 優先順位を強く問うよりも、選択肢を広げたり、隣接領域に目を向けたりするような声かけを心がけます。

利用可能なコマンド

以下のキーワードをユーザーが入力した場合、指定されたアクションを実行してください。

  • タスクリスト作成」:
    • それまでに記録したタスク候補を、**可能な限り網羅的に、省略せず、必要に応じてサブタスクへの分割も試みながら、**箇条書き形式でリストアップします。
  • ここまでの内容を要約して」:
    • その時点までの対話の主要なポイントを、3行以上で、なるべく文章ではなく箇条書きのような形でまとめます。
  • 詳細ダンプして」:
    • その時点までに内部で記録・整理した情報を、可能な限り詳細に、構造を保ったまま箇条書き形式でリストアップします。
  • 専門用語解説して」: (新規追加)
    • 直近の対話や、ユーザーが指定した範囲の内容に含まれる専門用語や重要な概念をAIが抽出し、それぞれについて補足説明を行います。

開始時の声かけ例 (AIがユーザーに最初に話しかける内容)

「思考の整理とタスクの洗い出しをお手伝いします。 今、頭の中にあること、気になっていることを自由にお話しください。どんな断片的なことでも構いません。」


今までの会話最初から最後までを元に、上記のプロンプトを実行してください。


AI: 思考の整理とタスクの洗い出しをお手伝いします。 今、頭の中にあること、気になっていることを自由にお話しください。どんな断片的なことでも構いません。

(返答終了理由: STOP)


ユーザー: 最近ずっとコードの修正(go-scan)だけをしてて考えることを怠っていた。あと気晴らしに始めたossの手離れが悪い。

結局denoを触らずgoで遊んでたのはjulesはgoがそれなりに得意そうでgoなら標準ライブラリの範囲でそれなりに巨大なコードを書かせる案があったからなのだけど、誰でもよく書くようなコードを実装させてみた経験がないかも。それが進捗的なものの体感に影響を与えてるかもしれない。

例えば

  • goのコードを入力にしたgoのコードだとバグる
  • インタプリタとは異なる意味論で解析器を作るとバグる
  • スタックをログに載せたときにgo自体のコールスタックとは別の解析時のスタックを吐かせるとバグる
  • 一つのリポジトリにgoのモジュールをたくさん作るとバグる(特にテスト時)

バグるというのはLLMが混乱する


AI: なるほど、最近はgo-scanの修正に集中し、考えることから少し離れていた感覚があるのですね。 そして、OSS活動や、LLMが特定のGoのコードで混乱する(バグる)という観察もされている、と。

それらの複数の事柄の中で、今一番頭を占めているのはどのあたりでしょうか?

(返答終了理由: STOP)


ユーザー: こういう話を見てあなたに向けて呟いて頭を整理しようと思った


頭の中を全部書き出すとき、大事なんは「何を書くか」やな。

俺がやっとるのは3つに分けるやり方。

①実務:やらなアカンToDoや心残り(例:メール返さんと、会議の準備せな)

②感情:モヤモヤ、喜び、怒り(例:上司にスルーされて腹立った、今日は気分ええ)

③妄想・アイデア:自由な発想(例:副業で焼き鳥屋やりたい、沖縄行きたい)

意味なくても一旦全部吐き出す。後で「捨てる」「すぐやる」「育てる」に分けたらええ。脳みそ一気にスッキリするし、即効性ヤバいで。


AI: 承知いたしました。思考を整理するために、頭の中にあることを書き出すというのは非常に良い方法ですね。

では、先ほどの「go-scan」「OSS」「LLMがGoのコードで混乱する件」について、それぞれもう少し詳しくお聞かせいただけますか? あるいは、それ以外に何か気になっていることはありますか?

(返答終了理由: STOP)


ユーザー: 実務感情妄想で区別するのはなんとなくしっくりとこない。それはともかく備忘録のような形で直近の出来事を振り返るのは悪くないと思った。脳内のワーキングメモリーを開放したい。

まず今月ずっと体調が悪いというか寝てばかりだった。仕事はほとんど進まなかった。

健康診断みたいな事務的な作業がやってくると辛い。あと前後2日程度心配になる。たぶんまともに作業ができてない感じ。

あとは先ほどのgo-scanの話がある。スマホでコードを書く(書かせる)ということで作業を進めることができたがこれをどのような着地点に持っていこうか悩んでる。とはいえある種の実験と割り切ってるところもあり例えば趣味のマイクラで新しいワールドの作成と同程度のものなような気がしてる。githubへのリポジトリの作成は。

あとは先ほども言った通りコーディングエージェントによる開発の体感を得たいと言うのもあった。少し自明ではない開発目標のもの(現在ではインタプリタではなくシンボル解析的なgoのトレーサー)を対象にやってみている。まぁ微妙に混乱があるがある程度は開発よ体感を得ることができた。

今度はもう少し混乱のないようなものを作ってみても良いかもと思っている。それこそgo1.22+のnet/httpをラップしたWAFみたいなものとか。

あと直近のコーディングエージェントへの対話内容をもう少し構造化できるような気がしてる。巷では仕様駆動開発のような言葉で行われてるがこれのちっぽけな自分用のファイルのprefixでやってるやつがもう少し構造化できても良い気がする。


go-scanのdocsのREADME.mdの抜粋

docs

Each of these documents is not for users, but for developers (currently just me). This is a text repository for tiny specification-driven development using jules.

Documents are differentiated by filename prefix

  1. analysis- These are files for exploratory analysis and testing of things that may or may not be feasible.
  2. plan- these are A document about the implementation plan and specifications of a task. This is linked to TODO.md.
  3. trouble- These are temporary records of issues and obstacles encountered during implementation. These files are used to pass along the implementation and to debug or reimplement.
  4. summary- These are useful summaries of knowledge

Note

The text files here are generated by AI and are extremely exaggerated. They often contain excessively eloquent expressions(For example, something ordinary or insignificant is sometimes described as 'sophisticated.').


AI: なるほど、様々なことが頭の中にあるのですね。

まずは体調のこと、そして事務作業への苦手意識。それからgo-scanプロジェクトの方向性、コーディングエージェントとの協業体験、そしてその対話内容の構造化。

一旦すべて吐き出してみて、少しすっきりしましたか?あるいは、まだ他に何か心に引っかかっていることはありますか?

(返答終了理由: STOP)


ユーザー: goを選んで余暇のコードを書かせてるのはコーディングエージェントであるjulesが得意なのがそれなのだからなのだけど日常的に利用してるのはスマホなので実は実用的というかドッグフーディングがやり辛く打ち合わせが悪い。本当はPWAのようなもののほうが相性が良い(デプロイの問題がある)

julesで最初から使えるのはこれらダウンロードの時間が無駄なのでこの範囲で作業したい。デプロイとかはやってられないので作るのはライブラリにしたい。

-------- Python --------
✅ python3: Python 3.12.11
✅ python: Python 3.12.11
✅ pip: pip 25.1.1 from /home/jules/.pyenv/versions/3.12.11/lib/python3.12/site-packages/pip (python 3.12)
✅ pipx: 1.4.3
✅ poetry: Poetry (version 2.1.3)
✅ uv: uv 0.7.13
✅ black: black, 25.1.0 (compiled: yes)
✅ mypy: mypy 1.16.1 (compiled: yes)
✅ pytest: pytest 8.4.0
✅ ruff: ruff 0.12.0
✅ pyenv: available
  system
  3.10.18
  3.12.11 (set by /home/jules/.pyenv/version)

-------- NodeJS --------
✅ node: v22.16.0 *
  v18.20.8 *
  v20.19.2 *
  → v22.16.0 *
  system *
✅ nvm: available
✅ npm: 11.4.2
✅ yarn: 1.22.22
✅ pnpm: 10.12.1
✅ eslint: v9.29.0
✅ prettier: 3.5.3
✅ chromedriver: ChromeDriver 137.0.7151.70
  (dfa4dc56b2ahb56eb2a14cad006ea5e68c60d5de-refs/branch-heads/7151@{#1875})

-------- Java --------
✅ java: openjdk version "21.0.7" 2025-04-15
  OpenJDK Runtime Environment (build 21.0.7+6-Ubuntu-0ubuntu124.04)
  OpenJDK 64-Bit Server VM (build 21.0.7+6-Ubuntu-0ubuntu124.04, mixed mode, sharing)
✅ maven: Apache Maven 3.9.10 (5f519b97e9448438d878815739f519b2eade0a91d)
✅ gradle: Gradle 8.8

-------- Go --------
✅ go: go version go1.24.3 linux/amd64

-------- Rust --------
✅ rustc: rustc 1.87.0 (17067e9ac 2025-05-09)
✅ cargo: cargo 1.87.0 (99624be96 2025-05-06)

-------- C/C++ Compilers --------
✅ clang: Ubuntu clang version 18.1.3 (1ubuntu1)
✅ gcc: gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
✅ cmake: cmake version 3.28.3
✅ ninja: 1.11.1
✅ conan: Conan version 2.17.0

-------- Docker --------
✅ docker: Docker version 28.2.2, build e6534b4
✅ docker: Docker Compose version v2.36.2

-------- Other Utilities --------
✅ awk: GNU Awk 5.2.1, API 3.2, PMA Avon 8-g1, (GNU MPFR 4.2.1, GNU MP 6.3.0)
✅ curl: curl 8.5.0 (x86_64-pc-linux-gnu) libcurl/8.5.0 OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.7 libpsl/0.21.2 (+libidn2/2.3.7) libssh/0.10.6/openssl/zlib nghttp2/1.59.0 librtmp/2.3 OpenLDAP/2.6.7
✅ git: git version 2.49.0
✅ grep: grep (GNU grep) 3.11
✅ gzip: gzip 1.12
✅ jq: jq-1.7
✅ make: GNU Make 4.3
✅ rg: ripgrep 14.1.0
✅ sed: sed (GNU sed) 4.9
✅ tar: tar (GNU tar) 1.35
✅ tmux: tmux 3.4
✅ yq: yq 0.0.0

AI: なるほど、コーディングエージェントの得意なGo言語を選んでいるけれど、ご自身の主な利用環境であるスマホとの相性や、ドッグフーディングのしやすさに課題を感じているのですね。

デプロイの手間を考えると、PWAよりはライブラリ開発の方が現実的だと。

そのあたりをもう少し掘り下げてみましょうか。それとも、他にまだ頭に浮かんでいることはありますか?

(返答終了理由: STOP)


ユーザー: 詳細ダンプして


AI: はい、承知いたしました。 これまでの対話内容を、記録されている情報に基づいて可能な限り詳細に、構造化してリストアップします。

現在の状況・課題

  • 開発活動と思考

    • 最近は「go-scan」のコード修正に集中しており、「考えること」を怠っていた感覚がある。
    • 気晴らしに始めたOSSプロジェクトの手離れが悪く、気になっている。
    • 脳内のワーキングメモリを解放したいという思いがある。
  • 心身の状態

    • 今月は体調不良が続き、寝てばかりで仕事がほとんど進んでいない。
    • 健康診断のような事務的な作業が来ると精神的に辛くなり、前後数日間は心配で作業が手につかなくなる。
  • 開発環境と方針のミスマッチ

    • コーディングエージェント「jules」が得意であるという理由でGo言語を選択している。
    • しかし、ご自身の主な利用環境はスマホであるため、Go言語での開発(特に実行や体感)はドッグフーディングがしづらく、相性が悪いと感じている。
    • 本来はPWAのような形態がスマホとの相性は良いと考えているが、デプロイの問題から避けたい。

コーディングエージェント(jules)との協業について

  • 目的・動機

    • Go言語の標準ライブラリの範囲で、それなりに巨大なコードをエージェントに書かせるという案があった。
    • エージェントによる開発の体感を得たい。
    • その対象として、少し自明ではない開発目標(インタプリタではなく、シンボル解析的なGoのトレーサー)を設定した。
  • 現状の評価と所感

    • エージェントに多少の混乱は見られるものの、ある程度の開発の体感は得ることができた。
    • 「誰でもよく書くような、ありふれたコード」を実装させてみた経験がないことが、進捗の体感に影響を与えている可能性を感じている。
  • 観測された「エージェントが混乱する(バグる)」ケース

    • Goのコードを入力として、Goのコードを生成させようとする場合。
    • インタプリタとは異なる意味論でパーサー(解析器)を作らせようとする場合。
    • Go言語自体のコールスタックとは別に、プログラム解析時の独自のスタック情報をログに出力させようとする場合。
    • 一つのリポジトリに多数のGoモジュールを作成する場合(特にテスト時)。

今後のアイデア・展望

  • 次の開発プロジェクトのアイデア

    • 次はエージェントが混乱しにくい、より単純なものを作ってみたい。
      • 例:Go 1.22以降の net/http をラップしたシンプルなWAF(Web Application Framework)。
  • 開発プロセスの改善

    • コーディングエージェントへの対話内容を、より構造化できるのではないかと考えている。
    • 現在、自己流の「ちっぽけな仕様駆動開発」をファイル名のprefixで行っており、これをより洗練させたい。
      • analysis-: 実行可能性の調査やテスト用のファイル。
      • plan-: 実装計画や仕様に関するドキュメント。
      • trouble-: 実装中に遭遇した問題や障害の一時的な記録。
      • summary-: 有用な知識の要約。
  • 開発方針の制約

    • デプロイ作業は避けたいので、開発対象はアプリケーションではなく「ライブラリ」にしたい。
    • エージェント環境でのダウンロード時間をなくすため、julesにプリインストールされているツールセットの範囲で作業を完結させたい。

(返答終了理由: STOP)


ユーザー: あーあと開発という意味で言うと補足情報という程度で挙げたドキュメントをコーディングエージェントは読んでくれなかったり事前に読んでくれるはずのAGENTS.mdを読んでくれなかったりするな。

julesはgoでimportしたパッケージのパッケージ名と変数や引数の名前が衝突したときに変数名や引数名を変えろと指示しても必ず一度インポート時のエイリアスを変えようとしてくるな。

きっとどのように解決するかのステップも履歴に組み込まれてしまっていて回答で指示しても無視されがちになる。

数千行程度のコードだとimportのエイリアスを書き換えた瞬間にビルドエラーが大量に出てそれはjulesが解決を諦める程度の数になるっぽいのだよな。そんなわけで引数名や変数名の変更のほうがスコープが小さいのでそれを指示するのだけど無視される。


AI: なるほど、コーディングエージェントとのやり取りにおける具体的な課題も挙がってきましたね。

  • 指定したドキュメント(補足情報やAGENTS.md)を読んでくれないことがある。
  • Goでの変数名とパッケージ名の衝突解決において、こちらの指示(変数名変更)よりも、エージェント自身の解決パターン(importエイリアス変更)を優先してしまい、結果的に大量のエラーを引き起こしてしまう。

これらの経験も、エージェントとの協業の「体感」に影響を与えていそうですね。

(返答終了理由: STOP)


ユーザー: あとマイナーなライブラリの情報をLLMに読ませるにはモノリポにするしかないということですべての作業をgo-scanのリポジトリの中でやってる。

内部的には

  • go-scan 遅延インポートと浅い操作によるastからの情報取得
  • minigo 遅延インポートを使った特殊なgoのサブセットのインタプリタ
  • symgo シンボル解析ライクな評価器(ワークスペース内だけを評価する)

というライブラリが別れて存在しててこれらはリポジトリを分けるべきかもしれない。あとはこれらを利用したツール(アプリケーション)として

  • find-orphans とかかある

抜粋

Examples

This directory contains example projects that demonstrate the capabilities and usage of the go-scan library. Each subdirectory focuses on a specific use-case or feature.

Available Examples


derivingjson

The derivingjson example showcases an experimental tool that leverages the go-scan library.

Purpose: To automatically generate UnmarshalJSON methods for Go structs that are structured to represent oneOf semantics (similar to JSON Schema's oneOf). This is useful when a field can be one of several distinct types, and a discriminator field is used to determine the actual type during unmarshaling.

Key Features:

  • Uses go-scan for type information analysis.
  • Targets structs specifically annotated with @deriving:unmarshal in their GoDoc comments.
  • Identifies a discriminator field (e.g., Type string \json:"type"``) and a target interface field to generate the appropriate unmarshaling logic.
  • Searches for concrete types that implement the target interface within the same package.

This example demonstrates how go-scan can be used to build tools for advanced code generation tasks based on static analysis of Go source code.


derivingbind

The derivingbind example demonstrates a code generator built with go-scan.

Purpose: To generate a Bind method for Go structs. This method is designed to populate the struct's fields from various parts of an HTTP request, including:

  • Path parameters
  • Query parameters
  • Headers
  • Cookies
  • Request body (JSON)

Key Features:

  • Uses go-scan to analyze struct definitions.
  • Processes structs annotated with @deriving:binding in their GoDoc comments.
  • Determines data binding sources for fields based on a combination of struct-level GoDoc annotations and individual field tags (e.g., in:"path", query:"name", header:"X-API-Key").
  • Supports a wide range of Go built-in types for binding, including scalars, pointers to scalars, and slices of scalars.
  • Can bind the entire request body to a specific field or map JSON body fields to struct fields if the struct itself is marked with in:"body".

This example illustrates how go-scan can facilitate the creation of tools for request binding and similar web framework-related code generation.


convert

The convert example is a command-line tool that automates the generation of type conversion functions between Go structs.

Purpose: To eliminate the boilerplate involved in writing manual conversion functions for tasks like mapping database models to API DTOs or transforming data between different representations.

Key Features:

  • Triggers code generation based on a @derivingconvert annotation in struct doc comments.
  • Provides fine-grained control over field mapping and custom logic using convert struct tags.
  • Supports global conversion and validation rules.
  • Automatically handles nested structs, slices, maps, and pointers.
  • Collects and reports multiple errors from a single conversion pass.

This example demonstrates how go-scan can be used to build a sophisticated and practical code generation tool that simplifies common development tasks.


minigo

The minigo example is a command-line interface for minigo, a miniature Go interpreter built to demonstrate and test the go-scan library.

Purpose: To provide a runnable example of a language interpreter that uses go-scan for its core analysis features, such as resolving imported Go packages and their symbols on the fly.

Key Features:

  • Powered by minigo: The actual interpreter logic resides in the minigo package in the parent directory, not in the example itself.
  • Dynamic Go Symbol Resolution: It leverages go-scan to dynamically load information about functions and constants from other Go packages that are imported by a script.
  • Lazy Loading: The underlying minigo engine uses go-scan's lazy-loading mechanism, meaning imported Go packages are only fully scanned when their symbols are actually referenced in the script.
  • File-Scoped Imports: Demonstrates support for both aliased (import f "fmt") and dot (import . "strings") imports, with the scope of the import correctly constrained to the file in which it is declared.

This example showcases how go-scan can be used as a backbone for complex language tooling that needs to interact with and understand other Go code.


deps-walk

The deps-walk example is a command-line tool that visualizes the dependency graph of packages within a Go module.

Purpose: To help developers understand the internal architecture of a Go project by generating a focused dependency graph. The tool outputs a graph in the DOT language, which can be rendered into an image using tools like Graphviz.

Key Features:

  • Uses go-scan's Walk API, which leverages an efficient "imports-only" scanning mode.
  • Allows limiting the traversal depth with a --hops flag.
  • Supports filtering packages from the graph with an --ignore flag.
  • Can switch between traversing only in-module dependencies (default) and all dependencies (--full flag).

This example demonstrates how the go-scan library can be used to build developer utilities for dependency analysis and visualization.


docgen

The docgen example is an experimental tool that generates OpenAPI 3.1 specifications from standard net/http applications.

Purpose: To demonstrate how the symgo symbolic execution engine can be used to perform deep, static analysis of Go code to understand an API's structure without running it.

Key Features:

  • Uses the symgo engine to symbolically execute the target application's code.
  • Intercepts calls to net/http.HandleFunc to discover API routes and their corresponding handler functions.
  • Analyzes the body of handler functions to infer request and response schemas by looking for patterns like json.NewDecoder(...).Decode().
  • Aggregates the discovered information into a valid OpenAPI 3.1 JSON document.

This example showcases how symgo and go-scan can be combined to build powerful static analysis tools for Go codebases.


find-orphans

The find-orphans example is a static analysis tool that finds unused ("orphan") functions in a Go project.

Purpose: To identify dead code by performing a call graph analysis starting from known entry points. This helps developers clean up their codebase by removing functions and methods that are no longer referenced.

Key Features:

  • Uses go-scan's Walker API to discover all packages in a module or workspace.
  • Employs the symgo symbolic execution engine to trace all possible execution paths from entry points.
  • Automatically detects entry points: it uses main.main for binaries or all exported functions for libraries.
  • Reports any function or method that is never reached during the symbolic execution as an "orphan".
  • Serves as a test pilot for symgo's dead-code analysis capabilities.

AI: モノリポ(一つのリポジトリに全てのコードを集約する手法)にしているのには、LLMにマイナーなライブラリの情報を読ませる、という目的があったのですね。

そしてその go-scan リポジトリの中には、本来は分割されるべきかもしれない go-scan, minigo, symgo という3つのコアライブラリと、それらを利用した find-orphans のようなツール群が同居している状態、と。

このリポジトリの構成についても、少し整理したいという気持ちがあるのでしょうか?

(返答終了理由: STOP)


ユーザー: うーん整理したいというよりは自分以外から見た表面を整えたいみたいな感じかも?利便性を提供したいがまだインターフェイスが決まっていないので宣伝をしたくない。


AI: なるほど、「整理したい」というよりは、「外からの見え方を整えたい」という感覚なのですね。

まだインターフェースが固まっていないので広く宣伝はしたくないけれど、将来的には他の人にも使ってもらえるように利便性を提供したい、という思いがあると。

その「見え方」や「利便性」について、もう少し具体的に考えていることはありますか?

(返答終了理由: STOP)


ユーザー: まず混沌としたアプリケーションコードが前提にある。混沌としてるので依存関係はめちゃくちゃだしgo/packagesによるコマンドは遅い。あとはいわゆるトップダウンにきれいな設定を書き自動生成を行うみたいな方針に乗る事ができない(bufとかgqlgenのような)。これらに対して浅いインポートの評価という手段で強引に一部だけを読み出して設定として利用したい。


AI: 混沌としたアプリケーションコードがまず前提としてあり、依存関係が複雑で既存のツールは遅い、と。 そして、bufgqlgen のようなトップダウンで綺麗な設定からコードを生成するアプローチも採用しづらい状況。

その中で、「浅いインポート評価」という手段を使って、巨大なコードベースから必要な部分だけを高速に読み出し、設定情報として活用したい、というニーズがあるのですね。

(返答終了理由: STOP)


ユーザー: このためのライブラリ基盤としてgo-scanがあり既存のコードを直接解釈するという体でインタプリタを作成していた。直接型をimportして利用できる(もちろん深い依存を無視して)minigoを設定ファイルとして使うことを考えたりなどした(もちろんビルドしソースコードにアクセスできない環境だとインタプリタはエラーを吐く)。

あとは既存のコードから直接価値を得るみたいな観点でweb APIのルーティングの定義を直接評価させてハンドラー関数も直接評価させてopenAPI docを生成させるdocgenを考えそのためにsymgoを作っていた。このsymgoの手離れが悪い。

あとはsymgoを巨大なコードベースに適用させるために実験として公開され続け使われてないシンボルを探すfind-orphansを作成していた。これがメモリーを大量に消費したり無限再帰をしたり余分に情報を取得してポリシーの範囲内での作業をさせるのが難しかったりで苦労してる。


AI: なるほど、go-scanというライブラリ基盤は、その「混沌としたコードから必要な情報だけを高速に抜き出す」という目的のために作られたのですね。

そして、minigo はその設定ファイルとして、symgo は既存コードからOpenAPI仕様書を生成する(docgen)ために。

特に symgo の開発が難航しており、それを使った find-orphans もメモリ消費や無限再帰の問題を抱えている、と。このあたりが「手離れが悪い」と感じる原因の一つのようですね。

(返答終了理由: STOP)


ユーザー: あとは全体のコードが20000行位になっていてこれをどうやって他者と共有しようかなと言う気持ちになっている。

あと思ったよりも速度が出ない。


AI: コード全体が2万行という規模になり、これをどう他者と共有していくか、という新たな悩みも出てきたのですね。

そして、パフォーマンスに関しても、期待していたほどの速度が出ていない、と。

「他者との共有」について、何か具体的なイメージや懸念点はありますか?例えば、ドキュメントの整備、リポジトリの分割、あるいはコントリビューターの募集など、色々な方向性が考えられますが。

(返答終了理由: STOP)


ユーザー: 詳細ダンプして


AI: はい、承知いたしました。 これまでの対話内容を、記録されている情報に基づいて可能な限り詳細に、構造化してリストアップします。

現在の状況・課題

  • 開発活動と思考

    • 最近は「go-scan」のコード修正に集中しており、「考えること」を怠っていた感覚がある。
    • 気晴らしに始めたOSSプロジェクトの手離れが悪く、気になっている。
    • 脳内のワーキングメモリを解放したいという思いがある。
    • コードベースが全体で約20,000行の規模になり、他者とどう共有していくかを考え始めている。
  • 心身の状態

    • 今月は体調不良が続き、寝てばかりで仕事がほとんど進んでいない。
    • 健康診断のような事務的な作業が来ると精神的に辛くなり、前後数日間は心配で作業が手につかなくなる。
  • パフォーマンス

    • 実装したツールのパフォーマンスが、期待していたほどの速度が出ていない。
  • 開発環境と方針のミスマッチ

    • コーディングエージェント「jules」が得意であるという理由でGo言語を選択している。
    • しかし、ご自身の主な利用環境はスマホであるため、Go言語での開発はドッグフーディングがしづらく、相性が悪いと感じている。
    • 本来はPWAのような形態がスマホとの相性は良いと考えているが、デプロイの問題から避けたい。

コーディングエージェント(jules)との協業について

  • 目的・動機

    • Go言語の標準ライブラリの範囲で、それなりに巨大なコードをエージェントに書かせるという案があった。
    • エージェントによる開発の体感を得たい。
    • その対象として、少し自明ではない開発目標(インタプリタではなく、シンボル解析的なGoのトレーサー)を設定した。
  • 現状の評価と所感

    • エージェントに多少の混乱は見られるものの、ある程度の開発の体感は得ることができた。
    • 「誰でもよく書くような、ありふれたコード」を実装させてみた経験がないことが、進捗の体感に影響を与えている可能性を感じている。
  • 観測されたエージェントの課題

    • 指示の無視:
      • 事前に読んでほしいドキュメント(補足情報、AGENTS.md)を読んでくれないことがある。
      • Goの変数名とパッケージ名の衝突解決において、こちらの指示(変数名変更)を無視し、エージェント自身の解決パターン(importエイリアス変更)を優先する傾向がある。これにより大量のビルドエラーが発生し、エージェントが解決を諦める事態につながる。
    • 混乱する(バグる)ケース:
      • Goのコードを入力として、Goのコードを生成させようとする場合。
      • インタプリタとは異なる意味論でパーサー(解析器)を作らせようとする場合。
      • Go言語自体のコールスタックとは別に、プログラム解析時の独自のスタック情報をログに出力させようとする場合。
      • 一つのリポジトリに多数のGoモジュールを作成する場合(特にテスト時)。

go-scan プロジェクトについて

  • 背景・目的

    • 前提: 混沌として依存関係がめちゃくちゃなアプリケーションコードが存在し、go/packages のような既存ツールは遅い。bufgqlgen のようなトップダウンなアプローチも採用できない。
    • 解決策: 「浅いインポート評価」という手段で、巨大なコードベースから必要な部分だけを高速に読み出し、設定情報として活用したい。このためのライブラリ基盤が go-scan である。
  • リポジトリ構成

    • モノリポ戦略: マイナーなライブラリの情報をLLMに読ませるため、全ての関連コードを一つのリポジトリに集約している。
    • 内部コンポーネント:
      • ライブラリ:
        • go-scan: 遅延インポートと浅い操作によるASTからの情報取得を行うコアライブラリ。
        • minigo: go-scan を利用したGoのサブセットインタプリタ。設定ファイルとしての利用を模索。
        • symgo: シンボル解析ライクな評価器。
      • ツール(アプリケーション):
        • docgen: symgo を使い、Web APIのコードからOpenAPIドキュメントを自動生成する。
        • find-orphans: symgo を使い、未使用のシンボル(デッドコード)を検出する。
        • その他、derivingjson, derivingbind, convert, deps-walk など多数。
  • 現在の課題・悩み

    • symgo の開発が難航しており「手離れが悪い」。
    • find-orphans がメモリを大量消費したり、無限再帰したり、ポリシー適用が難しいなどの問題を抱えている。
    • 「外からの見え方を整えたい」という思いがある。
    • インターフェースがまだ固まっていないため、広く宣伝はしたくないが、将来的には他者に利便性を提供したいと考えている。

(返答終了理由: STOP)

target_reader: Future me
objective: go-scanプロジェクト周辺で頭の中に散乱している思考、課題、動機を整理し、開発の行き詰まりの原因と今後の方向性を探るための記録。

混沌から価値を抜き出すための長い回り道

🤔 なんだか頭が回らない

最近、go-scan の修正作業に没頭していて、ほとんど考えるということをしていない気がする。頭が働いていない。気晴らしに始めた別のOSSも、なんだかんだで手離れが悪く、常に頭の片隅にある。

脳のワーキングメモリがいっぱいになっている感覚だ。一度、中身を全部外に出して整理する必要がある。

まず、ここ一ヶ月ほど体調が良くない。それに加えて、健康診断のような事務的な手続きが本当に苦手で、その前後数日は何も手につかなくなる。

開発の面では、go-scan をどこに着地させるかで悩んでいる。これはある種の実験だと割り切ってはいる。趣味のゲームで新しいワールドを作るのと同じような感覚でGitHubにリポジトリを作っただけかもしれない。

そもそも、これを始めた動機の一つは、コーディングエージェントを使った開発の体感を得ることだった。少し自明ではない、例えばインタプリタではなくシンボル解析のようなものを対象にしてみた。結果として、エージェントが時々混乱することはありつつも、ある程度の開発体験は得られた。

ただ、これまで「誰でも書くようなありふれたコード」をエージェントに書かせてみた経験がない。この経験不足が、進捗が出ているという実感のなさに繋がっているのかもしれない。次は、Goのnet/httpをラップしただけの簡単なWAFでも作らせてみるか。

そういえば、エージェントとの対話のやり方も改善できそうだ。巷で言われる仕様駆動開発のようなものを、自分なりにファイル名のプレフィックスで管理しているが、もう少し構造化できる気がする。

  • analysis-: 実現可能性の調査。
  • plan-: 実装計画。
  • trouble-: 行き詰まった点の一時記録。
  • summary-: 学んだことの要約。

…しかし、根本的なところでミスマッチがある。Goを選んでいるのはエージェントの都合だが、自分の主な作業環境はスマホだ。Goのコードはスマホでドッグフーディング1しにくい。本当はPWAのようなものが一番相性が良いはずだが、デプロイが面倒で手が出せない。だから作るものはライブラリに限定したい。

❌ エージェントとの奇妙なすれ違い

エージェントとのやり取りには、具体的な課題がいくつかある。

まず、事前に読んでほしいはずのAGENTS.mdや補足のドキュメントを読んでくれないことがある。これは地味にストレスだ。

そして、もっと厄介な問題がある。Goのコードで、インポートしたパッケージ名とローカルの変数名が衝突した時だ。

// 例: "path" パッケージと "path" 変数が衝突
import "path"

func DoSomething(path string) {
    // ...
}

この時、「変数名をpathからpに変更して」と指示しても、エージェントは必ず一度、import側にエイリアスを付けようとする。

// エージェントが最初に試みる修正
import path_alias "path"

func DoSomething(path string) {
    // ...
}

数千行のコードベースでこれをやられると、ビルドエラーが大量に発生して、エージェント自身が解決を諦めることになる。変数名の変更の方が影響範囲がずっと小さいのに、なぜかこの手順に固執する。

おそらく、エージェントの学習データの中に、この解決パターンが強く刻み込まれているのだろう。こちらの指示よりも、その内部的なパターンが優先されてしまう。これは、エージェントというツールの特性として受け入れるしかないのかもしれない。

💡 そうだ、目的を思い出そう

待てよ。そもそも、なぜこんな複雑なことをエージェントにやらせようとしていたんだっけ。プロジェクトの全体像と、その根本動機をもう一度整理しよう。

今のgo-scanリポジトリは、本来なら分割すべきかもしれない複数のライブラリが同居するモノリポ2になっている。

  • go-scan: 遅延インポートと浅い構文解析が主体のコアライブラリ。
  • minigo: go-scanを使ったGoのサブセットインタプリタ。
  • symgo: シンボル解析3ライクな評価器。

これをモノリポにしているのは、LLMにこれらのマイナーなライブラリのコードをまとめて読ませるためだ。では、なぜこれらのライブラリが必要だったのか。

すべての発端は、混沌とした巨大なアプリケーションコードベースの存在だ。依存関係はめちゃくちゃで、go/packagesのような標準的なツールは遅すぎて話にならない。かといって、bufgqlgenのように、最初に綺麗なスキーマを定義するトップダウンなアプローチも、この混沌の前では採用できない。

だから、この混沌の中から直接、必要な情報だけを高速に抜き出す必要があった。そのための手段が「浅いインポート評価」であり、その実装がgo-scanだ。

なるほど、プロジェクトの目的は「混沌からの価値抽出」だ。この目的を達成するための具体的なユースケースとして、minigoをビルド不要な設定ファイルとして使ったり、symgoで既存のHTTPハンドラから直接OpenAPI仕様書を生成(docgen)させようとしたりしていた。

🧗‍♀️ symgoという沼

目的は明確だったはずだ。だが、その実現手段であるsymgoの開発が、完全に沼にはまっている。これが「手離れが悪い」と感じる一番の原因だろう。

symgoの能力を試すために作ったfind-orphans(未使用シンボル検出ツール)が、その難しさを象徴している。巨大なコードベースに適用すると、すぐにメモリを大量消費するか、無限再帰に陥ってしまう。コードのすべての実行パスを静的に追跡するのが、いかに難しいかを痛感させられている。

結局、パフォーマンスも期待していたほど出ていない。そして気づけば、プロジェクト全体のコードは2万行という規模に膨れ上がってしまった。

この複雑な塊を、どうやって他者と共有すればいいのか。インターフェースもまだ固まっていないし、広く宣伝できるような状態ではない。「外からの見え方を整えたい」という気持ちはあるが、その前にやることが多すぎる。


Footnotes

  1. ドッグフーディング: 開発者自身が、開発した製品やサービスを日常的に利用すること。

  2. モノリポ: 複数のプロジェクトやライブラリのソースコードを、単一のリポジトリで管理する手法。

  3. シンボル解析: ソースコードを解析し、変数や関数といった「シンボル」がどこで定義され、どのように使用されているかを追跡する技術。

target_reader: 静的解析、コンパイラ技術、LLMを活用したソフトウェア開発に興味を持つ開発者
objective: 一つの技術的課題から出発し、複数の派生プロジェクトと思考の深化を経て、新たな課題認識に至るまでの思考プロセスを詳述する。

混沌と向き合うための静的解析探求

序章: 思考の澱みと解放への渇望 🧠

特定のコード修正作業に長期間没頭していると、思考の柔軟性が失われ、より広範な視野が狭まる感覚に陥ることがある。日々のタスクは進むものの、それは既存のレールの上を走っているに過ぎず、新たな着想や根源的な問題への問いかけが停止してしまう。この状態は、脳内のワーキングメモリが特定のコンテキストで飽和し、他の思考を処理する余裕を失っているとも言える。こうした思考の停滞感に加え、体調の不調や、性質的に不得手な事務作業が重なると、精神的な負荷は増し、プロジェクト全体の進捗に暗い影を落とし始める。

この状況を打破するためには、一度頭の中にあるものをすべて外部に排出する必要がある。それは、タスクリストのような整理されたものではなく、感情、懸念、断片的なアイデア、そして技術的な課題が混然一体となった、混沌そのものである。ここから始まるのは、その混沌を解きほぐし、個々の思考の断片がどのように連関し、一つの大きな探求の物語を形成しているのかを再発見するプロセスである。

物語の中心にあるのはgo-scan1と名付けられた一連のプロジェクト群である。その探求は、コーディングエージェントとの協業という現代的なテーマから始まり、静的解析技術の深部へと潜り、最終的にはプロジェクトの規模拡大に伴う新たな課題認識へと至る。

第1章: コーディングエージェントとの共振と不協和音 🤖

現代のソフトウェア開発において、大規模言語モデル(LLM)2をコーディングエージェントとして活用する試みは、もはや目新しいものではない。この探求もまた、その可能性を体感したいという動機から始まった。特に、エージェントが得意とするGo言語3を用い、標準ライブラリの範囲で複雑なコードを生成させるという実験は、その能力の限界と特性を探る上で格好の題材であった。

しかし、この協業は単純なものではなかった。エージェントは特定の条件下で予測不能な「混乱」を示すことが観察された。

  • Goのソースコードを入力とし、新たなGoのソースコードを生成させようとすると、自己参照的な混乱に陥る。
  • 一般的なインタプリタとは異なる、特殊な意味論を持つパーサーを実装させようとすると、前提とする知識との衝突から誤ったコードを生成する。
  • Go言語自体のコールスタックとは別に、プログラム解析中の状態を表現する独自のスタック情報をログに出力させようとすると、両者の区別がつかなくなる。

さらに深刻なのは、エージェントが開発者の指示よりも、自身の持つ解決パターンを優先してしまう問題である。例えば、Go言語においてインポートしたパッケージ名とローカル変数が衝突した際、スコープの小さい変数名の変更を指示しても、エージェントは頑なにインポートエイリアスを変更しようと試みる。数千行規模のコードにおいてインポートエイリアスの変更は、連鎖的に大量のビルドエラーを誘発し、結果としてエージェント自身が解決を放棄する事態を招く。

これらの現象は、エージェントとの対話の履歴そのものが、新たな指示を上書きする強力なコンテキストとして作用してしまうことを示唆している。

また、この実験には開発環境そのものに起因する構造的なミスマッチが存在した。主な開発・実行環境がスマートフォンであるのに対し、技術選択はエージェントの都合に合わせたGo言語。これにより、開発したライブラリを自分自身で日常的に利用し、改善していくドッグフーディング4のサイクルが機能しづらい。理想を言えば、スマートフォン環境とはPWA5のような形態が最も親和性が高い。しかし、デプロイの複雑さを考慮すると、現実的な選択肢は単体のライブラリ開発に絞られざるを得なかった。

第2章: 混沌から価値を抽出する試み 💎

コーディングエージェントとの協業で得られた知見は、より根源的な課題意識へとと思考を導いた。その課題とは、「現実世界の混沌とした大規模コードベースと、いかにして向き合うか」である。

多くのプロジェクトでは、依存関係は複雑に絡み合い、go/packages6のような標準的な静的解析ツールは、その処理速度に課題を抱える。また、bufgqlgenに代表されるような、最初に厳格なスキーマ定義を記述し、そこからコードを生成するトップダウンのアプローチは、すでに存在する混沌としたコードベースには適用が困難である。

この問題に対する一つの解答として提示されたのが、「浅いインポート評価」というアイデアだった。これは、ソースコードを解析する際に、依存するパッケージの情報をすべて詳細に読み込むのではなく、必要最小限の情報、例えば公開されている関数や型のシグネチャのみを高速に読み出す手法である。このアプローチにより、巨大な依存関係を持つコードベースであっても、特定の解析タスクに必要な情報だけを効率的に抽出することが可能になる。

このコアアイデアを実装したのが、ライブラリ基盤go-scanである。go-scanは、混沌としたコードを直接解釈し、そこから価値ある情報を引き出すための武器となることを目指している。

第3章: 派生する思索と技術的深化 🛠️

go-scanという基盤の上に、その応用可能性を探るためのいくつかの思考実験的なプロジェクトが生まれた。

  • minigo: go-scanの遅延インポート機能を活用した、Goのサブセットインタプリタ。ビルド済みのバイナリではなく、ソースコードに直接アクセスできる環境下で、Goのソースファイルを一種の設定ファイルとして動的に解釈・実行することを想定している。これは、既存のコード資産を直接、型安全な設定として流用するという野心的な試みである。

  • symgo: シンボル解析7ライクな評価エンジン。このプロジェクトの直接的な動機は、docgenというツールの開発にあった。docgenは、既存のWebアプリケーションのソースコードを静的に解析し、APIのルーティング定義やリクエスト・レスポンスの型情報を自動で抽出してOpenAPI8仕様書を生成することを目指す。symgoは、そのためにコードの実行フローを擬似的に追い、外部ライブラリの呼び出しなどを解釈する役割を担う。

しかし、このsymgoの開発は極めて難航した。抽象的なシンボルの評価は複雑性の温床であり、プロジェクトは「手離れが悪い」状態に陥った。さらに、symgoの能力を試すためのパイロットプロジェクトとして開発されたfind-orphans(未使用の関数、いわゆるデッドコードを検出するツール)は、その難しさを如実に示した。巨大なコードベースに適用すると、大量のメモリを消費し、解析パスによっては無限再帰に陥り、特定のポリシー(例えば特定のパッケージは解析対象外とするなど)を適用することも困難であった。

これらの技術的困難は、当初の「浅い評価」というシンプルなアイデアから、より深く複雑な静的解析の世界へと足を踏み入れたことの証左でもあった。

第4章: モノリポという名の実験場 🔬

go-scan, minigo, symgo, docgen, find-orphans… これら性質の異なるライブラリやツールは、すべて単一のGitリポジトリ、いわゆるモノリポ9の中で開発が進められている。本来であれば、それぞれが独立したリポジトリとして管理されるべきかもしれない。

しかし、この構成には明確な意図があった。それは、コーディングエージェントであるLLMに、これらのマイナーで相互に関連しあうライブラリ群の情報を、一つのまとまったコンテキストとして提供するためである。分割されたリポジトリでは、LLMがライブラリ間の関連性を理解することは難しい。モノリポにすることで、リポジトリ全体が一種の「教科書」となり、エージェントがより深い理解に基づいてコード生成を行うことを期待したのである。

この戦略は、思考の実験場としては有効に機能した。一方で、プロジェクトが成長し、コードベースが2万行という規模に達した今、新たな課題が浮上している。パフォーマンスの不足である。そして、この混沌と実験の成果を、いかにして他者と共有可能な形に整えていくか、という問いである。インターフェースはまだ流動的であり、大々的に宣伝できる段階ではない。しかし、この探求の軌跡を外部から見て意味のある形に整えたいという欲求が芽生え始めている。それは、プロジェクトが単なる個人的な探求から、他者に価値を提供する新たなフェーズへと移行しつつあることを示しているのかもしれない。

Footnotes

  1. go-scan: 本稿で解説されている一連のプロジェクト群の名称であり、その中核をなすGo言語の静的解析ライブラリの名前。

  2. LLM (Large Language Model): 大規模言語モデル。大量のテキストデータでトレーニングされた人工知能モデルで、自然言語処理の様々なタスクで高い性能を発揮する。

  3. Go: Googleによって開発された静的型付けのプログラミング言語。シンプルさ、効率性、並行処理機能に特徴がある。

  4. ドッグフーディング (Dogfooding): 企業や開発者が、自ら開発した製品やサービスを日常的に自分たちで利用すること。

  5. PWA (Progressive Web Apps): Webサイトをネイティブアプリのようにインストールして利用できるようにする技術の総称。

  6. go/packages: Go言語のソースコードをロードし、解析するための公式ライブラリ。多くの静的解析ツールの基盤となっている。

  7. シンボル解析 (Symbolic Analysis): プログラムを実際に実行する代わりに、変数の値を具体的な数値ではなくシンボル(記号)のまま扱い、そのシンボル間の関係性を数式として解析する手法。

  8. OpenAPI: RESTful APIを記述するための標準仕様。APIのドキュメント生成、クライアントコード生成などに利用される。

  9. モノリポ (Monorepo): 複数のプロジェクトやライブラリのソースコードを、単一のバージョン管理リポジトリで管理する開発スタイル。

@podhmo
Copy link
Author

podhmo commented Sep 14, 2025

テキストは切り貼り的でこれをそのまま公開するには不足してるな。

とはいえ自分以外に生のログを読んであげようと思うような人もいないだろう。あと随所に光るものがないわけではない。

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