拡張のしかた
何を足すと何が増えるか、どこまで画面の設定で足せて、どこからコードの変更が要るかをまとめた頁。
BOUNTY の拡張は、ほとんどが宣言(一か所の定義)に一行を足すことから始まる。画面・サーバ・API・MCP・この文書は宣言を読むので、足した行に追従する。
運営が画面で足せるのは、宣言の中で選べるもの(質問・共通モジュール・募集・選考の段・機能の ON/OFF・調整値・トークン)。宣言に新しい種類を足すのはコードの変更で、型と番人のテストが足し忘れを落とす。
宣言の多くは GEEK の写し(src/lib/geek-frozen)と対になっている。BOUNTY の宣言に行を足すときは、写しの側にも同じ行が要るかを確かめる。詳しくは最後の節にある。
拡張点
- モジュールアンケートBOSHU の募集とチケットの設問を、同じモジュールと同じ棚で組む仕組み。
- 団体登録フォームのモジュールとパターン団体・本人・パートナー登録・企画募集を組み合わせる、イベントの登録フォーム。
- BOSHU のテンプレート・種類・選考の段募集の型(テンプレート)と種類、募集ごとに組む選考の段。
- イベントの機能の ON/OFFイベントごとに機能を切り替える語彙と既定。
- ゲーム設定(調整値)運営が変えられる値のレジストリ。既定値は各モジュールが持つ。
- API の契約registry に一行足すと、OpenAPI・この文書・番人が追従する。
- MCP の道具と手順領域ごとの道具のファイルと、手順の一つの正本。
- トークンの scopeトークンに許す範囲の目録と、OAuth で配る範囲。
- GEEK のモジュールsrc/lib/geek-frozen から読む共通の部品。BOUNTY では直さない。
モジュールアンケート
何が拡張できるか
モジュールアンケートは「設問 → ページ → モジュール → 質問」の形で、BOSHU の募集とチケットの設問を同じ仕組みで組む。ページは行き先(BOSHU の募集・BOUNTY のプロフィール・このイベント・4S 共通)ごとに分かれ、回答の置き場は行き先が決める。
モジュールは一連の質問の束で、層(主体・企画・チケット)と置ける行き先を持つ。一覧の唯一の宣言は src/lib/questionnaire/catalog.ts の CATALOG で、棚の行・テンプレート・MCP・組み立ての画面はここを読む。
モジュールの種類は、質問の束(questions)・システムの表示(system。企画の中身を見せるだけで質問ではない)・イベントごとに作るもの(per_event。マッチングの m_match_ にイベントの id を付けた鍵)の三つ。
共通モジュールは棚(form_module)に置き、複数の募集やチケットから参照する。その募集だけの質問は、その募集の中のモジュール(inline)に入れる。
画面の設定でできること(運営)
募集の設問の画面では、棚の共通モジュールを差し込む、その場で質問を足して直す、その募集だけのモジュールを棚に入れる、がコードなしでできる。質問の種類は、その行き先が受け付ける種類から選ぶ。
チケットの設問は、イベントの管理の登録フォームとチケットの設問の画面で、行き先ごとのページにモジュールを並べる。
募集の設問は保存のたびに新しい版になる。公開済みの版は写しなので、共通モジュールを後で直しても変わらない。
質問の鍵は変えない。CSV の列は鍵で決まり、共通モジュールを「この設問だけ(複製)」にすると鍵が作り直されて新しい列になる。
開く画面
- /events/<イベント>/manage/forms
- /events/<イベント>/manage/tickets/questions
- /events/<イベント>/manage/boshu/<募集>/edit
- /admin/boshu
コードの変更が要ること(開発者)
一覧に新しいモジュールを足すときは、catalog.ts にモジュールを一つ書いて CATALOG に足す。層・行き先・requiresLogin と loginReason を必ず決め、アカウントを読み書きするかファイルを受け取るならログインを要にする。
質問の鍵は一覧の中で重ねない。プロフィールや団体へ結ぶ質問は欄の宣言(src/lib/boshu/profile-question-fields.ts・src/lib/boshu/organization-question-fields.ts)を読み、文言や上限を写さない。電話番号は聞かない。
テンプレートに組み込むときは catalog.ts の TEMPLATES の並びに足す。一覧から中身や並びを作る関数(catalogModuleBody・templateModuleKeys など)は GEEK の写し(src/lib/geek-frozen/forms)を通り、写しにも同じ一覧があるので、geek-system のパックにも同じ行を足して写しを入れ直す。
新しい行き先は src/lib/ticket-modules/contract.ts の DESTINATIONS と DESTINATION_SPEC(回答の置き場・誰の回答か・置き方・受け付ける種類・分岐の深さ)に足す。BOSHU の行き先は src/lib/questionnaire/contract.ts が広げているだけで、チケットの値を写さない。
棚の行の行き先は DB の制約で縛っていて、その一覧は FORM_MODULE_DESTINATIONS と同じなので、migration で制約も広げる。持ち主(イベント・募集)ごとに置ける行き先は OWNER_DESTINATIONS が決める。
新しい質問の種類は src/lib/forms/question.ts に足し、各行き先の types に載せたものだけが置ける。4S 共通のページに置けるのは 4S が表せる種類(FOURS_QUESTION_TYPES)だけ。
番人のテスト
- src/lib/questionnaire/catalog.test.ts全テンプレートに並びがあること、鍵の重なり、電話番号、ログインの要否、行き先と質問の種類の組み合わせを確かめる。
- src/lib/questionnaire/contract.test.ts既存の質問の組を一つの仕組みへ写すとき、鍵と並びが変わらないことを確かめる。
- src/lib/ticket-modules/contract.test.tsチケットの設問の行き先ごとのページ・分岐・鍵の一意を確かめる。
足したあとの確認
組み立ての画面の棚に新しいモジュールが出ること、テンプレートから作った募集の並びに入ることを見る。
ログインが要るモジュールを置いた募集は、自動でログインが必要になる。未ログインで開いて、ログインの段が出ることを確かめる。
続けて読む
団体登録フォームのモジュールとパターン
何が拡張できるか
団体登録フォームは、設問モジュール a(団体)・b(登録者)・c(イベントとの連携)・d(応募内容)と、その組み合わせのパターンでできている。宣言は src/lib/boshu/guild-modules.ts だけにある。
パターンは platform(a+b。SPIKES PLATFORM への団体登録)・partner(a+b+c。イベントのパートナー登録)・royale(a+b+c+d。GUILD ROYALE などの企画募集)。並べる順はどのパターンも b → a → c → d で、送信は一回・一つの transaction で書く。
パートナー募集のフォームでは、同じイベントに受付中の企画募集がちょうど一つあれば、それに参加するかを聞く。「はい」なら d が同じフォームに出て、送信は royale のパターンになる。
画面の設定でできること(運営)
新しいイベントは、パートナー募集や企画募集の下書きを作るだけで、コードを足さずに登録フォームが組み上がる。c と d の質問は、それぞれの募集の設問の画面で直せる。
a と b はシステムのページで、画面からは直せない。聞くことはコードの宣言(src/lib/boshu/form-builder.ts の FIXED_STEP_ASKS)が持つ。
開く画面
- /events/<イベント>/manage/forms
- /events/<イベント>/manage/partners
- /events/<イベント>/manage/boshu/new
コードの変更が要ること(開発者)
新しいモジュールは GUILD_FORM_MODULES に一行足し(出どころ・承認の持ち主・送信で書くもの・範囲の名前)、GUILD_FORM_ORDER に並べる。
サーバの表(src/lib/boshu/composite-service.ts の SERVER_MODULES)と画面の表(src/components/boshu/PartnerApplicationForm.tsx の sections と validators)は Record<GuildFormModuleId, …> なので、一行ずつ足さないと型で落ちる。段の名前(src/lib/boshu/submission-steps.ts)と文書の図の札(src/lib/developer/feature-diagrams.ts)も同じ形で落ちる。
新しいパターンは GUILD_FORM_PATTERNS に組み合わせを書く。企画募集のテンプレートを増やすときは、src/lib/boshu/templates.ts の COMPOSITE_PROGRAMME_TEMPLATES と GUILD_FORM_TEMPLATE_PATTERN に足す。
パターンを読む関数(guildFormPatternOf・guildFormModules など)は GEEK の写し(src/lib/geek-frozen/boshu)を通るので、写しのパック(BOUNTY_FORM_PATTERNS)にも geek-system 側で同じ行を足す。
番人のテスト
- src/lib/boshu/guild-modules.test.tsモジュールとパターンの宣言、テンプレートとパターンの対応、サーバと画面が宣言を順に回していることを確かめる。
- src/lib/boshu/form-builder.test.ts登録フォームの段の組み立てを確かめる。
- src/lib/boshu/submission-steps.test.ts応募の段の名前と並びを確かめる。
足したあとの確認
パートナー募集の URL と企画募集の URL の両方から開き、段の並びと送信先が宣言どおりかを見る。企画募集から開いたときは、参加の選択が「はい」で始まる。
続けて読む
BOSHU のテンプレート・種類・選考の段
何が拡張できるか
募集のテンプレートは src/lib/boshu/templates.ts の TEMPLATE_KEYS と BOSHU_TEMPLATES が持ち、名前・種類・プロフィールの扱いを決める。運営の画面で選べるのは AUTHORING_TEMPLATE_KEYS に入ったものだけ。
テンプレートの中身は catalog.ts の TEMPLATES(モジュールの並びと既定の登録の要否)が決める。企画の種類(登壇・ブース・体験)から使うテンプレートは CONTENT_KIND_TEMPLATE が決める。
募集の種類は src/lib/boshu/rules.ts の BOSHU_KINDS(staff・talk・pitch・other)。
選考の段は募集ごとに運営が設計する。段は名前・期限・案内・追加の質問を持ち、判定は決まった語彙(未判定・保留・通過・見送り・補欠)から選ぶ。
画面の設定でできること(運営)
募集を作るときにテンプレートを選び、ログインの要否と質問を画面で決める。
選考の段は募集の編集画面で足し、並べ、期限を付ける。段の数の上限までなら、画面だけで増やせる。
開く画面
- /events/<イベント>/manage/boshu/new
- /events/<イベント>/manage/boshu/<募集>/edit
- /admin/boshu/new
コードの変更が要ること(開発者)
新しいテンプレートは TEMPLATE_KEYS と BOSHU_TEMPLATES に足し、catalog.ts の TEMPLATES にモジュールの並びを書く。画面で作らせるなら AUTHORING_TEMPLATE_KEYS にも足す。
イベントの登録フォームに載る企画募集なら、COMPOSITE_PROGRAMME_TEMPLATES と GUILD_FORM_TEMPLATE_PATTERN にも足す(前の節)。
選考の判定の語彙・段の上限・既定の段は、src/lib/boshu/selection-contract.ts が GEEK の写し(src/lib/geek-frozen/selection)から読む。これらを変えるのは geek-system 側の変更になる。
番人のテスト
- src/lib/questionnaire/catalog.test.tsすべてのテンプレートにモジュールの並びがあり、並びの鍵が一覧にあることを確かめる。
- src/lib/boshu/selection-model.test.ts最後の段の通過だけが応募全体の通過になること、古い書き込みを断ることを確かめる。
- src/lib/boshu/selection-service.test.ts選考の下書きの保存・公開・判定の流れを確かめる。
足したあとの確認
テンプレートから募集を一つ作り、モジュールの並び・ログインの要否・応募の画面を見る。
選考の段を一つ足して保存し、審査の画面に段が順に出ることを確かめる。
続けて読む
イベントの機能の ON/OFF
何が拡張できるか
イベントごとの機能の ON/OFF は、src/lib/events/features.ts の EVENT_FEATURES が語彙・既定・解決の唯一の定義。各行は鍵・見出し・説明と、主のイベントとほかのイベントでの既定を持つ。
event.features には管理者が変えた値だけが残り、無い鍵は既定で読む。OFF の機能は画面の入口が消え、API は feature_disabled で断る。
開催規模でも変わる。small は WANTED・BOSHU・TRIO・QR ミートを基本とし、大規模専用の機能は保存値にかかわらず使えない。
画面の設定でできること(運営)
イベントの管理者は、イベントの管理のトップにある機能の切り替えで、規模と各機能を変える。明示した ON/OFF は、既定が後で変わっても残る。
開く画面
- /events/<イベント>/manage
コードの変更が要ること(開発者)
新しい機能は EVENT_FEATURES に一行足す(鍵・見出し・説明・主のイベントとほかの既定)。規模ごとの扱いは、同じファイルの SMALL_CORE と LARGE_ONLY のどちらに入れるかで決まる。切り替えの画面の行は、この一覧から出る。
機能の画面と API は eventFeatureEnabled(event, key) で入口を出し分ける。この呼び出しは、機能ごとに自分の入口に書く。
GEEK の写しの宣言(createFeatureRegistry に渡す一覧)は EVENT_FEATURES から作るので、打ち直さない。ブランドの段(src/lib/event/brand-spikes.ts の SPIKES_BRAND)に値を入れるときは、先に今の実装を外すか同じ段を足す。
番人のテスト
- src/lib/events/features.test.ts語彙・既定・規模ごとの扱い・上書きの読み方と保存の仕方を確かめる。
- src/lib/events/features.geek-parity.test.ts今の実装と GEEK の写しの答えが、全イベント・全機能で同じことを確かめる。
- src/components/events/event-settings.test.ts切り替えの画面が規模ごとの機能を出し分け、設定の版で古い保存を断ることを確かめる。
足したあとの確認
テスト用のイベントで ON と OFF を切り替え、OFF のときに入口が消えて API が断ることを見る。主のイベントとほかのイベントで、既定が宣言どおりかも見る。
続けて読む
ゲーム設定(調整値)
何が拡張できるか
運営が変えられる調整値(得点・称号・相性の重み・デッキ・WANTED・AI・通知など)の一覧は、src/lib/config/registry.ts の REGISTRY だけが持つ。
既定値は値を持つモジュールが DEFAULT_ で始まる名前で定義し、レジストリはそれを読んで検証・見出し・分類・イベント中に変えてよいかを足す。
読むのは src/lib/config/load.ts の getGameConfig だけ。既定と上書きを鍵ごとに検証し、通らない値は既定に戻して理由を返す。
コードの変更が要ること(開発者)
新しい値は、持ち主のモジュールに DEFAULT_ の既定を書き、REGISTRY に一行足す(分類・見出し・説明・既定・zod の形・eventSafe・保存先)。管理画面の欄はレジストリから作るので、画面を書き足さない。
純粋な関数は解決済みの値を引数で受け、DEFAULT_ を直接読まない。画面に出す値はサーバから受け取り、AI のジョブは作った時の値を入力に焼き込む。
使わなくなった鍵は RETIRED_CONFIG_KEYS に移し、保存済みの値を読まない。鍵をまたぐ検算は registry.ts の CROSS_CHECKS に書く。
番人のテスト
- src/lib/config/guard.test.ts既定値を持ち主・レジストリ・テストのほかが読んでいないこと、移す前の定数名が残っていないことを確かめる。
- src/lib/config/resolve.test.ts既定と上書きの解決、壊れた値を既定へ戻すことを確かめる。
足したあとの確認
ゲーム設定の画面に欄が出ること、範囲の外の値が理由付きで断られること、保存した値で振る舞いが変わることを見る。
続けて読む
API の契約
何が拡張できるか
API の一覧の正本は src/lib/contract/registry.ts の ENDPOINTS。一件ごとにメソッド・パス・認証・本文・応答の zod を持ち、分野ごとの一覧(例: src/lib/ticket-modules/registry.ts)を読み込んで並べる。
OpenAPI(src/lib/contract/openapi.ts)とこの文書の API の頁(src/lib/developer/api-model.ts)は registry から作る。公開の文書と OpenAPI に載るのは、isPublicEndpoint が公開と決めた入口だけ。
画面の設定でできること(運営)
画面の設定で API を足すことはできない。運営が画面でできるのは、API トークンの発行と失効(下の scope の節)。
コードの変更が要ること(開発者)
route.ts を書いたら、registry に一件足すか、src/lib/contract/unregistered.ts に理由の分類付きで一件載せる。どちらも無いと番人が落とす。
本文とクエリの zod は src/lib/contract/requests.ts に置き、route.ts も同じものを import する。応答の形をまだ zod で書けないときだけ schemaPending を付ける。
項目の削除と型の変更は CONTRACT_VERSION を上げ、足すだけなら上げない。新しい分類は registry の TAGS に足す。文書の分類の見出し(DEVELOPER_TAGS)は GEEK の写しから読むので、geek-system 側にも足す。
番人のテスト
- src/lib/contract/route-coverage.test.tsすべての route のメソッドが registry か unregistered.ts のどちらかに載っていることを確かめる。
- src/lib/contract/registry.test.tsパスとメソッドの組が重ならないこと、個別の入口の約束を確かめる。
- src/lib/developer/api-model.test.ts文書の API の頁が registry の全件と対応していることを確かめる。
- src/components/developer/api/api-render.test.ts公開の頁に出る件数が公開の入口の件数と同じで、匿名に運営の API が出ないことを確かめる。
足したあとの確認
公開の入口なら、この文書の API の頁と OpenAPI に新しい API が出ることを見る。運営だけの入口は、匿名で開いたときに出ない。
続けて読む
MCP の道具と手順
何が拡張できるか
MCP の道具は領域ごとに一つのファイル(src/lib/mcp/tools の下)にあり、並びの正本は src/lib/mcp/tools/index.ts の TOOL_MODULES。各領域は自分が呼べる REST の入口(endpoints)だけを宣言し、それ以外には届かない。
道具は下書きを作るだけで、公開や確定はしない。例外は運営だけの一部の道具(受付の通知・審査の判定)で、できることは各道具の説明が決める。
使い方の手順は src/lib/mcp/procedures.ts が正本で、ここから MCP の prompts と resources、Claude Code の skill、Codex の指示、MCP の頁のカード、bounty_guide の本文を作る。
画面の設定でできること(運営)
画面で道具を足すことはできない。利用者は MCP の頁の手順で AI をつなぎ、運営の管理者は API トークンの画面で接続リンクを出せる。
開く画面
コードの変更が要ること(開発者)
既存の領域に道具を足すときは、その領域のファイルで登録し、呼ぶ REST の入口を endpoints に足す。新しい領域はファイルを一つ作って TOOL_MODULES に足し、index.ts に道具そのものは書かない。
手順を足すときは procedures.ts の PROCEDURE_DOMAINS に一つ書く。生成物(skill・Codex の指示)は手で直さず、書き直しの印 BOUNTY_WRITE_MCP_DOCS を付けて prompts.test.ts を走らせて作る。
本人が今できることの宣言(src/lib/mcp/capabilities.ts)は、REST の入口の判定と合わせる。whoami はこの宣言を返す。
番人のテスト
- src/lib/mcp/prompts.test.ts書き直しても生成物に差分が出ないこと、手順が指す道具が登録済みであることを確かめる。
- src/lib/mcp/capability-truth.test.tswhoami の宣言と、その人のトークンで実際の route を呼んだ結果が一致することを確かめる。
- src/lib/mcp/server.test.tsMCP のプロトコルの約束と、道具の入力・注釈を確かめる。
足したあとの確認
whoami の capabilities に新しい領域が出ること、MCP の頁のカードと bounty_guide の本文が変わることを見る。
続けて読む
トークンの scope
何が拡張できるか
scope の目録は src/lib/auth/api-token-scopes.ts の API_TOKEN_SCOPE_CATALOG だけが持つ。各 scope は名前・誰に出すか(everyone か、staff と級)・MCP の道具があるかを持つ。
MCP の OAuth で配る scope と、範囲を指定しない許可で当てる既定は、目録から作る(src/lib/oauth/policy.ts)。scope が付いていても、入口は持ち主の今の権限を毎回確かめる。
画面の設定でできること(運営)
運営の管理者は、API トークンの画面で発行するときに scope を選ぶ。新しい scope を画面で作ることはできない。
開く画面
コードの変更が要ること(開発者)
BOUNTY だけの scope は、同じファイルの BOUNTY_LOCAL_SCOPES と BOUNTY_LOCAL_SCOPE_CATALOG に足す。GEEK の台帳にある scope は写しから読むので、共有する scope は geek-system 側に足し、写しに入ったら BOUNTY だけの行から外す。
トークン専用の入口なら registry の apiTokenScope に名前を足し、入口の guard(requireScopedViewer・requireScopedStaff)で確かめる。文書の札のアイコンは src/lib/developer/meta.ts の API_TOKEN_SCOPE_ICONS に足す。
番人のテスト
- src/lib/mcp/capability-truth.test.tsscope と入口の判定が、実際の route の結果と一致することを確かめる。
- src/lib/oauth/oauth.test.tsOAuth で配る範囲、運営だけの scope を運営でない人に出さないこと、今の権限での絞り込みを確かめる。
足したあとの確認
認証の頁の scope の表に新しい行が出ること、運営だけの scope が運営でない人の許可の画面に出ないことを見る。
続けて読む
GEEK のモジュール
何が拡張できるか
GEEK は SPIKES の共通の部品(geek-system)で、BOUNTY は src/lib/geek-frozen に写しを入れて読む。写しは geek-system の vendor:bounty が作り、VENDOR.json が元の commit と各ファイルの指紋を持つ。
BOUNTY の多くの宣言では、答えを作る関数を src/lib/geek/swap.ts の geekSwap で写しへ置き換える途中にある。既定の段では両方を走らせて今の実装の答えを返し、違いだけをログに出す。
画面の設定でできること(運営)
GEEK の部品を画面から変えることはできない。
コードの変更が要ること(開発者)
src/lib/geek-frozen のファイルは BOUNTY で直さない。直すのは geek-system の packages で、写しを作り直して BOUNTY の PR で入れる。
BOUNTY の宣言に行を足したら、写しの側に同じ行が要るかを確かめる。片側だけに足すと、置き換えの段を変えたときに答えが変わる。
BOUNTY だけの値(例: BOUNTY_LOCAL_SCOPES)は置き換えの口の外に足し、geek-system に入ったら写しへ移す。
番人のテスト
- src/lib/geek/vendor.test.ts写しの各ファイルの指紋が記録と一致し、記録に無いファイルが無いことを確かめる。BOUNTY で写しを直すと落ちる。
- src/lib/events/features.geek-parity.test.tsgeek-parity の名前のテストは、今の実装と写しの答えが同じことを確かめる(これは機能の ON/OFF の例)。
足したあとの確認
写しを入れ直したら、geek-parity のテストと写しの番人を走らせ、今の実装と写しの答えが同じことを確かめる。