Skip to content

Repository files navigation

PatchLoop

English version: README.en.md

PatchLoop は、AI で作った demo / PoC に対してブラウザ上で直接フィードバックを残し、その内容を Slack / GitHub / AI 修正 PR につなげるための実験的プロトタイプです。

ローカルで起動する

任意の静的ファイルサーバーで配信して examples/plain-html/ を開きます。

python3 -m http.server 4173
http://localhost:4173/examples/plain-html/

開発

Node.js 22.12 以上が必要です(receiver が共有 ES module を require() で読み込むため)。

依存を入れます。

npm install

lint と test を実行します。

npm run lint
npm test
npm run check

npm test は Node.js の test runner でローカル receiver を一時ポートに起動し、/feedback/import の保存・検証・screenshot 処理を確認します。テストデータは OS の一時ディレクトリに作られ、終了時に削除されます。

main への push と pull request 時には GitHub Actions(.github/workflows/check.yml)が同じ npm run check を自動実行します。

widget のソースは widget/src/ の ES modules で、配布用の単一ファイル dist/patchloop-widget.js は依存ゼロの自前ビルドスクリプトで生成します。dist/ は commit 対象で、npm run check がビルド結果との一致を検証します。

npm run build

receiver を起動している場合は http://localhost:4000/widget.js からも同じ bundle を配信します。

現在できること

script-tag widget:

  • 邪魔にならない右端ドロワー(折りたたみ時はハンドルのみ表示)
  • ドロワーヘッダーのコメントモード切り替え(モード ON 中はハンドルが赤くなる)
  • クリックで点キャプチャ、ドラッグで範囲キャプチャ
  • 送信前はドラフト表示、送信時に 1, 2, 3 と確定番号が振られる
  • 送信後もコメントモードは継続し、連続でコメントできる
  • コメント入力中は Cmd+Enter(Windows は Ctrl+Enter)で送信
  • ドラフト中、対象要素にダッシュドラインの outline
  • ドロワー内のコメント一覧(番号 / kind / reviewer / 本文 / 配送ステータス)
  • マーカーホバーでコメントのツールチップ表示(feedback モード中は無効)
  • 個別の編集・削除と残りマーカーの自動再番号付け
  • URL / 点・範囲位置 / selector / viewport / browser / reviewer / timestamp を含む payload
  • viewport の lightweight screenshot snapshot(SVG)を payload に添付
  • feedback list の localStorage 永続化と reload 後の pin / area overlay 復元
  • ウィンドウリサイズ時は selector で対象要素を引き直し、pin / area を要素に追従して再配置
  • 再配置できない場合(要素が見つからない・非表示など)は従来座標のまま、marker と一覧に近似表示(≈)
  • 任意の onSubmit(payload) callback
  • 任意の endpoint 設定で payload を receiver に POST
  • ローカル receiver から任意の Slack Incoming Webhook へ、スクショリンク / image block / 任意の file upload 付きで転送
  • Download mode で、未送信ぶんをデモ単位でまとめた versioned JSON bundle を一括保存(送り済みフラグで管理)
  • receiver inbox から download mode の bundle(単一・batch の両方)を import
  • 設定または drawer UI から、receiver 経由送信 / Slack webhook 直送 / download / 送信なしを切り替え

埋め込み Widget

PatchLoop は、普通の HTML に script tag で埋め込める standalone widget を含んでいます。

<script src="../../dist/patchloop-widget.js"></script>
<script>
  window.PatchLoop.init({
    projectId: "patchloop",
    demoId: "plain-html-renewal-review",
    endpoint: "http://localhost:4000/feedback",
    showDeliverySettings: true,
    onSubmit(payload) {
      console.log(payload);
    }
  });
</script>

