Skip to content
Back to skills

Pipeline

ASecurity

ステージ型パイプライン(declared inputs → declared outputs の実行単位を繋ぐ構成)と その監視ダッシュボードの設計・構築・運用・改善の約束。パイプラインを作る (DAG 設計・stage 追加・component 化)・回す・形を変える・resume する・ 失敗を分類して直す・lab で計測改善する・監視 UI を作る・監視側と実行状態を 同期する、といった作業全般に使う。特定のリポジトリやドメインに限定しない。 ユーザーが /pipeline と入力したら使う。

  • 8 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 2, 2026
researchgonodeapi

Works with

  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add coil398/dotfiles --skill pipeline --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pipeline?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pipeline
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/coil398-pipeline/badge)](https://www.skillsdirectory.com/skills/coil398-pipeline)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pipeline
description: >-
  ステージ型パイプライン(declared inputs → declared outputs の実行単位を繋ぐ構成)と
  その監視ダッシュボードの設計・構築・運用・改善の約束。パイプラインを作る
  (DAG 設計・stage 追加・component 化)・回す・形を変える・resume する・
  失敗を分類して直す・lab で計測改善する・監視 UI を作る・監視側と実行状態を
  同期する、といった作業全般に使う。特定のリポジトリやドメインに限定しない。
  ユーザーが /pipeline と入力したら使う。
---

# /pipeline — ステージ型パイプラインと監視ダッシュボード

複数の LLM / 外部サービス / 決定的処理を繋ぐパイプラインで、繰り返し躓いた構造的判断の正本。
実装仕様は各リポジトリのコードと SSOT に残し、ここには **どんなパイプラインにも効く約束** を書く。

## パイプラインの最小正典

- **各 stage は declared inputs → declared outputs の実行単位**。完了トリガーは実行の終了(exit / `.done` 中継)だけ
- **LLM・worker はパイプラインを制御しない**。verdict 解釈・次段起動・収束・blocked 判定はエンジンが機械的に行う。プロンプト内の LLM 判断にフロー制御を委譲しない
- **transport は adapter であり契約ではない**(CLI spawn / bridge 中継 / SDK 呼出し)。特定ランタイム専用の機構を stage 契約や resume 規則に組み込まない。run 途中で transport を差し替えても成果物契約だけで継続する設計が健全(実測: 同一 run 内で 3 transport を横断して収束)
- **直列化・並列化は engine の責務**。stage 側は自分の I/O だけを知る
- **semantic stage と deterministic stage を分離する**。LLM は recommendation を出し、最終決定(集計・publish 可否・receipt 発行)は決定的 stage が担う。LLM に final blocker の役割を与えない

## 止まってよいのは2つだけ

1. **品質 verdict**(FAIL 系 — コンテンツ判定・検証結果)
2. **human-gate の実承認待ち**

それ以外 — hash・fingerprint・provenance・証跡一致の不一致、照合不成立、改ざん検知、transport 障害 — は **メタデータ記録**であって停止理由にしない。

成果物の再利用可否は2分岐のみ:

- 存在し、記録が現行定義と整合 → 黙って再利用
- 不在・不整合・判定不能 → 黙って当該スコープを再実行(入力が変われば下流へ連鎖)

**なぜか**: 失敗のたびに照合・証明・承認ゲートを足すと、resume 機構が膨張して「普通の運用で止まるパイプライン」になる(実測例: resume 機構が 403→1,724 行に膨張、「証跡がずれた」だけで resume が起動後 0 秒死を繰り返した)。この層を**官僚ゲート**と呼び、新設・維持を禁止する。削除しても別層で再燃し得る — 「コードを1行直しただけで run が死ぬ」「本文は完成しているのに resume が殺される」兆候を見たら全層を洗い直す。照合系の検査は resume 経路ではなく CI に寄せる。

**settle の意味を一箇所に固定する**。「葉 stage が COMPLETED」を run 完了に写さない(**偽 COMPLETED**。手で report を直しても次の葉で再発する)。完了の定義は「最終成果物イベントが journal にあり disk に実体がある」に統一する。

## パイプラインの作り方(DAG 設計と component 化)

### 宣言・解決・実行の3層を分ける

「型ごとに形が違う」は実行グラフの問題ではなく **宣言の編成** の問題として扱う:

- **宣言層**: flat な node リスト(`id`/`kind`/`dependsOn`/`roleRef`/`outputs`)+ 型別 parameters(`enabled`・`roleRef`・`outputArtifactIds`・`mode`・fanout 数)
- **解決層(compiler)**: parameters を型・variant で解決して不要 node を prune し実行グラフを生成。宣言と写像の不一致は exact 検証で fail-closed(黙って無視しない)
- **実行層**: engine は compile 済みグラフだけを見る。型やドメインの知識を持たない

この構造があると「形を変える」は宣言層だけの作業になる(実例: 82 ノード宣言が型解決で 44 ノードの実行グラフに prune される)。直列化・fanout・loop の機構は engine 側で共有され続ける。

### 単一 DAG + 型別 prune vs 別 DAG

- **分離してよい層**: 宣言の編成。大きくなったら fragment + composer で型ごとの flat DAG を生成してよい — 出力が同じ flat DAG なら engine・bindings・resume・correction・validator がすべてそのまま生きる
- **分離してはいけない層**: engine・artifact binding・resume・correction machinery・verdict 語彙・成果物命名規約。複製すると drift しか生まない(実例: 別契約 schema + 独自 runner/resume に分岐した系列は「2つ目の契約宇宙」になり、契約の二重ミラーで形状変更のたびに run が死んだ)
- **型別 DAG 化の等価性条件**: 型別に生成した compile 結果(位相順序 + binding 集合)がモノリス + 型別パラメータの compile 結果と一致すること — 「正しい分離」の唯一の客観的定義
- **component 境界は「変動点 × correction-loop 閉包」で引く**。loop をまたぐ境界分割は reentry 経路を壊す。典型境界: 共有 entry → 型固有 producer(interface 成果物だけ固定し producer 名は変えてよい)→ 共有閉包(fanout→synthesis→critic→patch の loop が閉じる単位を割らない)
- **生成物はチェックイン + CI regen-diff 検査**。共有 component を直すと全型に波及するので「生成せず手で育てる」運用は drift で死ぬ
- **分離の動機を実測で確認する**: 「その型の失敗」が DAG 形状起因でない(timeout policy・stage 実行問題等の)実測があるなら、構造分離は over-scope

### fanout / variant / provided input の3パターン

- **fanout(数が決まっている並列)**: shard 配列(`ordinal`/`identity`/`profileRef`/`artifactId`)+ 「数 → artifactId リスト」の逆引き表(cardinalityOutputs)を宣言し、compiler が個数と集合の exact 照合で fail-closed
- **variant(同型の異種)**: variant → 入力 artifactIds のマップを宣言し、variant 必須・未知値拒否を compiler が検証
- **provided input(外部供給)**: producer stage を起動せず外部 artifact だけで入力 contract を満たすモード。別パイプラインの産物を入力にする「入力提供のみの component(ノードなし)」を宣言だけで表現できる。compiler は producer が binding に含まれないことで非起動を検証する
- 条件付きグループはグループレベルの `when` 式で宣言(compiler が `when` を exact 文字列で受理)

### correction loop の設計不変条件

- **forward DAG と back-edge を分離**: `dependsOn` は DAG(非巡回)のまま、再入場は loop メタデータだけで表現。DAG に直接 back-edge を書かない
- **loop 宣言の完全な要素**: owner(判定を出す node)・decisionSource(owner 出力への参照)・transitions(verdict → reentryTarget)・counterRef(上限パラメータ参照)・onExhaustion・coversGates・priority
- **bounded**: `maxRounds` は有限、`onExhaustion` は stop(使い切りで強制 PASS にしない)。ラウンド証拠は `toRound = fromRound + 1` で owner/verdict/contentHash の整合を検証
- **生成 stage は establish-once**: 最初に産物を作る stage(writer 等)は correction loop の再入場先にしない。修正は専用 patch stage への reentry。validator + check script + runtime supervisor の多層で強制する(実例: writer/初期 fanout への reentry を 3 層で fail-closed)
- **evidence の閉包**: 各 loop の再入場が必要とする前ラウンド成果物を `loopId | reentryTarget | previousRoundArtifactId | transitionVerdict` の binding で宣言し consumer を exact 指定。round 1 は「前ラウンドなし」sentinel、round 2+ は直前ラウンド snapshot 必須、fanout 時は全 shard が同一 evidence を入力
- **patch が「全部書き直し」しない仕組みを用意する**(whack-a-mole の発生源。計装層の節を参照)

### stage を追加するときの全登録面

stage・role・artifact の追加は「1ファイル宣言」では済まない。健全なパイプラインでは **契約が複数の検証層でミラーされている** — どれか一つ抜けると compile か CI で fail する設計が正常。一般形:

1. workflow 定義に node 追加(`id`/`kind`/`dependsOn`/`roleRef`/`outputs`)
2. 宣言パラメータ: 型定義(`enabled`/`roleRef`/`outputArtifactIds`)、artifact manifest(物理パターン・最低件数・schemaId・条件付きマーカー)、型の artifactSet 参照
3. 入力契約: consumer 側の requiredArtifactIds、条件付き入力は `when` 式 + 解決先 ref
4. compiler: resolver 分岐・active artifacts 分岐・manifest conditional の skip・conditional 入力の受理
5. 論理出力 → 物理 artifact の binding。決定的 producer なら producer 定義 + operationId の用途別リスト登録
6. contract catalog(contractId/nodeId/roleRef/入出力/schemaId/適用型)
7. **role 追加なら role ファイル + manifest/catalog の両方**。片方だけでは解決しない。missing/empty role は fail-closed
8. semantic-oracle(正準入力集合の期待値)と CI check スクリプト — 両方がミラー層
9. mutation test・compiler test(enabled/disabled/不正 override/未知参照の pin)
10. **fixture・lab case・docs の同期** — params 変更はテスト fixture や lab case の複製にも波及させる

correction loop に関与するなら correctionLoops + reentryBindings + evidenceConsumers も。フェーズ名を消費するもの(detect-phase・進捗集計・dashboard)があればそれも登録面。

## 失敗の分類(再発時はまず型を特定する)

| 型 | 症状 | 構造的原因 | 正しい対処 |
|---|---|---|---|
| 官僚ゲート | 証跡・pin・fingerprint 不一致で resume・進行が殺される | 照合を admission gate 化 | 照合は記録のみ。品質 verdict と human-gate だけが止まれる |
| whack-a-mole | patch が全部書き直す → 前回の指摘が別の形で再発 → FAIL が無限供給 | 修正に必要な情報が不足(mustFix の機械列挙・mustPreserve・台帳がない) | retry やゲート追加ではなく **情報層**で担保: 機械列挙・保存契約・closure attestation・差分計測 |
| transport 障害 | `RESULT_NOT_SUBMITTED`・timeout・worker 消失・spawn ハング | adapter 層の障害を stage 失敗と混同 | stage 失敗として記録し resume で再 dispatch。契約に transport を混ぜない |
| evidence 死 | 前ラウンドの成果物が構造的に参照されない(静的展開と staleness 判定の衝突など) | データフローと証跡解決の不整合 | aggregate の inputHashes → 実ファイル hash 逆引き等、実測で証跡を辿る |

追加の障害パターン:

- `.done` を worker が早期に書く → 下流が途中状態を読む競合(「完了してから書く」契約を明示)
- structured result schema への過度な依存 → 本文が妥当でも FAIL(salvage 経路を用意)
- dev server 偽陽性 → 本番 bundle(`vite preview` 相当)で検証する
- 大きな成果物の一括書き込み → kill で途中切断、不正 JSON が残る(小分け書き込み+読み直し検証)
- 親子 run で occupancy/lease が「途中 state を新規起動から塞ぐ」→ stale RUNNING や ABANDONED が溜まる。occupancy 判定と掃除規約を決める
- **外部 quota 枯渇は transport 障害と分けて記録する**。429/rate-limit 系は「一定時間 retry しても無駄」な時間窓の失敗 — 連続するなら provider の usage endpoint で残量層(5h/週/月など)を直接確認してから再開間隔を決める。retryable として放置すると bounded retry を燃やし尽くすだけ(実例: OpenCode Go `GoUsageLimitError`、週次 100% で ~6日停止)

## resume の契約

- resume は **現行の宣言で live 再コンパイル**する設計が主流。run 途中に宣言を変えると **新しい形で続行**される — workspace 内の宣言スナップショットは再コンパイルに使われない
- 起動フラグ一式を再指定する(`--run-id` だけでは起動しない実装が多い)
- worker 消失・kill・transport 障害は stage 失敗として記録 → resume で同一 prompt の再 dispatch(prompt は byte 一致で再生成されるのが望ましい — 番号・内容が同じなら中断前と同じ dispatch を再発行できる)
- **verdict 成果物は評価対象に紐付ける**: review・判定系の成果物は「どのバージョンを評価したか」をファイル名・本文メタに必須化する。これがないと resume の replay が旧バージョンの verdict を新成果物に誤適用し、途中工程を近道して成果物を退行させる(実測で発生)。gate は「現行対象を subject に持つ成果物」のみ受理する純粋導出に統一し、プロセス内フラグで判定しない(フラグは resume で再構成できない)
- 成果物契約は「存在する」→「**存在しパース可能**」に引き上げる。不正な成果物が残ると resume しても同じ箇所で再クラッシュする無限ループになる
- resume cursor(metrics 等)の破損は空 cursor へ degrade + WARN(kill が write 中に刺さると truncated JSON が残る)
- positional な dispatch 番号を使うなら、同名の `.done`/`.result` は dispatch 開始時に除去する(前回試行のシグナルで即時 resolve して worker が走らない)
- **状態イベント store は append-only + immutable segment + 増分 replay にする**。「node 実行ごとに全イベントを再読する」構造は O(nodes×events) で、数千イベント級になると RSS が GC 上限に張り付き実質停止する(実測: 8000ファイル/110MB を毎回再読で 4.5 時間空転 → revision-keyed キャッシュで 483ms→6ms)。イベントを `Object.freeze` しておけばキャッシュ共有も安全
- **resume boundary が期待する nodeId と compiler が emit する nodeId を同じ座標語彙で書く**。「sealed tip の直下に `patch:rN`」を期待するのに compiler が selector 分岐(`:waive:`/`:reverify:`)経由でしか emit しない、のような語彙のズレは「graft 不発 → replay だけ空転 → BLOCKED 固定」の直接原因になる。継続 continuation は「journal の最深実在トークン(selector 分岐を含む)」を tip として派生させ、期待 node が compile 済みグラフに実在することを compile 時に検証する
- **「前提条件の達成」を「スキップ条件」に流用しない**。「salvage 完了済みなら return」が「salvage 完了後にだけ発火する reconciliation」を恒久的に殺した実例がある — early-return のガード対象と、機構の発火前提が同じ出来事を指していないか確認する
- 合成 resume: run dir をコピーして成果物を置くだけで resume 対象になる設計にしておくと検証が楽
- **scope 指定 resume の識別子はバイト厳密一致**。node instanceId(座標語彙を含む長大な ID)はイベントログから機械抽出して渡す — 手転写で `:`→`/` を1箇所潰すと、scope が何も警告なく unmatched になって全 composite が replay されるだけの静黙不発になる。scope 要求の受理時と settle 時に durable イベント(受領 ID 一覧・matched/unmatched + 最近傍候補)を残すと転写ミスが即座に可視化される
- **死んだ RUNNING attempt の回収 close-out は専用の遷移 identity で書く**。回収用の `RUNNING→FAILED_RETRYABLE` を新しい代替 attemptId で書くと、直後の dispatch 失敗が同じ attemptId・同じ edge を書いて idempotency 衝突で wedge する。かといって previousAttemptId 帰属は、過去の誤帰属 edge が残ると再衝突する。`<attemptId>:recovery-close` のような hop ごと一意の scope id で記録し、実装固有の詳細と回帰テストは対象プロジェクト側で管理する。
- **quota が乏しいときは resume scope を失敗 leaf に絞る**。広い scope は配下の全 descendant を force-rerun するため、成功するはずの上流 stage が貴重な quota 枠を先取りし、真に必要な失敗 stage が饿死する(実測: evidence が毎 hop 完走して plan が永遠に 429)
- **自動 resume 分岐は全て durable な発火イベントを出す**。複数の recovery 経路が存在する runner で「どの分岐が resume を横取りしたか」が静黙だと、resumeFrom が届いているのに scope 不発のような不可解な状態になる。入口で recoveryReason を記録するだけで全分岐をカバーできる

## 品質ゲートの分類(blocking / advisory)

- **常に blocking**: 数値・算術不整合、主張の内部矛盾・因果混同、根拠なき断定・出典偽装、必須契約違反、保存対象(mustPreserve)の破壊
- **advisory**(pass-with-known-issues 相当で通過可): 文体・リズム・生成物らしさ、読者好み、消費側 accessibility、改善提案
- 「指摘ゼロの FAIL」を許容判定に降格しない。pass-with-known-issues を完全失敗と同一視しない
- 決定的 checker(export 整合・数値 SSOT・必須構造)が final publish ゲートに向く。LLM verdict は upstream の修正信号としては有効でも、skip・forced-pass・監査タイミング起因で実効性が揺らぐことを実測済み

## パイプラインの改善の仕方

### 回しながらテストし、実測で改善を決める

改善は「止まって相談」ではなく **実行中の計測ループ** で決める:

- **run を止めずに診断する**。stage が失敗・停滞していても journal / gateway-events / reservation / shadow 成果物は読める。まず実物の状態を見てから動く
- **孤立 probe で再現する**。本 run の retry を浪費する前に、失敗した stage と同じ入力・role・出力契約を gateway に直接流す最小再現を組む(実例: 実 role md + 実 staged inputs を `gateway.run()` に渡すプローブ。RESULT_NOT_SUBMITTED 系は `error.diagnostics` の assistantTextPreview / finishReason / executedToolCount に生存情報が入る)。本パイプラインを回さず失敗型を確定できる
- **対照実験で切り分ける**。同じ endpoint で「小さい write_output」「大きい write_output」「別タスク」を流して、契約・payload サイズ・タスク形状のどれが原因かを潰す
- **同型失敗が3連続したら構造問題として扱う**。stochastic retry に賭けず、タスク形状・契約・経路のどれかを変える(実例: endpoint が `<|DSML|>` markup を漏らし tool call が degenerate 化 → 4 連続空 submit で endpoint 限界と判定)
- **改善するかどうかも実測で決める**。「直せるか」を推測や確認ではなく、小さい実験の成否で判定してから本線に適用する

### lab / shadow 経路を用意する

- **production 正本と実験 snapshot をバージョン分離**(case = 入力一式 + role/プロンプトセットのバージョン dir)。同じ case で role・計装の差分を A/B 計測し、品質退化なしを確認してから本番に port する
- lab の run は production と同じ stage 契約・同じ resume 規則で動かす。lab だけ別機構にすると「lab で通って本番で死ぬ」になる
- **失敗した実 run を lab case に fixture 化する**。失敗資産が計測基盤に還流する構造を作る(実例: 実運用の失敗ケースを lab の case として再現・修正検証)

### 収束を止めるのは retry ではなく情報層

whack-a-mole(patch が全部書き直す → 前回の指摘が別形で再発 → FAIL が無限供給。実測 49 ラウンド BLOCKED)の根治は「情報層」:

- **mustFix の機械列挙**: 「見つけたら直せ」ではなく、エンジンが FAIL 成果物から blocking 指摘を抽出して patch へ列挙注入。列挙外の suggestions・自由記述を変更入力にしない(「走査せよ」→「見つけた全箇所を列挙せよ」の言い換えが効いた実績)
- **mustPreserve 台帳**: PASS 観点・保存条件を累積台帳化し、patch が触れるなら両条件を満たす統合を要求(ついで直しの禁止)
- **closure attestation**: findingId ごとの RESOLVED/UNRESOLVED を成果物に書かせ機械が集計
- **patch 差分計測**: changeRatio(変更行比率)で「外科修正か全部書き直しか」を数値化(健全な外科修正の実測値は 0.01〜0.17)
- **退行スキャン**: 前ラウンド PASS の軸は全量再レビューではなく差分走査で済ませる(時間短縮と PASS→FAIL 退行の計測を両立)
- **判定不能は収束に数えない**: verdict 解析不能・dispatch 失敗の軸があるラウンドは「未完」として resume で欠けた軸だけ再 dispatch

### 計測すべき収束形状

ラウンド数・mustFix 件数・resolved / unresolved / regressed・patchChangeRatio・軸の PASS→FAIL 退行数。「収束したか」ではなく「**何ラウンドで・退行ゼロで・未解決ゼロで収束したか**」を見る。run 間のばらつき(mustFix 6→4→7 で収束形状が同じ)は正常。

- **検証は本番と同じ経路で**: dev server の偽陽性は本番 bundle で排除、図・画像は機械検査と別に実画像目視
- **失敗の情報を stage に流す**: retry 時は detailCode → 修正指示の対応表を prompt に注入し、feedback は上限 bounded にする

### transport の堅牢化

- timeout は「即 resolve(error) → grace → プロセスグループ kill」。SIGTERM を無視する worker で永久ハングし、孫プロセスが stdout pipe を握ると子が死んでも EOF が来ない(実測で発生)
- ハーネス差し替え(CLI→bridge→別 CLI)で成果物契約だけで継続できることを確認しておくと、provider 障害時の復旧が「別 transport で resume」になる
- `.env` は export なしなら `set -a; source .env; set +a` が必要(単純 source では子に届かない)

## 監視ダッシュボードの作り方

### アーキテクチャ: 単一 snapshot API への一本化

- **観測データの単一契約を1本の snapshot エンドポイントに集約する**。サーバがファイルシステム・プロセス・ログを一括走査して 1 JSON を返し、ブラウザ UI・CLI・TUI は全て同じ snapshot を読む。クライアントごとに独自走査させると状態判定ロジックが drift する
- snapshot には生データだけでなく **UI が必要な派生値**(counts・active リスト・activity 時系列・稼働フラグ)までサーバ側で計算して入れる。しきい値・スキャン範囲等のメタ情報も snapshot に載せ、UI 側にハードコードしない
- **定期ポーリング + fingerprint 差分描画**で十分(WebSocket 不要)。間隔は「人が古いと感じない下限」とスキャンコストのバランス(実例: 5 秒・応答 ~56ms/438KB でキャッシュ・部分取得は不要と判断)。client は fingerprint 比較で変化した DOM だけ更新する。`force` 更新を fingerprint skip 条件で上書きしない
- **`bootId` でサーバ再起動を検知**: プロセス起動ごとに一意 ID を snapshot に含め、client は変化で「再起動」バナーを出す。自動 reload ではなくユーザー確認(フォーム入力中の強制リロード回避)。fetch 失敗時は最後の正常 snapshot を保持して「fetch failed」を示す
- **既定 loopback**。外部公開は明示フラグ + 認証必須。ファイル本文配信は許可ルート配下に厳格限定(パス正規化 + symlink 拒否)し、外部公開時は本文を返さずメタのみ
- **実行系ごとにモードを分ける**(production / calibration / lab 等):モード別にデータ源と UI セクションを割り当て、ヘッダにモード別稼働インジケータを出す。非表示セクションは `hidden` で描画・計測・イベントの対象外にする
- **走査は壊れたファイルで落とさない**: 監視対象は run 中に書き換わるので fs 読み取りは全て例外捕捉で null/空を返し、1行の失敗が snapshot 全体を落とさない(実害: `new Date(null)` で API が 500)
- **ノイズ分離**: 「中断・未完」(WIP)やアーカイブ済みを active 一覧から fold 分離する(実測: active の 96% が WIP だった)。アーカイブ判定規約が環境依存なら暫定と明記する

### 実機検証ワークフロー

- 「UI が正しい」は **DOM の textContent・API の値・スクリーンショットの3つを別々に確認**して初めて言える。API が正しくても描画バグ・ソート・fingerprint キャッシュで表示が違うことがある
- `pageerror` / console error / HTTP≥400 を全ページ遷移・全操作で収集する。初回表示・別モード・別タブでだけ出るエラーを見落とさない
- screenshot は DOM/API と一致を確認してから撮る。polling 途中・再起動直後・非表示タブの screenshot は古い/空になり得る
- **非表示要素を測らない**: `hidden`/`display:none` の高さ 0 は仕様であって欠陥ではない。計測・scroll・操作の前に可視性を確認し、重い描画は `clientWidth===0` で早期 return
- **非同期 fetch に stale ガード**: 応答が返るまでに選択が変わったら結果を捨てる(リクエスト時の選択キーと応答時のキーを照合)
- **URL に全選択状態を持たせる**(タブ・フィルタ・選択・展開): reload/back/deep link で復元。URL 由来の値は許可値にクランプする
- 実測で効いた改善: mark 遷移の Δ バッジ(tick 間の状態変化を可視化)・stale 超過時間の行内表示・detail の permalink + ファイル preview・sticky thead・大規模グラフは Map/NodeList キャッシュ + rAF 集約

## 監視側が実行状態を読む方法(dashboard ↔ pipeline の同期)

### 進行中の identity は settle 前情報源から補完する

settle 後の最終レポートだけでは「いま何が動いているか」は読めない — **実行中は report がまだ書かれていない**。情報源を「新しさ」と「確度」で優先順位付けする:

- **journal(状態遷移ログ)の末尾が report の mtime より新しければ run は live**。report は settle 時点のスナップショットなので、resume/再 dispatch で journal が伸び続けている run は journal と実行予約を優先する(`live = journalTs > reportMtime`)
- run の identity(runtime/model/profile)は複数箇所に分散し得る。優先順位の一般形: **gateway event → attempt reservation(実行予約ファイル)→ profile 定義 SSOT**。report は settled 時だけ正
- 「いま走っている stage」は journal tail を逆順に走査して最後の RUNNING/RETRYABLE 系遷移を拾う。in-flight attempt は gateway event がまだ無くても reservation に identity が出ている(実害: 進行中 stage の model 欄が空だった原因が gateway event 未到達)

### raw state と UI mark を分離する

- エンジンの raw state(PENDING/RUNNING/COMPLETED/FAILED_RETRYABLE/BLOCKED_*/CANCELLED 等)と UI 表示語彙(PASS/FAIL/FLAKE/RUN/HUNG/WIP/TODO)は **別物**。変換ロジックを1関数に集約し、UI は mark だけ描画する。「失敗」を1語で済ませず、優先順位付きの一意ルールにする
- **HUNG = `running` 状態だが heartbeat/更新が stale 閾値超過**。status ファイルだけ残って実体が死んでいる run を「正常稼働」と誤認しない。HUNG 行には stale 超過時間と「runner プロセスがあるか」のヒントを出す
- **FLAKE(retryable 失敗)と FAIL(停止・ブロック系)を分ける** — 「様子見」と「要介入」を区別できる。WIP(成果物はあるが非実行)と TODO(signal なし)も分ける

### 読み取りの堅牢性

- JSONL ログは **末尾だけ部分読み**(末尾 N KB を読み、先頭の不完全行を捨ててから各行を個別 parse)。大きな journal を全文読むとメモリを食う
- run 一覧は mtime 降順 + 件数 cap
- 監視側からの mutation(stale 状態の掃除・sweep)は既定 OFF の opt-in にし、読み取り経路と分ける
- **失敗の内因と retry 位置を run 一覧に出す**。最終 gateway event の `providerError`(429/quota/接続障害の区別)と supervisor の forward hop 位置(`forward_hop_retry_wait hopN` 等)を snapshot に含めると、「コードの失敗か quota 待ちか」が一覧から即判る(実例: `scanPipelineRuns` で gateway-events/forward-events の tail から拾う)

## 運用の罠(実測済み)

- 外部 API trial / 検証枠は本番の **数倍遅い**ことがある(実測 5〜7 倍)。疎通・契約・provenance・retry 経路の確認には十分だが、完走の実用的な検証は本番経路で行う
- `params` 変更は run 途中でも resume で反映される。形状比較を測るなら基準 run を先に完走させてから変えるか、変わることを前提にする
- timeout は constructor 既定値ではなく **request 単位の policy** で解決される経路を確認する(profile に書いても gateway が読まなければ届かない)
- 並列に見える stage でも実 spawn は直列 lease されていることがある — stage の RUNNING 時刻と worker spawn 時刻を混同しない
- 長時間走る worker は timeout 既定を実測から取る(実例: 旧 30 分既定が健全な 35〜60 分の dispatch を潰していた → 90 分に)
- resume 中の worktree で vendor/依存ファイルを消す移行ジョブを同時に走らせない — import が `MODULE_NOT_FOUND` で死ぬ運用事故になる
- **即失敗する retryable エラーは bounded retry を数分で燃やす**。429/transport が即座に返る環境では hop 間に設定可能な delay を挟まないと「16 hop の回復窓」が数分で尽きる。quota 待ちなら長い delay で監視窓を伸ばす。
- **汎用 worker エラー(ASSISTANT_EMPTY 等)に基底の provider/HTTP エラーを乗せる**。`finishReason:"error"` だけ記録すると quota 枯渇と endpoint 障害と契約問題が区別不能になる。session/assistant/message のエラーフィールドを防御的に走査して redact 済み `providerError` として durable event に残すと、本当の原因(実例: `429 GoUsageLimitError`)が一発で見える

## 知見の出所(事例)

繰り返しの実運用、対照実験、障害分析から得た一般化可能な運用知見をまとめる。具体的なプロジェクト名・コード位置・内部資料は各プロジェクトのドキュメントに記録し、この共有スキルには再利用可能な原則だけを置く。

## このスキルを使うときの約束

- 失敗を見たらまず **4型のどれか** を実測で特定してから直す。症状だけを patch しない
- 照合・証明・承認系の停止条件を新設しない
- 形を変えるときは宣言層(parameters / manifest / catalog)で行い、engine・contract の骨格は変えない
- stage 追加は **全登録面をリスト化してから着手**する。ミラー層を1つでも抜くと compile/CI で fail する
- 「パイプラインが通らない」と「成果物の品質が悪い」は別問題として切り分ける。前者は官僚ゲート・transport・evidence、後者はコンテンツ verdict
- 監視 UI を作るときは snapshot API 一本化・bootId・安全な fs 読み取りから始める。クライアント独自の状態判定を増やさない
- 改善は lab で計測してから本番へ。「収束形状(ラウンド数・退行 0・未解決 0)」を見ずに「動いた」で終わらせない

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…