brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
manage-engagement-bufferManage an engagement buffer that ingests, prioritizes, rate-limits, deduplicates, and tracks state for incoming engagement items across platforms. Generates periodic digests and enforces cooldown periods. Composes with du-dum: du-dum sets the observation/action cadence, this skill manages the queue between beats.
Independent GitHub snapshot · Automated classification · Original documentation governs
プラットフォームを横断する着信エンゲージメントアイテムを取り込み、重複排除し、優先順位付けし、レート制限を行い、それから簡潔なダイジェストを行動クロックへ引き渡す。バッファは生のプラットフォーム信号と意図的行動の間に座る: バーストを吸収し、重複をマージし、クールダウンを強制し、エージェントが最高価値のアイテムを最初に処理することを保証する。バッファなしには、自律エージェントは到着順にアイテムを処理する(ノイズに埋もれた緊急のものを逃す)か、すべてを一度に試みる(レート制限にぶつかりスパムに見える)。
本スキルは du-dum と構成する: du-dum は いつ 観察し行動するかを決め、本スキルは 何が 行動に値するかを決める。バッファは du-dum の拍の間に蓄積する queue。
buffer_path — JSONL バッファファイルへのパスplatform_config — プラットフォームごとのレート制限とクールダウン設定digest_size — ダイジェストのトップアイテム数(既定: 5)ttl_hours — 未行動アイテムの time-to-live(既定: 48)cooldown_minutes — 行動後のスレッドごとクールダウン(既定: 60)エンゲージメントアイテム構造を設計する。バッファ内の各アイテムはこれらのフィールドを持つ単一 JSON 行:
{
"id": "gh-notif-20260408-001",
"source": "github:pjt222/agent-almanac",
"timestamp": "2026-04-08T09:15:00Z",
"content_summary": "PR #218 review requested by contributor",
"priority": 4,
"state": "new",
"dedup_key": "github:pjt222/agent-almanac:pr-218:contributor-name",
"thread_id": "pr-218",
"ttl_hours": 48
}
フィールド定義:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (source prefix + date + sequence) |
source | string | Platform and channel (github:repo, slack:channel, email:inbox) |
timestamp | ISO 8601 | When the item was ingested |
content_summary | string | One-line description of the engagement item |
priority | int 1-5 | Composite priority (see Step 4) |
state | enum | new, acknowledged, acted, cooldown, merged, expired |
dedup_key | string | Composite key: source + thread + author |
thread_id | string | Conversation thread identifier for cooldown tracking |
ttl_hours | int | Hours until item expires if unacted (default: 48) |
JSON Lines ファイル(行ごとに 1 つの JSON オブジェクト)として保存する。このフォーマットは追記専用書き込み、行ごとの処理、期限切れ行なしで書き直すことによる簡単な剪定をサポートする。
期待結果: スキーマがコンパニオンコメントまたはヘッダで文書化された、buffer_path で初期化された JSONL バッファファイル。スキーマはすべての下流ステップをサポートするのに十分安定している。
失敗時: バッファファイルが作成できない(権限、パス問題)なら、現在のサイクルにはインメモリリストにフォールバックしファイルシステムエラーをログする。アイテムを静かにドロップしない — 一時的でもどこかにバッファする。
プラットフォームアダプタからアイテムを受け入れ、初期優先順位割り当てと共にバッファに追記する。
アイテムタイプ別の優先順位割り当て:
| Type | Priority | Rationale |
|---|---|---|
| Direct mention (@agent) | 5 | Someone explicitly asked for attention |
| Review request | 4 | Blocking someone else's work |
| Reply in tracked thread | 3 | Active conversation the agent participates in |
| Notification (assigned, subscribed) | 2 | Informational, may require action |
| Broadcast (release, announcement) | 1 | Awareness only, rarely actionable |
各着信アイテムについて:
state を new に設定timestamp を現在 UTC 時間に設定dedup_key を生成# Pseudocode: ingest from GitHub adapter
for notification in github_adapter.fetch():
item = build_item(notification)
item.priority = priority_by_type(notification.reason)
item.state = "new"
append_jsonl(buffer_path, item)
log("ingested {item.id} priority={item.priority}")
期待結果: 新しいアイテムが正しい優先順位と state=new でバッファファイルに現れる。各アダプタは独立に整形式のアイテムを生成する — アダプタ失敗が他のアダプタをブロックしない。
失敗時: プラットフォームアダプタが失敗(auth 期限切れ、レート制限、ネットワークダウン)したら、失敗をログしこのサイクルではそのソースをスキップする。既存バッファアイテムをクリアしない — 以前の成功フェッチからの古いアイテムは空バッファよりまし。
設定可能な窓(既定: 24 時間)内で同じ dedup_key を共有するアイテムをバッファでスキャンする。最高優先順位インスタンスを保ち、他をマージとしてマークする。
dedup_key でアイテムをグループ化state=merged としてマークthread_id は活動バーストを示す — content_summary に追加された参加者数で単一アイテムに統合# Dedup logic
groups = group_by(buffer, "dedup_key", window_hours=24)
for key, items in groups:
if len(items) > 1:
keeper = max(items, key=lambda i: (i.priority, i.timestamp))
for item in items:
if item.id != keeper.id:
item.state = "merged"
# Thread burst detection
thread_groups = group_by(buffer, "thread_id", window_hours=1)
for thread_id, items in thread_groups:
active_items = [i for i in items if i.state == "new"]
if len(active_items) >= 3:
keeper = max(active_items, key=lambda i: i.priority)
keeper.content_summary += f" ({len(active_items)} participants)"
for item in active_items:
if item.id != keeper.id:
item.state = "merged"
期待結果: バッファは窓内に重複 dedup_key エントリを含まない。スレッドバーストは参加者数と共に単一アイテムに崩される。マージされたアイテムは(監査用に)ファイルに残るが下流処理から除外される。
失敗時: 重複排除が予想外のマージ(鍵を共有する正当な別個のアイテム)を生むなら、dedup 窓を狭めるか鍵構成を精緻化する。dedup 鍵にコンテンツハッシュを加えると、source + thread + author を共有するが真に異なるコンテンツを持つアイテムを区別できる。
最近度減衰とエスカレーションを取り入れた合成スコアでバッファを再ソートする。
合成スコア式:
score = base_priority * recency_weight * escalation_factor
recency_weight = 0.9 ^ hours_since_ingestion
escalation_factor = 1.0 + (resubmission_count * 0.2)
# Cap effective priority at 5
effective_priority = min(5, score)
挙動:
3 * 1.0 * 1.0 = 3.03 * 0.43 * 1.0 = 1.29(priority-2 アイテム未満に減衰)2 * 1.0 * 1.4 = 2.8(priority-3 近くにエスカレート)すべての state=new アイテムを effective_priority 降順でソート。このソート順がダイジェスト(ステップ6)が du-dum に提示するもの。
期待結果: バッファが合成スコアでソートされる。新鮮な高優先順位アイテムが上にある。古いアイテムは減衰した。再提出アイテムはエスカレートした。アイテムは優先順位 5 を超えない。
失敗時: スコア式が直感に反するランキング(例: 1 時間古い priority-2 アイテムが新鮮な priority-3 アイテムより上)を生むなら、減衰率を調整する。1 時間あたり 0.95 の減衰はより穏やか; 1 時間あたり 0.85 はより攻撃的。エンゲージメントテンポに合うようにチューニングする。
プラットフォームごとの書き込み制限とスレッドごとのクールダウンを強制してエージェントが過剰エンゲージしないようにする。
プラットフォームごとレート制限(platform_config で設定可):
| Platform | Default limit | Window |
|---|---|---|
| GitHub comments | 1 per 20 seconds | rolling |
| GitHub reviews | 3 per hour | rolling |
| Slack messages | 1 per 10 seconds | rolling |
| Email replies | 5 per hour | rolling |
スレッドごとクールダウン: エージェントがスレッドに行動した後、そのスレッドは cooldown_minutes(既定: 60)クールダウンに入る。クールダウン中、そのスレッドの新アイテムは取り込まれるがダイジェストに表面化しない。
エラーバックオフ: 任意のプラットフォームから 429/レート制限応答を受けたら、そのプラットフォームのクールダウンを倍にする。成功行動後に既定にリセット。
# Rate limit check before action
def can_act(platform, thread_id):
if rate_limit_exceeded(platform):
return False, "rate limited"
if thread_in_cooldown(thread_id):
return False, "thread cooldown active"
return True, "clear"
# After action
def record_action(platform, thread_id):
increment_rate_counter(platform)
set_cooldown(thread_id, cooldown_minutes)
# After rate-limit error
def handle_rate_error(platform):
current_cooldown = get_platform_cooldown(platform)
set_platform_cooldown(platform, current_cooldown * 2)
期待結果: エージェントは決してプラットフォームレート制限を超えない。スレッドは強制されたクールダウン期間を持つ。レート制限エラーは自動バックオフを引き起こす。バッファはクールダウン中にアイテムを失わずに蓄積する。
失敗時: 強制にも関わらずレート制限がヒットする(クロックスキュー、並行エージェント)なら、安全マージンを増やす — 制限をプラットフォームの実際制限の 80% に設定。クールダウンが攻撃的すぎる(時間敏感スレッドを逃す)なら、高優先順位スレッドのみ cooldown_minutes を減らす。
du-dum の行動拍のための簡潔な概要を作成する。ダイジェストが引き渡し点: du-dum はこれを読み、生のバッファではない。
ダイジェスト内容:
state=new アイテムのカウントdigest_size から既定 N=5)# Engagement Digest — 2026-04-08T12:00:00Z
## Pending: 12 items
### Top 5 by Priority
| # | Priority | Source | Summary | Age |
|---|----------|--------|---------|-----|
| 1 | 5.0 | github:pr-218 | Review requested by contributor | 2h |
| 2 | 4.2 | github:issue-99 | Maintainer question (escalated) | 6h |
| 3 | 3.0 | slack:dev | Build failure alert | 1h |
| 4 | 2.8 | github:pr-215 | CI check feedback (3 participants) | 3h |
| 5 | 2.1 | email:inbox | Collaboration inquiry | 8h |
### Expiring Soon
- github:issue-85 — 4h remaining (TTL 48h, ingested 44h ago)
### Cooldowns Active
- pr-210: 22 min remaining
- issue-92: 45 min remaining
### Buffer Health
- Total items: 47 | New: 12 | Merged: 18 | Acted: 11 | Expired: 6
ダイジェストを du-dum の行動クロックが読む既知のパス(例: buffer_path.digest.md)に書く。
期待結果: du-dum が一読で解析できる 50 行以下のダイジェスト。ダイジェストには何に行動するかを決めるに十分な情報が含まれるが、フルバッファではない。何も保留中でなければ、ダイジェストはそう明確に言う。
失敗時: ダイジェストが 50 行を超えて成長したら、digest_size を減らすか expiring/cooldown セクションをより攻撃的に要約する。ダイジェストは概要 — バッファのサイズに近づいたらその目的を失っている。
du-dum がダイジェストからアイテムを処理した後、状態を更新し監査トレイルを維持する。
状態マシン:
new → acknowledged → acted → cooldown → expired
↑ │
└───── (re-ingested) ───┘
merged → (terminal, no further transitions)
expired → (terminal, archived)
各状態遷移について:
state フィールドを更新{"item_id": "...", "from": "new", "to": "acknowledged", "timestamp": "...", "reason": "du-dum digest pickup"}保持と剪定:
state=acted または state=expired アイテムをアーカイブ(設定可)buffer_path.archive.jsonl)への移動でアーカイブstate=merged アイテムを剪定(dedup 目的を果たした)# End-of-cycle maintenance
for item in buffer:
if item.state == "new" and age_hours(item) > item.ttl_hours:
transition(item, "expired", reason="TTL exceeded")
if item.state in ("acted", "expired") and age_days(item) > retention_days:
archive(item)
if item.state == "merged" and age_hours(item) > 24:
archive(item)
rewrite_buffer(buffer_path, active_items_only)
期待結果: すべての状態遷移がタイムスタンプと理由でログされる。バッファファイルはアクティブアイテム(new、acknowledged、cooldown)のみを含む。アーカイブされたアイテムは監査用に別途保存される。バッファは無制限に成長しない。
失敗時: バッファファイルが書き直し中に壊れた(部分書き、クラッシュ)なら、書き直し前バックアップから復元する。常にテンプファイルに書きアトミックにリネーム — その場で書き直さない。アーカイブが大きくなりすぎたら、月次で圧縮またはローテートする。
du-dum — このバッファが構成する周期パターン; du-dum は いつ 観察し行動するかを決め、本スキルは 何が 行動に値するかを決めるmanage-token-budget — コスト会計; バッファはダイジェストのサイジングと行動スループット制限時にトークン予算制約を尊重するcircuit-breaker-pattern — バッファに供給するプラットフォームアダプタの失敗処理; アダプタの回路が開くと取り込みが優雅に劣化するcoordinate-reasoning — バッファと行動システム間のスティグマージック信号; バッファファイル自体がスティグマージック成果物forage-resources — バッファの取り込みアダプタに供給する新しいエンゲージメントソースの発見