Init options

  • projectId (string) — payload に乗せるプロジェクト識別子
  • demoId (string) — payload に乗せるデモ識別子
  • sourceContext (object, optional) — レビュー対象ページの git 由来情報 { repo, branch, commit, root, buildUrl, previewUrl }(すべて string・任意)。埋め込み側がビルド/デプロイ時に実値を注入するのが正で、AI agent が feedback をソースコードに対応付けるための情報。未指定のフィールドは <meta name="patchloop:repo"> / patchloop:branch / patchloop:commit / patchloop:root / patchloop:build-url / patchloop:preview-url の meta タグから補完されます
  • reviewer (string, optional) — コメントフォームに初期表示する投稿者名。未指定の場合は保存済み reviewer を localStorage から復元し、保存値もなければ空欄
  • reviewerStorageKey (string, optional) — reviewer 名を保存する localStorage key。デフォルトは patchloop:reviewer
  • persistFeedback (boolean, optional) — feedback list を localStorage に保存し、同じ project / demo / page URL の reload 後に復元するか。デフォルトは true
  • feedbackStorageKey (string, optional) — feedback list を保存する localStorage key。デフォルトは patchloop:feedback
  • deliveryMode ("receiver" | "slack-webhook" | "download" | "none", optional) — 送信方式。デフォルトは "receiver"
  • endpoint (string, optional) — payload を POST する URL。未設定なら送信しない
  • ingestKey (string, optional) — receiver に X-PatchLoop-Ingest-Key ヘッダーで送るプロジェクトごとの公開キー。receiver 側で INGEST_KEYS / ingestKeys を設定している場合は必須。ページに埋め込まれるため秘密ではなく、プロジェクト識別・無差別 spam の抑止・ローテーションによる失効が目的
  • slackWebhookUrl (string, optional) — deliveryMode: "slack-webhook" 時にブラウザから直接送る Slack Incoming Webhook URL
  • showDeliverySettings (boolean, optional) — drawer 内に送信先切替 UI を表示するか。デフォルトは false
  • captureScreenshot (boolean, optional) — viewport snapshot を payload に含めるか。デフォルトは true
  • screenshotMaxBytes (number, optional) — widget 側で snapshot を省略する最大バイト数。デフォルトは 1200000
  • onSubmit(payload) (function, optional) — submit のたびに呼ばれる callback

window.PatchLoop API

  • PatchLoop.init(options) — widget をマウントしてキャプチャを開始
  • PatchLoop.destroy() — widget DOM・マーカー・ハイライトを全部撤去
  • PatchLoop.setFeedbackMode(boolean) — コメントモードを外部から切替
  • PatchLoop.getFeedback() — 現在の feedback 一覧のコピーを返す(newest first)

Events

submit のたびに documentpatchloop:feedback が発火し、event.detail に payload が入ります。endpoint の POST が終わるのを待たずに呼ばれます。

基本操作

  1. 右端のハンドルを押して drawer を開く
  2. 「コメントモード開始」を押す
  3. 画面上の場所をクリック、または範囲をドラッグする
  4. コメントと投稿者を書いて送信する。Cmd+Enter(Windows は Ctrl+Enter)でも送信できます。投稿者が空欄の場合は送信できません。コメントモードは送信後も継続するので、終了するには「コメントモード終了」を押します
  5. drawer の一覧に追加され、onSubmit(payload) でも payload を受け取る。送信済みの項目は drawer 内から個別に編集・削除できる

投稿者名は送信後に localStorage へ保存され、次回以降の widget 起動時に復元されます。feedback list もデフォルトで localStorage に保存され、同じ project / demo / page URL の reload 後に drawer list と pin / area overlay が復元されます。drawer の「フィードバックを消す」は、表示中の marker と保存済み feedback の両方を削除します。永続化を使わず memory-only にしたい場合は persistFeedback: false を指定してください。

Payload

