0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vite 8でブラウザエラーが見えても終わりじゃない。AI agentの完了条件を4層に分ける

0
Posted at

pnpm buildは通った。agentも「実装完了」と返した。ところがtool-result panelをクリックすると、browser consoleにruntime exceptionが出る。

AI agentへUI修正を任せていると、この手のずれが厄介です。buildが見ているものと、ユーザー操作後のbrowserが見ているものは同じではありません。

Vite 8には、browser consoleのlogやerrorをdev serverのterminalへ転送するserver.forwardConsoleが入りました。coding agentを検出した場合は自動で有効になる仕組みもあります。

これはかなり便利です。ただし、consoleがterminalに戻っただけでPRを完了にしてはいけない。増えたのは観測経路であって、合否判定ではないからです。

自分なら完了条件を次の4層に分けます。

browser runtime evidence
  -> lint / test / build
  -> GitHub security checks
  -> human scope review
  -> complete / reject

まずforwardConsoleを明示する

検証用projectでは、agent検出だけに任せず設定を残します。

// vite.config.ts
import { defineConfig } from "vite"

export default defineConfig({
  server: {
    forwardConsole: true,
  },
})

明示する理由は、特別な挙動を期待していることをrepository上で読めるようにするためです。agentを起動したshellやIDEによって検出条件が変わる可能性もあるので、fixtureの前提を暗黙にしません。

ここで期待してよいのは、browser consoleの出力をdev server terminalでも観測できることです。少なくとも、この設定だけで次のことまで保証されたとは扱いません。

  • runtime errorが出たらdev server processも非zeroで終了する
  • すべてのbrowser errorを漏れなく捕捉する
  • UIの表示や操作が正しいと判定する
  • E2E testやsecurity scanを代替する

terminalに赤いerrorが見えるようになっても、それを誰が、どの条件でfailにするかは別途決める必要があります。

1 route、2 actionでfailure pathを固定する

いきなり実際の画面全体をagentに巡回させると、どの操作を確認したのか曖昧になります。最初は検証用routeを一つに絞ったほうが扱いやすいです。

route: /agent-runtime-gate
component: tool-result-panel

action A:
  open panel
  -> console.error("[fixture] tool result failed")

action B:
  submit tool
  -> throw new Error("[fixture] invalid tool payload")

Reactなら、fixture自体はこの程度で足ります。

import { useState } from "react"

export function ToolResultPanelGate() {
  const [open, setOpen] = useState(false)

  const openBrokenPanel = () => {
    console.error("[fixture] tool result failed")
    setOpen(true)
  }

  const submitInvalidTool = () => {
    throw new Error("[fixture] invalid tool payload")
  }

  return (
    <section>
      <button type="button" onClick={openBrokenPanel}>
        Open panel
      </button>
      <button type="button" onClick={submitInvalidTool}>
        Submit tool
      </button>
      {open && <div role="status">Tool result</div>}
    </section>
  )
}

これは成功例ではなく、観測経路を確かめるための故障fixtureです。実在するcredentialを入れたり、わざと脆弱なdependencyを追加したりする必要はありません。固定文字列なら、どのactionから出たerrorかも追いやすい。

生成UIのfixture候補を探すときは、SDK、OSS、実装記事をまとめた生成AI UIデザインのリソース集を補助にできます。ただし、選ぶのはtool result、approval panel、streaming listのどれか一つで十分です。凝ったdemoを作るより、failure actionを再実行できる小ささを優先します。

agent-done.ymlは公式schemaではなく、チームの完了契約にする

console forwardingの確認結果をagentの最終メッセージだけに残すと、次のPRではまた判定基準が変わります。そこで、repository側に小さな完了契約を置きます。

# agent-done.yml
# ViteやGitHubの公式schemaではない。チーム側の検証template。
task: genui-tool-result

runtime:
  route: /agent-runtime-gate
  required_actions:
    - open-panel
    - submit-tool
  result: not-observed

commands:
  - command: pnpm lint
    result: not-run
  - command: pnpm test
    result: not-run
  - command: pnpm build
    result: not-run

security:
  - category: code-scanning
    result: unconfigured
  - category: secret-scanning
    result: unconfigured
  - category: dependency-review
    result: unconfigured

