PlanGate

HarnessManifest — Harness N / N+1 の同一性と Runtime Activation

Status: Phase 0.1 canon(#1275) North Star: north-star.md §10 / §14 / §15 Role: 「その Run で実際に評価対象となった Harness」を再現可能な identity として固定し、RunEvidence / HarnessExperimentResult から参照できるようにする。V2 artifact budget の 9 件目

1. 問題

harness_version 文字列(Legacy RunEvidence schema の必須項目、#874 / #1025 / #894)は「どの版か」を名乗るだけで、次を再現できない。

したがって Harness N と N+1 の paired comparison(North Star §14)は、harness_version が異なることは言えても 何が違ったかを言えない。Candidate が「効いた」という主張も、ファイルが存在した/plugin にコピーされた事実からは導けない。

2. HarnessManifest 契約

schema_version: "1"
harness_id: sha256:<manifest canonical form の digest> # content-addressed。同じ内容なら同じ id
source_commit: <git sha> # Harness を構成した正本の commit
distribution_digest: sha256:<plugin 配布物の digest> # 配布経路が別なら別 digest
components:
  - type: skill | agent | flow | verifier | prompt | context | routing | eval | hook
    id: <安定 ID。例 skill:ai-dev-plan>
    content_sha: sha256:<ファイル集合の digest>
    installed: true | false # 実行環境のファイルシステムに存在する
    registered: true | false # ランタイムのレジストリ(hooks/list・skill 一覧等)に登録されている
routing_policy_sha: sha256:...
policy_profile_sha: sha256:... # C-3' 等 autonomy profile を含む Policy の digest
verifier_set_sha: sha256:... # Verifier pipeline の定義の digest
model_profiles: # role → model / effort。重みではなく選択の記録
  planner: { model: ..., effort: ... }
  builder: { model: ..., effort: ... }
  verifier: { model: ..., effort: ... }
runtime:
  platform: claude-code | codex
  plugin_version: <semver>
  captured_at: <ISO-8601>

原則:

3. RunEvidence / HarnessExperimentResult からの束縛

# RunEvidence(抜粋)
harness_manifest_ref: sha256:... # 必須。無ければ evidence_status は ready にならない
harness_version: "..." # 任意のラベル

# HarnessExperimentResult(抜粋)
baseline_manifest_ref: sha256:...
candidate_manifest_ref: sha256:...

4. Runtime Activation の 6 段階

「ファイルが存在する」「plugin にコピーされた」だけでは Component が効いたと主張できない。activation を次の 6 段階に分け、どの段階まで Evidence があるかを Run ごとに記録する。

段階 意味 Evidence の所在
installed ファイルとして実行環境に存在する HarnessManifest
registered ランタイムのレジストリに登録されている(hooks/list・skill 一覧・agent 一覧) HarnessManifest
selected その Run でルーティング/呼び出し対象に選ばれた RunEvent(component_selected
fired 実際に実行された(hook 発火・skill 展開・agent 起動) RunEvent(component_fired。hook-events.log 等の一次ログへの ref)
produced_evidence 実行結果が VerificationResult / FailureRecord / artifact として残った RunEvent + evidence refs
influenced_decision その evidence を Decision Engine が実際に参照して判断した RunEvent decision_madeinputs

原則:

5. 独立 Artifact にする理由(artifact budget review)

phase0-migration.md §6 の budget(Phase 0 時点で 8 件)に対し、HarnessManifest を 9 件目として追加する(同 §6 は Phase 0.1 で RunEvent stream を 10 件目として追加している)。既存 artifact への additive 表現を検討した結果を残す。

候補 却下理由
RunEvidence に埋め込む Manifest は Run 横断で共有される identity。Run ごとに複製すると同じ Harness が Run 数だけ存在し、drift を検出できない。RunEvidence は 1 Run の projection であり、Harness 定義の正本にならない
RunState に埋め込む RunState は mutable(revision で進む)。Manifest は immutable。寿命と可変性が異なる
LoopContract に埋め込む LoopContract は Task / Plan 由来。Harness は Task に依存しない
HarnessImprovementCandidate / HarnessExperimentResult に埋め込む baseline 側の identity を Candidate が持つと、Candidate が baseline の記述を書き換えられる(Trust Boundary 違反)

独立 artifact にすると、RunEvidence / RunState / ExperimentResult からは *_manifest_ref(digest 1 本)で束縛でき、既存 artifact への変更は additive な参照フィールド 1 つに留まる。

判断: 独立 artifact として採用。budget を 9 件へ更新(phase0-migration.md §6)。

6. Phase 0.1 で決めないこと