主な payload 項目:

  • id
  • projectId
  • demoId
  • comment
  • reviewer
  • page.url
  • page.title
  • sourceContext — レビュー対象ページの git 由来情報(repo / branch / commit / root / buildUrl / previewUrl)。init オプションと meta タグのどちらにも無ければ null
  • target.kind
  • target.x
  • target.y
  • target.clientX
  • target.clientY
  • target.pageX
  • target.pageY
  • target.documentX
  • target.documentY
  • target.area
  • target.selector
  • target.text
  • target.anchor — アンカー要素 rect 内の相対位置(%)と selector。area の場合は width / height も含む。リサイズ・reload 時の要素への再アンカーに使用。area はドラッグ開始点ではなく範囲中心の要素にアンカーします。viewport より大きい要素(main / body 等)は相対位置が不安定なためアンカー対象にせず、その marker は従来座標(page px)固定 + 近似表示になります
  • environment.viewport
  • environment.browser
  • environment.language
  • screenshot — viewport snapshot。成功時は status: "captured"mimeType: "image/svg+xml"dataUrltargetOverlay などを含む
  • createdAt
  • deliveryendpoint 設定時、POST 完了後に { ok, status } または { ok: false, error } が追加される

target.kindpoint または area です。範囲選択の場合は target.area に viewport 上の percentage (x / y / width / height) に加えて、clientX/Y/Width/HeightpageX/YdocumentX/Y/Width/Height のピクセル値も入ります。

clientX/clientY は現在の viewport 上の位置、pageX/pageY はスクロールを含む document 上の位置です。pin / area overlay は document 上に固定されるため、スクロールしても対象箇所に追従します。ウィンドウリサイズでレイアウトが変わった場合は target.selector + target.anchor で対象要素に再アンカーされ、保存座標も再計算されます。

ローカル receiver

endpoint を指定すると、widget は payload をその URL に POST します。検証用のローカル receiver が同梱されています。

node server/receive.js
  • POST /feedback で payload を受け取り、デフォルトでは server/feedback.db(sqlite)に保存します
  • POST /import で download mode の JSON bundle(単一 feedback の v1 / 配列の v2 batch の両方)を読み込み、通常の inbox と同じ形式で保存します。重複 id はスキップし imported / duplicates / failed を返します
  • GET / で受信した feedback の一覧(inbox)を表示します
  • inbox にはテキスト検索と status / kind / project / demo / reviewer / source / Slack の絞り込みがあります
  • 各 feedback には triage status(new / accepted / fixed / ignored)があり、card 上の select から変更できます。status は sqlite に永続化されます
  • POST /feedback/:id/status で API からも status を更新できます(body は {"status": "accepted"} 形式)
  • DELETE /feedback/:id で feedback と紐づく screenshot を削除できます(inbox の card の「削除」ボタンからも)
  • GitHub 連携を設定すると、inbox の各 card から GitHub Issue を作成できます(後述)
  • inbox UI から .patchloop-feedback.json を選択して import できます
  • GET /feedback.json で raw JSON を返します(?projectId= / ?demoId= / ?status= で絞り込み可)
  • GET /screenshots/:file で保存済み screenshot を返します
  • GET /healthz で死活監視ができます(store 疎通込みで 200 / 異常・シャットダウン中は 503。認証不要・rate limit 対象外)
  • SIGTERM / SIGINT で graceful shutdown します(新規接続を止め、処理中のリクエスト完了と store の close を待ってから終了。10 秒で強制終了)

ストレージ

feedback は組み込みの node:sqliteserver/feedback.db)に保存します。バックエンドは server/store.js の小さな非同期インターフェース(init / insert / get / list / update / delete / count)の背後に隔離してあり、将来 MySQL 等の別バックエンドに差し替えても receiver 本体は変更不要です。

