AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
大学ヨット部の反省会のための、複数艇GPX航跡リプレイ・注釈共有ツール。
Translation pending
Developer toolsTypeScript · CSSGitHub @happiitsumo-bitOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗id: proj:sailvlog type: project name: sailvlog(反省会リプレイ) aliases: [反省会リプレイ・デバッガ, 反省会リプレイ, セイルブイログ] summary: ヨット部の反省会のために、複数艇の GPX を同じ時間軸で再生し、タイムラインに注釈を残して部内・部外へ共有する Web アプリ status: active part_of: area:dev uses: ['tool:nextjs', 'tool:vercel', 'tool:render', 'tool:neon', 'tool:express', 'tool:prisma', 'tool:postgresql', 'tool:docker', 'tool:github-actions', 'tool:codex-cli', 'tool:claude-code'] provides:
大学ヨット部の反省会を、記憶とホワイトボードから「航跡データ」へ置き換える。 複数艇のGPXを取り込み、同じ時間軸で再生し、気づいた瞬間にタイムラインへ注釈を残して部内で共有する。
[ここにデモGIF/スクリーンショットが入ります — demo-director 作業待ち。挿入までは /sessions/[id] を実際に開いて確認してください]
このリポジトリはもともと「セーラー向けナレッジシェアSNS」(記事・Q&A・フィード・学習コース)として作られていましたが、**「機能を寄せ集めただけで、誰の何の課題を解いているか説明できない」**という自己診断(v1批判)を経て、v3としてピボットしました。
v3が解くのは1つだけです。大学ヨット部の週次反省会で、艇のGPS航跡を並べて見ながら「あのタックはどうだった」を議論し、その気づきを次の代へ引き継ぐこと。機能を足すより、この1本の体験を最後まで太くすることを優先しています。
ピボットの意思決定の経緯は以下に記録されています。
docs/dev-org/PRD.md — 何を作り、何を作らないか(企画の正本)docs/dev-org/GATES.md — 各工程の人間承認の記録docs/dev-org/ARCH.md — 技術設計とADRdocs/dev-org/TASKS.md — 実装タスクの分解と検証記録(2026-08-02 までの履歴。新しいタスクと進捗は GitHub Issue が正本。AGENTS.md の「正本の場所」)/sessions/new → /sessions/[id])/handbook)/p/[slug] が発行される。非公開の注釈・編集UIは一切露出せず、OGP(unlistedはnoindex)にも対応(本番は稼働中だが、/p/[slug]の公開URLは当面部内限定の運用としており外部へは配布していない — 詳細は下記「デプロイについて」)/sessions/[id] の再生画面で「公開する」ボタン(uploader本人 または Team adminにのみ表示)を押す/p/[slug])が発行され、ヘッダのボタンが「公開URLをコピー」に切り替わる。/sessions 一覧・再生画面には「公開中」(public)/「リンク限定」(unlisted)のチップが表示される| 領域 | 技術 | 選定理由 |
|---|---|---|
| Frontend | Next.js 14 (App Router) / React / TypeScript | 型安全なままSSR/CSRを使い分けられ、部内限定〜将来の公開ページ追加まで1リポジトリで完結させたかった |
| 描画 | Canvas(命令的描画・自前実装) | 複数艇×数千点のリプレイをフレーム落ちなく描く要件に対し、汎用地図ライブラリより制御しやすいと判断(docs/dev-org/ARCH.md のADR参照) |
| Backend | Node.js / Express / TypeScript | 認証・チーム管理などv1の基盤をそのまま引き継げる構成 |
| DB | PostgreSQL / Prisma ORM | GPX由来の時系列データ(JSONB)とリレーショナルなチーム/権限モデルを1つのDBで両立 |
| 開発環境 | Docker / Docker Compose | 「新規メンバーが docker compose up だけで動かせる」を優先し、ローカルのNode/PostgreSQLバージョン差異を吸収 |
| CI | GitHub Actions | pushのたびにbackend/frontendのテスト・型チェック・ビルドを自動実行(後述) |
| 新規依存 | ゼロ(GPXパース・リプレイエンジンとも自前実装) | 「新技術予算を将来のPhaseのために温存する」という設計方針(ARCH.md §1) |
前提: Docker / Docker Compose が使えること。
git clone https://github.com/happiitsumo-bit/sailvlog.git
cd sailvlog
cp .env.example .env # 値はローカル用のデフォルトのままでOK
docker compose up -d
起動後:
| サービス | URL |
|---|---|
| Frontend | http://localhost:3001 |
| Backend API | http://localhost:8001 |
| PostgreSQL | localhost:5433(コンテナ間は db:5432) |
ポート番号に注意:
docker-compose.ymlはホスト側を3001/8001/5433にマッピングしています(コンテナ内部はそれぞれ3000/8000/5432)。.env.exampleのNEXT_PUBLIC_API_URLも8001前提です。
初回のみ、コンテナ内の依存関係が package.json と食い違っていることがあります(下記Q&A参照)。その場合は:
docker compose exec backend npm install
動作確認:
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3001/login # → 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8001/api/health # → 200
/api/teams は 2026-07-26 から認証必須になったため、未認証の curl では 401 が返ります(死活の確認には本番監視と同じ /api/health を使います)。
重要(2026-07-28 更新): backendのテストは ホスト側から実行します。
docker compose exec backend npm testは意図的に失敗する設計になりました(理由は下の「テスト運用のルール」参照)。
# backend(Jest。DBはdocker-composeのdbサービスをホストの5433経由で使用)
cd backend && npm test
# frontend(Vitest。GPX/リプレイエンジンの純関数テスト)
cd frontend && npm test
# frontendの型チェック・ビルド確認
cd frontend && npx tsc --noEmit && npm run build
通る条件は、型チェック(npx tsc --noEmit)がエラー0、テストが全件成功、npm run build が成功です(2026-10-02 の CI では10ルート = /, /handbook, /login, /register, /sessions, /sessions/[id], /sessions/new, /p/[slug], /teams, /_not-found)。
テストの件数のベースライン(下回ったら未完成)は AGENTS.md の「検証コマンドとベースライン」を正本とし、README には書きません。
TRUNCATE するため、2つのjestプロセスが互いのデータを消し合います。CI・ローカルとも1本ずつ実行してくださいdocker compose exec backend npm test は使わない。 以前はコンテナの DATABASE_URL(=開発DB)が使われ、テストのたびに開発データが消えていました。現在は .env.test が必ず優先されるよう修正済みで、その結果コンテナ内からはテストDBに到達できず失敗します(安全側の設計)export DATABASE_URL=<本番> した状態で npm test を叩くと本番が全テーブル消去されうるため、接続先ホストとDB名の二重ガードで中断するようにしてあります(localhost/127.0.0.1/db 以外、または _test で終わらないDB名は拒否).skip で隠さない。 原因を特定して直します(過去に supertest の一時サーバ生成レースで約1/2の確率で落ちる状態を根絶した経緯があります。詳細は docs/dev-org/TEST-PLAN.md)GitHubにpushすると .github/workflows/test.yml が同じ内容(backendジョブ + frontendジョブ)を自動実行します。
/register でアカウント作成 → /login/sessions/new で複数艇のGPXファイル(1艇1ファイル)をまとめて選択し、タイトル・チームを入力して取込/sessions の一覧からセッションを開く(/sessions/[id])と、全艇の航跡が同じ時間軸で再生されるGPS収録そのものの手順(Geo Trackerの設定・出艇前チェックリスト等)は /handbook にまとまっています。
実装・検証の過程で実際に踏んだ罠を記録しています(一次ソース: docs/dev-org/TASKS.md の「発見事項」)。
Q. GPXを取り込んだのに保存できない/エラーが出る A. 以下のいずれかに該当するとその艇のGPXだけ拒否されます(意図的なバリデーション)。1本でも拒否されると保存ボタン全体が無効化されます。
trkpt に緯度・経度・時刻のいずれかが欠落しているtrkpt が0件、または1点しかない該当ファイルだけをGeo Tracker等で録り直すか、そのファイルを除いて残りの艇だけで取り込んでください。
Q. GPSロガー(Geo Tracker)の設定がわからない
A. /handbook(収録ハンドブック)に設定手順・出艇前チェックリスト・取込手順をまとめています。特に「記録間隔を1〜2秒にする」「位置情報の許可を『常に許可』にする」の2点を間違えると、記録が途中で止まったり間隔が粗くなり反省会での議論に耐えません。
Q. 部外向けの公開URLはありますか
A. 機能としては実装済みで、本番でも動作します。/sessions/[id] の「公開する」ボタンから昇格すると、認証不要で開ける読み取り専用ページ /p/[slug] が発行されます(手順は上記「部外向け共有(公開ビュー)の使い方」参照)。ただし現状は ③Quality Gate 未通過のMajor課題が残っているため、/p/[slug] の公開URLは部内利用に留め、外部(他大学・部外者)へは配布しない運用制約が敷かれています(詳細は docs/dev-org/GATES.md ③、および後述「デプロイについて」参照)。
Q. 「公開をやめる」を押した後、同じURLは見られますか
A. 見られません。取り消し後は同じスラッグへのアクセスが404になります(存在しないスラッグと同じレスポンス)。再度公開すると別の新しいURLが発行され、取り消し前のURLが復活することはありません(docs/dev-org/TASKS.md T-34のE2E検証で確認済み)。
Q. 公開ビューに部内の反省会メモや部内ナビゲーションが漏れませんか A. 漏れません。注釈は昇格時に選んでチェックしたものだけがAPIレスポンス・DOMの両方に出ます(既定は全注釈非公開)。公開ビューはログインリンクや部内タブなどのナビゲーションも表示しない専用レイアウトです(T-33検証で確認済み)。
Q. docker compose exec backend npm test が Cannot find module 'pg' で落ちる
A. docker-compose.yml の backend は ./backend:/app に加えて /app/node_modules を匿名ボリュームとして固定しているため、イメージビルド後に package.json へ依存を追加しても、コンテナを再ビルドするまで反映されません。次のコマンドで復旧します。
docker compose exec backend npm install
Q. frontendコンテナで package.json や設定ファイルを編集したのに反映されない
A. docker-compose.yml の frontend は frontend/src と frontend/public だけをbind mountしており、package.json/vitest.config.ts 等はイメージビルド時点の内容で固定されています。編集を反映するには次のいずれかが必要です。
docker compose cp frontend/package.json frontend:/app/package.json
docker compose exec frontend npm install
# vitest.config.ts 等も同様に cp が必要
または docker compose up -d --build frontend でイメージごと作り直してください。
Q. NEXT_PUBLIC_API_URL を変更したのに反映されない
A. NEXT_PUBLIC_* はNext.jsのビルド時に埋め込まれる値です。next start(本番モード)で環境変数だけ変えても反映されません。値を変えたら npm run build からやり直してください(このリポジトリの開発時は next dev を使っているため通常は意識不要です)。
Q. docker compose exec backend npm test を並列実行するとまれに失敗する
A. テスト用フック(各テスト前にDBをTRUNCATE)が、Jestのデフォルト並列ワーカーと競合し、FK違反等で非決定的に失敗することがあります。backend/package.json の test スクリプトは既に jest --runInBand(直列実行)をデフォルトにしているため、通常のコマンドで踏むことはありません。自分で npx jest(オプションなし)を直接叩くと再現するので避けてください。
Q. docker compose exec backend npm test は本当にテスト専用DBを見ている?
A. 2026-07-27〜28 の修正で、開発DBは使われなくなりました。以前は docker-compose.yml がコンテナに注入する開発用DB(sailvlog_db)向けの DATABASE_URL を dotenv が上書きせず、開発DBに対してテストが走って開発データが消えていました。今は backend/src/__tests__/setup/env.ts と backend/scripts/ensure-test-db.js(pretest)が .env.test を override: true で読むため、コンテナ経由でも .env.test のテストDBを見に行き、コンテナ内からは届かずに失敗します(上の「テスト運用のルール」2。接続先ホストとDB名のガードもあります)。テストはホスト側から cd backend && npm test で実行してください(CI もホストで直接実行しています)。
docker compose ps で3コンテナ(db/backend/frontend)が Up になっているか確認docker compose logs backend / docker compose logs frontend で直近のエラーを確認next dev が動いているコンテナ内で npm run build(本番ビルド)を同時に実行すると .next の競合でdevサーバーが壊れることがあります。その場合は docker compose restart frontend で復旧しますdocker compose ps で db が healthy か確認してから docker compose restart backendv3/replay-mvp を main へ統合したものが、Neon(DB)/ Render(backend)/ Vercel(frontend)の0円構成で本番として稼働しています(2026-07-30統合。docs/dev-org/GATES.md ③参照)。ただし ③Quality Gate は本稿執筆時点でまだ通過しておらず(Major課題が残存)、/p/[slug] の公開URLを外部へ配布しないという運用制約のもとで公開されています。詳細・解除条件は docs/dev-org/GATES.md ③を参照してください。
cold start に注意: Render無料プランはスリープするため、しばらく誰もアクセスしていないと初回表示に約12.5秒かかります(warm状態なら0.33〜0.59秒。docs/dev-org/GATES.md ③実測。オーナーが構造的制約として受容済み)。反省会でURLを開く直前に、誰か一人が先に一度開いて温めておくことを推奨します。
PWA化(ホーム画面に追加)してもcold startは解決しません: /(公開ホーム)はホーム画面に追加してアプリのように起動できますが、これは見た目とURLを開く手間を省くだけで、実体は上記と同じRenderのbackendにアクセスします。ホーム画面から開いた初回も、スリープ明けなら同じ約12.5秒を待つ必要があります。オフラインキャッシュ(Service Worker)は導入していません。
デプロイ作業で実際に踏んだ罠(docs/dev-org/TASKS.md 発見事項より。いずれもエラーメッセージから原因に辿り着けない種類だったため記録):
main に戻ってしまう — v3の成果が反映されないままデプロイされる。ビルドログの Checking out commit ... in branch main で気づけるbackend を指定する。両方に指定すると backend/backend を探して失敗するOther になっていた — デプロイ自体は「Ready」になるが全パスがプラットフォーム404(x-vercel-error: NOT_FOUND)を返す。ビルドログにエラーが出ないため気づきにくい。404本文がNext.jsの404ページでなくプレーンテキストの NOT_FOUND なら、アプリのルーティング以前の設定ミスを疑う/ が vercel.com/sso-api へ302し、Vercelにログインしていない相手には中身が返らない。プレビューだけの制約と思い込むと詰まる。Settings → Deployment Protection → Require Log In をOFFで解除する(Hobbyプランでも操作可能)部内限定プロジェクトです。OSSとしての公開・外部貢献は現時点で想定していません。