review:
  scope_matches_task: pending
  owner: pending

最初からpassで埋めないのがポイントです。これは設定例なので、未確認のruntimeはnot-observed、未実行のcommandはnot-runにしています。

securityの名前も期待する検査カテゴリにすぎません。実際のrepositoryで有効なcheck名、対象branch、適用条件をGitHub上で確認し、その結果へ置き換えます。「GitHubに機能がある」と「このPRでcheckが走った」は別です。

4層のevidenceを混ぜない

結果は一つのbooleanへ急いで丸めず、層ごとに残します。

layer evidence result
runtime route、実行action、forwarded log pass / fail / not-observed
commands command、exit status pass / fail / not-run
security check URL、status pass / fail / unconfigured
review changed files、owner accept / reject / pending

たとえば、browser errorが0件でもpnpm testを走らせていなければcommandsはnot-runです。buildが成功しても、対象PRにdependency checkが設定されていなければsecurityはunconfiguredのままです。

空欄や未設定を成功扱いすると、この表を作る意味がなくなります。

commandのexit statusも、agentの要約ではなくshellの結果から記録します。簡単に確認するだけなら、次のような形で十分です。

pnpm lint
printf 'lint=%s\n' "$?"

pnpm test
printf 'test=%s\n' "$?"

pnpm build
printf 'build=%s\n' "$?"

CIへ組み込むなら、各commandの終了コードをjob resultへ反映させます。ここで保存したいのは「実行したはず」という会話ではなく、commandとexit statusの組です。

GitHub側はruntimeと別のgateにする

GitHubのthird-party coding agents向けドキュメントでは、agentが変更したコードに対するCodeQL、secret scanning、依存関係の検査が説明されています。一方で、利用できる機能や適用範囲はrepository設定やplan、agentによって確認が必要です。

そのため、forwardConsoleでerrorが見えなかったことをsecurityの合格理由にはしません。逆方向も同じです。CodeQLが通っても、click handlerがbrowserで落ちる可能性は残ります。

agent sessionがGitHub Actions minutesやAI creditsを使う点も、runtime gateとは分けて扱います。失敗時に無制限retryするのではなく、最初のfailure evidenceを保存してから、人が続行か差し戻しかを決めるほうが運用しやすいです。

最後のscope reviewは人間が持つ

agentic coding toolの初期採用を調べた研究では、2025年5月から7月に観測された2,361 repositories、25,264件のagentic PRのうち、78.9%でreviewとcommitを同じ一人が担当していました。複数人が関与した割合は11.3%です。

これは現在の全projectへ当てはめられる数字ではありません。ただ、小規模なrepositoryでは判断が一人へ集まりやすい、という運用上の注意にはなります。

最後のreview packetには、少なくとも次をまとめます。

changed files
requested task scope
runtime result
command exit statuses
security check URLs / statuses
unresolved failures
review owner

人間が見るのはコードの雰囲気ではなく、task外の変更がないか、未解決failureが残っていないか、各gateの証拠が揃っているかです。agent自身の「完了しました」は、このpacketの代わりになりません。

再現手順

手元のVite 8 projectへ適用するなら、自分はこの順で進めます。

  1. 現在のVite versionを記録する。
  2. server.forwardConsole: trueを明示する。
  3. /agent-runtime-gateへ2つの固定failure actionを置く。
  4. dev serverを起動し、routeを開いて両actionを実行する。
  5. terminalへ戻ったlogにroute、action、errorの有無を記録する。
  6. fixtureを正常系へ戻し、同じactionをもう一度実行する。
  7. pnpm lint、pnpm test、pnpm buildのexit statusを保存する。
  8. GitHub上で実際に有効なsecurity checkを確認し、人間がdiff scopeをreviewする。

4層すべてに証拠があるときだけcompleteにします。not-observed、not-run、unconfigured、pendingが残っているなら、そのPRはまだ完了していません。

Vite 8のconsole forwardingで、agentはbrowser側の失敗を拾いやすくなりました。そこで止めず、見えたfailureをcommand、security、scope reviewへ渡す。AI agentの速度を活かすには、この地味な完了条件のほうが効きます。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?