起動時に旧形式の server/feedback.json が残っていれば一度だけ sqlite に取り込み、元ファイルは feedback.json.migrated-<timestamp> に退避します(壊れていれば feedback.json.corrupt-<timestamp> に退避して空で起動)。db ファイルのパスは FEEDBACK_DB_PATH、移行元の JSON は FEEDBACK_STORE_PATH で指定できます。

  • PORT / HOST env で変更可能(デフォルトは 127.0.0.1:4000
  • FEEDBACK_DB_PATH env で sqlite DB の保存先を変更できます(FEEDBACK_STORE_PATH は保存先ではなく、旧 feedback.json の移行元です)
  • SCREENSHOT_DIR env で screenshot 保存先を変更できます
  • PUBLIC_BASE_URL env で Slack に載せる receiver の URL を指定できます
  • MAX_BODY_BYTES / SCREENSHOT_MAX_BYTES env で payload / screenshot の上限を変更できます
  • MAX_IMPORT_ITEMS / MAX_FIELD_LENGTH / MAX_ARRAY_LENGTH / MAX_OBJECT_DEPTH env(または config の maxImportItems / maxFieldLength / maxArrayLength / maxObjectDepth)で、受信 payload の形(POST /import 1 回の件数・文字列長・配列長・ネスト深さ)の上限を変更できます。未設定でもローカルで困らない緩いデフォルト(500 / 20000 / 1000 / 32)が常に有効です(超過は 413screenshot.dataUrlSCREENSHOT_MAX_BYTES 側で別途上限)
  • RATE_LIMIT_MAX / RATE_LIMIT_WINDOW_MS / RATE_LIMIT_MAX_CLIENTS env(または config の rateLimitMax / rateLimitWindowMs / rateLimitMaxClients)で、IP ごとの固定窓レート制限を変更できます(デフォルト 120 req / 60000 ms、超過は 429 + Retry-After)。クライアント識別は既定で socket の remoteAddress。reverse proxy 配下では RECEIVER_TRUST_PROXY1 にしたときだけ X-Forwarded-For 先頭を使います(既定では直アクセスがヘッダーで識別を偽装できないようにするため)
  • MAX_FEEDBACK_COUNT env(または config の maxFeedbackCount、デフォルト 100000)を超えると新規保存を 507 で拒否します。SCREENSHOT_DISK_MAX_BYTES env(または config の screenshotDiskMaxBytes、デフォルト 500000000)を超える screenshot 書き込みも 507 で拒否します(起動時にディスク使用量を実測し、保存・削除で追跡)
  • RECEIVER_TOKEN env(または config の receiverToken)を設定すると、操作系 endpoint(POST /import / POST /feedback/:id/status / DELETE /feedback/:id / POST /feedback/:id/github-issue)と閲覧系 endpoint(GET /(inbox)/ GET /feedback.json / GET /screenshots/:file)に認証を必須にします。API からは Authorization: Bearer <token>、ブラウザからは inbox のログインフォーム(GET /login)に同じ token を入力します。ログイン後は HMAC 派生値の HttpOnly cookie(有効期限 7 日、SameSite=LaxpublicBaseUrlhttps:// のとき Secure 付き)でセッションが維持され、生 token はブラウザに保存されません。token を変更すると全端末のセッションが即失効します。未設定ならローカルは認証なしで動作します(widget の POST /feedbackGET /widget.js は設定時も常に公開)
  • INGEST_KEYS env(カンマ区切り)または config の ingestKeys(配列)を設定すると、widget の投稿(POST /feedback)に X-PatchLoop-Ingest-Key ヘッダーの一致を必須にします(不一致・欠落は 401)。config では "key文字列" に加えて { "key": "...", "projectId": "..." } 形式で key と projectId を紐付けでき、紐付いた key での投稿は payload の projectId 詐称を 403 で拒否し、省略時は key の projectId を補完します。キーはデモページに埋め込まれる公開キーで、秘密による認証ではありません(プロジェクト識別・spam 抑止・ローテーション失効が目的)。未設定なら従来通り誰でも投稿できます
  • ALLOWED_ORIGINS env(または config の allowedOrigins、env はカンマ区切り・config は配列)を設定すると、widget の投稿(POST /feedback)の CORS を許可 origin(scheme://host[:port] の完全一致)に制限します。JSON POST は必ず preflight されるため、リスト外 origin のブラウザ投稿は本体 POST の前にブラウザ側で遮断されます。未設定なら従来通り全 origin 許可(*)で、起動ログに警告が出ます。CORS ヘッダーが付くのは POST /feedback のみで、inbox・操作系・screenshot は同一オリジン利用のため CORS 自体を返しません。受信した feedback には received: { origin, originAllowed } が保存され、inbox の raw payload から確認できます(Origin ヘッダーは偽装可能なため参考情報です)
  • SLACK_WEBHOOK_URL env を設定すると、受信した feedback を Slack Incoming Webhook にも転送します
  • SLACK_IMAGE_MODE env で Slack 上の screenshot 表示方式を変更できます(auto / link / block / upload / off
  • SLACK_BOT_TOKENSLACK_UPLOAD_CHANNEL_ID env を設定すると、保存済み screenshot を Slack file としてアップロードできます
  • SLACK_TIMEOUT_MS env で Slack 転送の timeout を変更できます(デフォルトは 5000

examples/plain-html/ はデフォルトで http://localhost:4000/feedback に送信する設定です。python3 -m http.server 4173 でページを配信した状態で receiver も起動すると、コメントが inbox に届きます。

Receiver 設定ファイル

Slack webhook URL などのローカル設定は server/receiver.config.json に置けます。このファイルは git 管理外です。共有用テンプレートとして server/receiver.config.example.json を用意しています。

cp server/receiver.config.example.json server/receiver.config.json
{
  "host": "127.0.0.1",
  "port": 4000,
  "feedbackDbPath": "feedback.db",
  "screenshotDir": "screenshots",
  "publicBaseUrl": "http://127.0.0.1:4000",
  "maxBodyBytes": 3000000,
  "screenshotMaxBytes": 1500000,
  "slackWebhookUrl": "https://hooks.slack.com/services/...",
  "slackImageMode": "auto",
  "slackBotToken": "",
  "slackUploadChannelId": "",
  "slackTimeoutMs": 5000
}

feedbackDbPath / screenshotDir などのパス系キーに相対パスを書く場合は、設定ファイルからの相対パスとして扱われます。サポートする全キーと既定値は server/receiver.config.example.json を参照してください(feedbackStorePath は旧 feedback.json の移行元で、通常は設定不要です)。publicBaseUrl は Slack 通知内の screenshot link と image block に使われます。ローカル検証なら http://127.0.0.1:4000 のままで十分です。外部の Slack 上で画像 preview まで表示したい場合は、ngrok などで公開した URL を指定してください。

slackImageMode はデフォルト auto です。publicBaseUrl が公開 URL の場合は Slack message に image block を追加します。slackBotTokenslackUploadChannelId も設定されている場合は、Slack Web API で保存済み screenshot を file upload します。この token には Slack App の files:write scope が必要です。link はリンクのみ、block は image block を強制、upload は file upload のみ、off は screenshot 表示を送らない設定です。

別の場所の設定ファイルを使う場合は PATCHLOOP_RECEIVER_CONFIG=/path/to/receiver.config.json node server/receive.js で指定できます。

数値系の設定に不正な値(非数値や、上限系での 0・負・小数)を与えた場合は、その値を無視してデフォルト(env が不正なら config の値)に戻し、起動ログに ignored invalid setting ... の警告を出します。実効値は起動時の limits: / rate limit: サマリ行で確認できます。

環境変数を指定した場合は設定ファイルより優先されます。たとえば一時的に Slack 転送を試す場合:

SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..." node server/receive.js

Slack 転送に失敗しても、receiver は payload を保存します。Slack の結果は保存済み payload の integrations.slack と inbox の Slack 行で確認できます。screenshot の dataUrl は receiver でファイル保存されたあと payload から取り除かれ、screenshot.url として参照されます。

GitHub Issue 作成

inbox の feedback から GitHub Issue を作成できます。Issue 作成は receiver 側で行い、token がブラウザに渡ることはありません。

GITHUB_TOKEN="github_pat_..." GITHUB_REPO="owner/repo" node server/receive.js
  • GITHUB_TOKEN / githubToken — GitHub token。fine-grained PAT で対象リポジトリ + Issues: write のみに絞ることを推奨
  • GITHUB_REPO / githubRepo — Issue を作成するリポジトリ(owner/repo 形式)
  • GITHUB_LABELS / githubLabels — 付与するラベル(env はカンマ区切り、config は配列)
  • GITHUB_ASSIGNEES / githubAssignees — アサイン先(同上)
  • GITHUB_API_BASE / githubApiBase — API base URL(デフォルト https://api.github.com。GHES やテスト時に変更)
  • GITHUB_TIMEOUT_MS / githubTimeoutMs — timeout(デフォルト 8000

設定済みの場合、inbox の各 card に Create GitHub Issue ボタンが表示されます。作成された issue には feedback 本文・reviewer・ページ URL・selector・対象位置・viewport・screenshot link・raw payload が含まれます。結果は保存済み payload の integrations.github に永続化され、card には issue link(失敗時はエラー)が表示されます。同じ feedback からの二重作成は拒否されます。API から行う場合は POST /feedback/:id/github-issue を使います。

screenshot の画像は GitHub から publicBaseUrl に到達できる場合のみ issue 上に表示されます(ローカル receiver のままなら link のみ機能します)。RECEIVER_TOKEN を設定している場合、GitHub の image proxy は認証を通れないため、issue には画像を埋め込まず [Open screenshot] リンクのみを載せます(開くには receiver へのログインが必要です)。

公開デプロイ(EC2 など)

receiver はデフォルトでローカルプロトタイプ前提(127.0.0.1 bind・認証なし・CORS *)です。インターネットに公開する場合は次を前提にしてください。

  • HTTPS 終端は reverse proxy(nginx / Caddy / ALB など)で行う: receiver 自体は HTTP のみです。proxy の背後では HOST の bind 先を proxy からのみ届く interface に限定し、rate limit がクライアント IP を正しく見るよう RECEIVER_TRUST_PROXY=1 を設定します
  • RECEIVER_TOKEN を必ず設定する: 未設定のまま公開すると inbox・feedback データ・操作系がすべて無認証で露出します
  • ALLOWED_ORIGINS にデモページの origin を列挙する: widget からの投稿を想定した origin に絞ります
  • INGEST_KEYS を設定し、widget の init に ingestKey を渡す: キーなしの POST /feedback を 401 で拒否できます。キーは公開キーなので漏えい前提で、プロジェクトごとに分けてローテーションできるようにしておきます
  • PUBLIC_BASE_URLhttps:// の公開 URL にする: Slack / GitHub に載せる screenshot link の到達性に加え、セッション cookie の Secure 属性がこの URL のスキームで決まります
  • secrets(RECEIVER_TOKEN / GITHUB_TOKEN / SLACK_WEBHOOK_URL など)は env 注入を推奨: env は config ファイルより優先されます。config ファイル(receiver.config.json)に書く場合は git 管理外・ファイル権限の管理下に置いてください
  • 死活監視は GET /healthz に張る: 認証不要・rate limit 対象外で、store 疎通込みの 200 / 503 を返します。systemd / ALB からの停止は SIGTERM で graceful shutdown します(in-flight 完了を待つため、停止タイムアウトは 10 秒より長めに)
RECEIVER_TOKEN="<long-random-token>" \
INGEST_KEYS="<per-project-public-key>" \
ALLOWED_ORIGINS="https://demo.example.com" \
PUBLIC_BASE_URL="https://feedback.example.com" \
RECEIVER_TRUST_PROXY=1 \
HOST=127.0.0.1 PORT=4000 node server/receive.js

Slack direct mode

deliveryMode: "slack-webhook" を使うと、receiver を立てずにブラウザから Slack Incoming Webhook に直接送信できます。drawer UI を有効にしている場合は、画面上で送信先を Slack direct に切り替えて webhook URL を入力できます。

window.PatchLoop.init({
  deliveryMode: "slack-webhook",
  slackWebhookUrl: "https://hooks.slack.com/services/..."
});

このモードでは webhook URL がブラウザに見えるため、公開環境では使い捨ての検証用 webhook に限定してください。Incoming Webhook はブラウザ内で生成した dataUrl screenshot を Slack image/file として送れないため、Slack direct mode が Slack に送るのはコメント本文・ページ・対象位置・selector・viewport・screenshot 取得ステータスです。widget 内の payload と onSubmit には screenshot 情報が残ります。画像そのものを Slack に表示または file upload したい場合は、receiver mode で publicBaseUrl / slackBotToken / slackUploadChannelId を使ってください。ブラウザ直送は no-cors で投げるため、成功レスポンスの本文は取得できません。

Download mode と receiver import

deliveryMode: "download" を使うと、receiver や Slack webhook を使わずに feedback をローカルファイルとして保存できます。

window.PatchLoop.init({
  deliveryMode: "download",
  showDeliverySettings: true
});

download mode では、コメントするたびに自動ダウンロードはされません。コメントは drawer に溜まり、「未送信をまとめてDL(N)」ボタンを押すと、未送信ぶんをまとめて 1 ファイルとして <project>-<demo>-<件数>-<timestamp>.patchloop-feedback.json に書き出します。書き出したコメントには送り済みフラグ(一覧で「DL済み」表示)が付き、次回の一括 DL からは除外されます(DL済みコメントを編集すると未送信に戻ります)。bundle は単一 JSON ファイルで、現時点では ZIP ではありません。形式は versioned で、feedback は配列です。

{
  "kind": "patchloop-feedback-bundle",
  "version": 2,
  "exportedAt": "2026-06-16T00:00:00.000Z",
  "projectId": "patchloop",
  "demoId": "plain-html-renewal-review",
  "feedback": [
    {
      "id": "pl_...",
      "screenshot": {
        "status": "captured",
        "dataUrl": "data:image/svg+xml;base64,..."
      }
    }
  ]
}

Import するには receiver を起動し、inbox (http://127.0.0.1:4000/) の Import feedback bundle から .patchloop-feedback.json を選択します。API から送る場合は同じ JSON を POST /import に投げます。

curl -X POST http://127.0.0.1:4000/import \
  -H "Content-Type: application/json" \
  --data-binary @patchloop-feedback.json

receiver は bundle version(v1 の単一 feedback / v2 の配列の両方)と payload shape を検証し、各 feedback の screenshot dataUrlserver/screenshots/ に保存してから store に追記します。import した feedback には source: "import" / importedAt が付きます。batch import では、すでに存在する id は重複としてスキップし(残りは取り込む)、応答に imported 件数・duplicatesfailed を返します。payload のどれか 1 件でも不正なら、何も書き込まずに batch 全体を 400 で拒否します。Slack への再転送はせず、inbox 上では Slack: skipped と表示されます。

現在の境界

GitHub Issue 作成は receiver inbox からの手動操作のみで、自動作成や issue との双方向同期はありません。Slack は local receiver 経由の Incoming Webhook prototype として扱います。受信したフィードバックはローカル receiver に保存されます。widget 内の feedback list はブラウザの localStorage に保存できますが、チーム共有や長期保存用の永続 DB はまだありません。feedback を回収したい場合は endpoint 経由で receiver に送るか、download mode で bundle を保存してください。

未対応:

  • Slack App / OAuth 連携
  • 永続 DB
  • pixel-perfect なブラウザ screenshot capture
  • レビュアー個人の認証(ingest key はプロジェクト単位の公開キーで、個人を識別しない。デモ側ログイン前提の署名付き token は将来スコープ)
  • AI PR 連携

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages