phasegate 0.254.0 → 0.264.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.ja.md +6 -3
  3. package/README.md +6 -3
  4. package/docs/contracts/attestation-v2.schema.json +110 -0
  5. package/docs/guide/cli-reference.md +12 -1
  6. package/docs/guide/configuration.md +56 -0
  7. package/docs/templates/ci/aidlc-gate.yml +42 -2
  8. package/package.json +1 -1
  9. package/scripts/harness/agent-integration/application/dto/open-world-obligations-context-dto.ts +30 -0
  10. package/scripts/harness/agent-integration/application/ports/world-obligations-query-port.ts +30 -0
  11. package/scripts/harness/agent-integration/application/usecases/get-open-world-obligations-context-usecase.ts +66 -0
  12. package/scripts/harness/agent-integration/infrastructure/adapters/world-model-open-obligations-query-adapter.ts +58 -0
  13. package/scripts/harness/agent-integration/presentation/session-start-hook.ts +37 -1
  14. package/scripts/harness/agent-integration/presentation/world-obligations-session-context.ts +60 -0
  15. package/scripts/harness/attestation/application/dto/attestation-document.ts +17 -4
  16. package/scripts/harness/attestation/application/mappers/attestation-record-mapper.ts +55 -4
  17. package/scripts/harness/attestation/application/ports/world-snapshot-root-provider.ts +10 -0
  18. package/scripts/harness/attestation/application/usecases/produce-attestation-usecase.ts +33 -7
  19. package/scripts/harness/attestation/composition-root.ts +5 -0
  20. package/scripts/harness/attestation/domain/entities/attestation-record.ts +37 -2
  21. package/scripts/harness/attestation/index.ts +7 -1
  22. package/scripts/harness/attestation/presentation/handlers/attest-handler.ts +5 -2
  23. package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +35 -8
  24. package/scripts/harness/config-foundation/application/mappers/world-model-config-mapper.ts +15 -0
  25. package/scripts/harness/config-foundation/domain/harness-config.ts +67 -87
  26. package/scripts/harness/config-foundation/domain/services/preset-resolution-service.ts +77 -88
  27. package/scripts/harness/config-foundation/domain/value-objects/world-config.ts +198 -0
  28. package/scripts/harness/config-foundation/index.ts +14 -15
  29. package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +24 -0
  30. package/scripts/harness/config-foundation/infrastructure/presets/standard.json +24 -0
  31. package/scripts/harness/config-foundation/infrastructure/presets/strict.json +24 -0
  32. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +83 -0
  33. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +83 -0
  34. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +18 -4
  35. package/scripts/harness/integrations/pre-commit.ts +169 -27
  36. package/scripts/harness/main.ts +174 -130
  37. package/scripts/harness/traceability-model/application/dto/changed-design-fragment-dto.ts +31 -0
  38. package/scripts/harness/traceability-model/application/facades/design-change-read-facade.ts +14 -0
  39. package/scripts/harness/traceability-model/application/ports/staged-design-change-source-port.ts +9 -0
  40. package/scripts/harness/traceability-model/composition-root.ts +5 -0
  41. package/scripts/harness/traceability-model/index.ts +9 -0
  42. package/scripts/harness/traceability-model/infrastructure/adapters/git-staged-design-change-adapter.ts +155 -0
  43. package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +31 -0
  44. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +34 -0
  45. package/scripts/harness/validator-system/composition-root.ts +21 -6
  46. package/scripts/harness/validator-system/domain/ports/world-constraint-admission-policy-port.ts +28 -0
  47. package/scripts/harness/validator-system/domain/ports/world-constraint-rederivation-policy-port.ts +11 -0
  48. package/scripts/harness/validator-system/domain/services/design-change-declaration-policy.ts +75 -0
  49. package/scripts/harness/validator-system/domain/services/world-constraint-admission-service.ts +78 -0
  50. package/scripts/harness/validator-system/domain/services/world-constraint-rederivation-service.ts +76 -0
  51. package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +4 -0
  52. package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +38 -16
  53. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-admission-adapter.ts +56 -0
  54. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-rederivation-adapter.ts +56 -0
  55. package/scripts/harness/world-model/application/dto/pinned-design-endpoint-dto.ts +19 -0
  56. package/scripts/harness/world-model/application/dto/world-resolved-config-input.ts +92 -27
  57. package/scripts/harness/world-model/application/dto/world-snapshot-root-dto.ts +8 -0
  58. package/scripts/harness/world-model/application/facades/pinned-design-endpoint-facade.ts +63 -0
  59. package/scripts/harness/world-model/application/facades/world-snapshot-root-facade.ts +19 -0
  60. package/scripts/harness/world-model/application/usecases/derive-world-obligations-use-case.ts +3 -1
  61. package/scripts/harness/world-model/composition-root.ts +62 -33
  62. package/scripts/harness/world-model/index.ts +11 -0
  63. package/scripts/harness/world-model/infrastructure/adapters/attestation-fact-extractor.ts +48 -13
  64. package/scripts/harness/world-model/infrastructure/adapters/file-system-world-control-repository-adapters.ts +6 -4
  65. package/scripts/harness/world-model/presentation/cli/world-derive-command-handler.ts +6 -2
package/CHANGELOG.md CHANGED
@@ -7,8 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Fixed
11
+
12
+ - **WI-309 — WI-305 validator domain reflection repair** — `DesignChangeDeclarationPolicy`を実装・配線しながらvalidator-system `domain_model.md`へのWI-305累積反映を欠落させ、story reflection corpusが検出したbaseline外違反を正規に解消。exact `corpusRole + DeclaredKey`照合、pinned change限定、Work-Item trailer intersection、unique sorted finding、local fast-path / L3 authority境界を実コードどおり記録し、baseline / allowlistには触れていない。
13
+
14
+ - **WI-308 — CLI large stdout drain** — self-repoのWorld enforcement有効化により`validate --layer L2 --json`が604件のadopted-legacy warningを含む64 KiB超のJSONとなり、`console.log`直後の`process.exit`がpipe bufferをdrainせず末尾を切断する回帰を修正。direct stdout resultを返す全top-level CLI経路を共通graceful exitへ統合し、warningを省略せず任意サイズの完全な出力と既存exit codeを維持する。64 KiB超を必須条件とするprocess E2Eで`--format json` / `--json`双方を固定し、同E2E fileの全subprocess caseへ明示60秒timeoutを適用した。
15
+
10
16
  ### Added
11
17
 
18
+ - **WI-307 / H17-19 — World production-ready CI / template regression(WM-24)** — self-repo CIをtest → requirement-test matrix生成 → pure `world:derive --json`二重byte一致 → authoritative L3 → attestation v2 produce / verify → integrity verifyのtrust chainへ整列。保存obligation reportをCI入力にせず、runner tempの二出力とv2 evidenceだけを比較・検証する。bundled `aidlc-gate`はconfig JSONをfail-closedで読み、`world.enabled:true`の場合だけmatrix後のderive二重一致を実行するため、false / absentの採用projectは既存L3契約を維持する。regression-suiteにactual processの3 `world:*` command、`phasegate-world-cli/v1` envelope、exit 0 / 1 / 2、CI source order、package surfaceのcontract testを追加。README / README.ja / CLI guideを登録済み`L2-017` / `L3-008`、bounded SessionStart、attestation v2 root pin、self-repo dogfood有効のproduction仕様へ更新し、H17-19を同一着地でrequiredとして登録した。Phase CのCI統合により、warning-only validatorの`passed:false`とaggregate `allPassed:true`が同時に公開される潜在矛盾を顕在化。harness-apiのpublic ci-check projectionで同一`failOnWarning` policyをper-validator結果にも適用し、warning diagnosticsを保持したまま既定時は`passed:true`、strict時は`passed:false`へ一貫させ、attestation INV-1を緩和せずv2 smokeを成立させた。
19
+
20
+ - **WI-306 / H17-18 — Attestation v2 World snapshot root pin(WM-23)** — `phasegate-attestation/v2` / `https://phasegate.dev/attestation/gate-run/v2`を追加し、World canonical `corpusRoot`を必須`worldSnapshotRoot`としてattestationDigestのcanonical payloadへ封印する。fragment / node個別digestは保存せず、published `attestation-v2.schema.json`もroot一件だけを許可する。attestation applicationはconsumer-owned plain root providerだけを受け、top-level harness compositionがworld-model public `WorldSnapshotRootFacade`からrootを注入するため、attestation→world-model importを作らない。provider未配線のprogrammatic produceと全v1 verifyは無期限互換のv1を維持し、schema / predicate / root presence mismatchやprovider failureはv1へdowngradeせずfail-closed。World owner projectionはv1 / v2を受理しながらv2 root self-referenceをcorpus projectionから除外する。v1 / v2 produce→verify、root改竄、published schema、projection determinismをtestで固定し、H17-18を同一着地でrequiredとして登録した。
21
+
22
+ - **WI-305 / H17-17 — Design change declaration / reflection hook(WM-22)** — commit-msg経路へpin済み設計fragmentの変更宣言checkを追加。traceability-modelのpublic plain DTO facadeがGit index / HEADから内容の変わったexplicit product / inception fragmentだけをrole、DeclaredKey、path、change kind、sorted `@work-item-id`、明示`@world-reflects`付きで観測し、world-modelのpublic facadeがconstraint repositoryを露出せずclaimant / premiseのexplicit fragment pinだけを投影する。validator-system policyは両者をrole + keyでendpoint-symmetricに突合し、pin済み変更fragmentのWork Item集合とcommitの`Work-Item: WI-NNN` trailerに共通IDがない場合だけnon-bypassableでblockする。unpinned / legacy whole-file / ADR / source変更へblocking面を広げず、`world.enabled:false`ではproviderを呼ばず従来挙動を維持。Git / control observation不能はfixed code warningへfail-openし、local hookは偽造可能なfast-path、authoritative trust rootはL3-008であることを出力する。H17-17を同一着地で`planned -> required`として登録し、changed fragment / pin projection / matching・mismatch・unavailable contractをunit / Git fixture testで固定した。
23
+
24
+ - **WI-304 / H17-16 — SessionStart open World obligations summary(WM-21)** — agent-integrationのSessionStart経路へconsumer-owned `WorldObligationsQueryPort`、plain context DTO、priority / adopted-count usecase、bounded presentationを追加。infrastructure adapterはworld-model public `createWorldModelModule`だけを消費し、保存済み`.harness/world-obligations.json`を読まず`writeReport:false`でcurrent corpusからpure deriveする。`new-structural` / `invalid-declaration` / expired waiverをcleanup-required / waivedより先にstable keyで表示し、adopted-legacyは個別列挙せず件数一行へ集約。World sectionはconfig値にかかわらず最大5件 / 2000 Unicode scalar、entry途中切断なし、決定的省略行を保証し、reason / diagnostic details / corpus prose / full reportをpromptへ中継しない。`world.enabled:false`またはsession summary無効時はquery未実行・非表示、config / derive不能時はrepository由来reasonを含まない固定一行warningへfail-openしてhook exit 0を維持する。self-repo E2Eで604 adopted-legacyが一行だけになりfingerprint本文を注入しないことを固定し、H17-16を同一着地で`planned -> required`へ進めた。
25
+
26
+ - **WI-303 — self-repo World enforcement 有効化(dogfood)** — CP-4 合格を受け `phasegate.config.json` に `world.enabled: true` を設定。以後 self-repo の L2 は L2-017(constraint admission fast-path)、L3 は L3-008(authoritative re-derivation)を実際に実行する。604 件の adopted-legacy baseline は非 blocking warning として可視化され、新規構造違反・不正宣言は fail-closed。実測コストは両ゲート合計 2 秒未満。
27
+
28
+ - **WI-302 / H17-15 — L3-008 authoritative World constraint re-derivation(WM-20)** — ADR-030のCI trust rootとADR-035 / ADR-037のnon-authoritative generated report contractを執行し、`L3-008 world-constraint-rederivation`をValidatorId、default registry、RunL3、composition-rootへ登録。専用consumer-owned port / service / infrastructure adapterが呼出しごとにworld-model public compositionをfresh構築し、current corpusとversioned constraints / baseline / waiver / debtから`writeReport:false`で義務を独立再導出する。`.harness/world-obligations.json`のreader / cache / pathを依存に持たず、report absent / forged / unsupported-version / deletedでobservationとblocking結果が不変であることをreal filesystem fixtureで固定した。validator-system policyは`new-structural` / `invalid-declaration`と全derive diagnosticをfingerprint・WCR rule付きerrorとしてfail-closed、`adopted-legacy` / active waiverをwarningとして可視non-blockingにする。base fixtureはPASSし、new unpinned claim / duplicate IDを既存mutation manifestのexact fingerprint、unknown schemaをauthoritative diagnosticとして検証。resolved `world.enabled:false`ではL3-008を明示skip、trueの場合だけ実行し、self-repo config自体は変更していない。H17-15を同一着地で`planned -> required`へ進め、enforceable MVPのL2 local / L3 authoritative dual pathを完成した。
29
+
30
+ - **WI-301 / H17-14 — L2-017 World constraint admission fast-path(WM-19)** — ADR-037で予約した`L2-017 world-constraint-admission`をValidatorId、default registry、RunL2、composition-rootへ登録。config-foundationのresolved `world.enabled`をautomatic gate selectionとして消費し、false / absentではdefinitionを残した明示skip、trueの場合だけworld-model public facadeからpure `deriveWorldObligationsUseCase`を実行する。validator-system所有のpolicy serviceは`new-structural` / `invalid-declaration`とconstraint document admission failureをerrorとしてfail-closedにし、`adopted-legacy` / active waiverをfingerprint・WCR rule付きwarningとして可視化する。validなnew claim / pin自体はblockせず、保存obligation reportは入力にしない。HarnessErrorはlocal fast-pathが偽造可能でauthoritative判定は後続L3 clean-corpus re-derivationであると明記。fixtureでunpinned claim / malformed schemaのfail-closed、new pin finding、baseline採用後のlegacy non-blocking、disabled時のport非実行を固定した。self-repo `world.enabled`はfalseのまま、L3-008は未登録。H17-14を同一着地で`planned -> required`へ進めた。
31
+
32
+ - **WI-300 / H17-13 — World config surface と resolved mapping(WM-18)** — `phasegate.config.json` v2 / v3へADR-037のtop-level `world` contractを追加し、corpus roots / selection、matrix・attestation・integrity inputs、constraints・baseline・waivers・debts declarations、obligation report、session-start limitをschema / domain Value Objectでfail-closed検証する。absolute / backslash / traversal path、cross-role root overlap、case-fold collision、unknown field、範囲外limitを拒否。minimal / standard / strictは全てcanonical defaultsと`world.enabled:false`を持ち、explicit `world:*` commandは引き続き常時実行可能。preset resolutionはnested overrideをmergeし、World field省略時だけlegacy design / inception / matrix pathを継承する。dedicated `toWorldModelConfig()`をpublic mapping boundaryとして追加し、mainから完全plain DTOをWorld compositionへ注入。複数root、custom provider / control / output pathをextractor、repository、writerへ配線し、corpus digestからoutput / session / gate enablementを除外した。validator-system mapperにもWM-19 / WM-20用World projectionを渡すが、`L2-017` / `L3-008`は未登録のまま維持。H17-13を同一着地で`planned -> required`として登録し、configuration guideとaffected Unit設計を更新した。
33
+
12
34
  - **WI-299 — World Model のユーザー向けドキュメント反映** — README.md / README.ja.md に World Model 節(端点対称な制約再評価、`world:inspect` / `world:pin` / `world:derive`、immutable obligation report、adoption baseline、fail-closed 新規違反、CLI-only の現状スコープ)と Core Capabilities 行・CLI 表エントリを追加。`docs/guide/cli-reference.md` に World Model 節(options / exit code 0-1-2 / 制御ファイル 4 種 + `.harness/world-obligations.json` / `phasegate-world-cli/v1` envelope / `world.enabled` 既定 false と L2-017 / L3-008 予約の明記)を新設。README.ja footer の版表記を現行へ更新。
13
35
 
14
36
  - **WI-298 / H17-12 — Self-repo World adoption baseline と dogfood smoke(WM-17)** — final tracked corpus、H17-12 AC-bound smoke、再生成matrix、skill-quality semantic debt reflectionを含むcheckoutをbaselineなしで二重deriveし、serialized bytesとunique fingerprint集合の一致を確認。initial structural violationは実測604件で、全件implicit global TestReference ID duplicateの`WCR-005`、WCR-001 / explicit constraint finding / waiver / malformed policy inputは0件だった。candidate evaluation / corpus / constraint rootsをprovenanceに持つ604-entry closed `phasegate.world-baseline.json`を`adoptedByWorkItemId: WI-298`で採用し、same-ruleset追記禁止・返済削除onlyを明記。skill-quality coverage reportのungated attestation gapを`pgw:v1:semantic-debt:skill-quality.coverage-attestation-legacy`として`phasegate.world-debts.json`へ一件宣言し、既存`@coverage-gating`と`@world-semantic-debt`を併存させてL2-016を変更せず別collectionへimportした。self-repo smokeはmatrix再生成後の`world:derive --json`二重実行をbyte-identical、baseline=current fingerprint集合、604件全て`adopted-legacy`、new / repaid / policy diagnostic 0、semantic debt 1、exit 0として固定。H17-12を`planned -> required`へ進め、Phase B機能MVPを完成した。
package/README.ja.md CHANGED
@@ -189,7 +189,7 @@ npx phasegate reconcile --apply
189
189
  | **HarnessError 形式** | 全エラーに ADR 参照 + 修正例が含まれ、AI が自己修正できる |
190
190
  | **Baseline (retrofit)** | 既存リポジトリ導入時、`baseline` snapshot に登録した既存ファイルは構造的に編集されるまで gate 対象外 |
191
191
  | **カスタム gate** | AIDLC 以外のプロジェクトでも schema-first など独自の前提条件を設定できる |
192
- | **World Model (CLI)** | 設計文書・ソース・テスト・matrix・attestation を型付き事実グラフに抽出し、制約の両端点を pin して義務を決定的に再導出(`world:inspect` / `world:pin` / `world:derive`) |
192
+ | **World Model** | 設計文書・ソース・テスト・matrix・attestationを型付き事実グラフへ抽出。決定的`world:*` CLI、L2 fast-path、L3 authoritative再導出、bounded SessionStart、attestation v2 root pinを提供 |
193
193
 
194
194
  ---
195
195
 
@@ -260,7 +260,7 @@ Phasegate はプロンプトインジェクションを独立した新規脅威
260
260
 
261
261
  phasegate のゲートは従来一方向でした: 書き込み時にコードを設計と照合する。**World Model**([ADR-031](docs/ADR/031-world-model-ownership-and-corpus-lifecycle.md)〜[037](docs/ADR/037-world-cli-and-output-contract.md))はこの制約面を**端点対称**にします。設計文書・ソースメタデータ・テスト・requirement-test matrix・attestation を型付き・content-addressed な事実グラフとして抽出し、pin された制約は**どちらの端点が変わっても**再評価されます — 設計文書を編集すれば、それを根拠として主張していたコード側に可視の義務が生まれます(逆方向だけではなく)。
262
262
 
263
- 3 コマンドを提供します(明示実行は常に可能。`phasegate.config.json` の `world.enabled` は既定 `false` で、将来のゲート統合のみを制御します):
263
+ 3 コマンドは常に明示実行できます。`world.enabled` の product 既定値は `false` で、有効化すると登録済み L2/L3 統合が動きます。このリポジトリでは dogfood のため有効です。
264
264
 
265
265
  ```bash
266
266
  npx phasegate world:inspect --json # 決定的な read-only snapshot: node / edge / 抽出 diagnostics
@@ -274,8 +274,11 @@ npx phasegate world:derive --json # 制約評価から obligation report を
274
274
  - **新規違反は初日から fail-closed。** 既存違反は閉じた・人間レビュー可能な baseline(`phasegate.world-baseline.json`)として採用され、縮小のみ許されます(同一 ruleset での追加は拒否)。
275
275
  - **既知の意味的ギャップは宣言するもので「再発見」しない。** explicit debt は `phasegate.world-debts.json` に宣言し import として表示。waiver(`phasegate.world-waivers.json`)は fingerprint / 理由 / 期限 / Work Item が必須です。
276
276
  - **決定性は契約。** 同一 checkout での 2 回実行は byte-identical な JSON を出力します。
277
+ - **enforcement は二つの信頼レベルを持つ。** `L2-017` は偽造可能な local fast-path、`L3-008` は current corpus から authoritative に再導出し、`.harness/world-obligations.json`を信頼しません。adopted legacy は可視・非blocking、新規構造違反や不正宣言はfail-closedです。
278
+ - **agent context はbounded。** SessionStartは最大5件 / 2000文字でopen itemを表示し、adopted legacyは件数だけに集約。導出不能時は固定warningへfail-openします。
279
+ - **evidenceはroot一件だけをpinする。** attestation v2はfragment digestを複製せず`worldSnapshotRoot`をgate-run evidenceへ封印し、v1 produce / verify互換も維持します。
277
280
 
278
- 現在のスコープは **CLI のみ**です: validator ID L2-017 / L3-008 は予約済みですが pre-commit / CI ゲートへの登録は未実施で、将来フェーズとして管理しています。
281
+ World enforcementはproduction統合済みです。`L2-017` / `L3-008`は登録済み、bundled CI gateはWorld有効projectで決定的deriveを条件付き実行し、このリポジトリはfull dogfood pathを実行します。
279
282
 
280
283
  ---
281
284
 
package/README.md CHANGED
@@ -173,7 +173,7 @@ npx phasegate reconcile --apply
173
173
  | **Agent-readable HarnessError output** | Gives AI agents the reason, missing artifacts, references, and examples needed to self-correct |
174
174
  | **Retrofit baseline** | Lets existing repositories adopt Phasegate gradually by grandfathering unchanged files |
175
175
  | **Configurable gates** | Supports AIDLC defaults or custom gates such as schema-first API development |
176
- | **World Model (CLI)** | Extracts design docs, source, tests, matrices, and attestations into a typed fact graph, pins constraints between endpoints, and deterministically re-derives obligations (`world:inspect` / `world:pin` / `world:derive`) |
176
+ | **World Model** | Extracts design docs, source, tests, matrices, and attestations into a typed fact graph; deterministic `world:*` commands, L2 fast-path, L3 authoritative re-derivation, bounded SessionStart context, and attestation v2 root pinning |
177
177
 
178
178
  ---
179
179
 
@@ -240,7 +240,7 @@ Five components implement this posture:
240
240
 
241
241
  Phasegate's gates historically pointed one way: code is checked against design at write time. The **World Model** (per [ADR-031](docs/ADR/031-world-model-ownership-and-corpus-lifecycle.md)–[037](docs/ADR/037-world-cli-and-output-contract.md)) makes that constraint surface **endpoint-symmetric**: design documents, source metadata, tests, the requirement-test matrix, and attestations are extracted into a typed, content-addressed fact graph, and a pinned constraint is re-evaluated whenever *either* endpoint changes — so editing a design document creates visible obligations on the code that claimed it, not just the other way around.
242
242
 
243
- Three commands (always runnable explicitly; `world.enabled` in `phasegate.config.json` defaults to `false` and only governs future gate integration):
243
+ Three commands are always runnable explicitly. The product default for `world.enabled` is `false`; enabling it activates the registered L2/L3 integrations. This repository enables it for dogfooding.
244
244
 
245
245
  ```bash
246
246
  npx phasegate world:inspect --json # deterministic read-only snapshot: nodes, edges, extraction diagnostics
@@ -254,8 +254,11 @@ Design commitments that keep it honest:
254
254
  - **New violations fail closed from day one.** Pre-existing violations are adopted into a closed, human-reviewable baseline (`phasegate.world-baseline.json`) that can only shrink; same-ruleset additions are rejected.
255
255
  - **Known semantic gaps are declared, never "rediscovered."** Explicit debts live in `phasegate.world-debts.json` and are displayed as imports; waivers (`phasegate.world-waivers.json`) require a fingerprint, reason, expiry, and Work Item.
256
256
  - **Determinism is a contract.** Double runs over the same checkout produce byte-identical JSON output.
257
+ - **Enforcement has two trust levels.** `L2-017` is a forgeable local fast-path; `L3-008` authoritatively re-derives from the current corpus and never trusts `.harness/world-obligations.json`. Adopted legacy remains visible and non-blocking; new structural or malformed declarations fail closed.
258
+ - **Agent context is bounded.** SessionStart shows at most five open items within 2,000 characters, summarizes adopted legacy as a count, and fails open with a fixed warning if derivation is unavailable.
259
+ - **Evidence pins one root.** Attestation v2 seals `worldSnapshotRoot` in gate-run evidence without copying fragment digests; v1 produce/verify compatibility remains available.
257
260
 
258
- Current scope is **CLI-only**: validator IDs L2-017 / L3-008 are reserved but not yet registered into pre-commit/CI gating, which is tracked as a future phase.
261
+ World enforcement is production-integrated: `L2-017` and `L3-008` are registered, the bundled CI gate conditionally runs deterministic derivation for World-enabled projects, and this repository runs the full dogfood path.
259
262
 
260
263
  ---
261
264
 
@@ -0,0 +1,110 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://phasegate.dev/contracts/attestation-v2.schema.json",
4
+ "title": "PhaseGate attestation v2",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schemaVersion",
9
+ "predicateType",
10
+ "subject",
11
+ "inputs",
12
+ "granularity",
13
+ "acBoundScope",
14
+ "worldSnapshotRoot",
15
+ "metadata",
16
+ "signature"
17
+ ],
18
+ "properties": {
19
+ "schemaVersion": { "const": "phasegate-attestation/v2" },
20
+ "predicateType": { "const": "https://phasegate.dev/attestation/gate-run/v2" },
21
+ "worldSnapshotRoot": { "$ref": "#/$defs/digest" },
22
+ "subject": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "required": ["command", "gateResult", "validatorSet"],
26
+ "properties": {
27
+ "command": { "type": "string", "minLength": 1 },
28
+ "gateResult": { "enum": ["pass", "fail"] },
29
+ "validatorSet": {
30
+ "type": "array",
31
+ "items": {
32
+ "type": "object",
33
+ "additionalProperties": false,
34
+ "required": ["validatorId", "passed", "skipped"],
35
+ "properties": {
36
+ "validatorId": { "type": "string", "minLength": 1 },
37
+ "passed": { "type": "boolean" },
38
+ "skipped": { "type": "boolean" }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ },
44
+ "inputs": {
45
+ "type": "object",
46
+ "additionalProperties": false,
47
+ "required": ["digestAlgorithm", "sources", "inputDigest"],
48
+ "properties": {
49
+ "digestAlgorithm": { "const": "sha256" },
50
+ "sources": {
51
+ "type": "array",
52
+ "items": {
53
+ "type": "object",
54
+ "additionalProperties": false,
55
+ "required": ["path", "digest"],
56
+ "properties": {
57
+ "path": { "type": "string", "minLength": 1 },
58
+ "digest": { "$ref": "#/$defs/digest" }
59
+ }
60
+ }
61
+ },
62
+ "inputDigest": { "$ref": "#/$defs/digest" }
63
+ }
64
+ },
65
+ "granularity": {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": ["traceability"],
69
+ "properties": {
70
+ "traceability": {
71
+ "type": "object",
72
+ "additionalProperties": false,
73
+ "required": ["validator", "level", "claim", "knownLimitations"],
74
+ "properties": {
75
+ "validator": { "type": "string", "minLength": 1 },
76
+ "level": { "enum": ["file", "ac"] },
77
+ "claim": { "type": "string" },
78
+ "knownLimitations": { "type": "array", "items": { "type": "string" } }
79
+ }
80
+ }
81
+ }
82
+ },
83
+ "acBoundScope": { "type": "array", "items": { "type": "string" } },
84
+ "metadata": {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "required": ["producedAt", "producer", "gitCommit"],
88
+ "properties": {
89
+ "producedAt": { "type": "string", "minLength": 1 },
90
+ "producer": { "type": "string", "minLength": 1 },
91
+ "gitCommit": { "type": ["string", "null"] }
92
+ }
93
+ },
94
+ "signature": {
95
+ "type": "object",
96
+ "additionalProperties": false,
97
+ "required": ["mode", "attestationDigest", "algorithm", "keyId", "value"],
98
+ "properties": {
99
+ "mode": { "enum": ["unsigned-poc", "signed"] },
100
+ "attestationDigest": { "$ref": "#/$defs/digest" },
101
+ "algorithm": { "type": ["string", "null"] },
102
+ "keyId": { "type": ["string", "null"] },
103
+ "value": { "type": ["string", "null"] }
104
+ }
105
+ }
106
+ },
107
+ "$defs": {
108
+ "digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
109
+ }
110
+ }
@@ -328,8 +328,9 @@ L4 warning findings fail the process only when warning strictness is enabled (`v
328
328
  ## World Model
329
329
 
330
330
  <!-- @work-item-id WI-299 -->
331
+ <!-- @work-item-id WI-307 -->
331
332
 
332
- World Model コマンド(ADR-037)。設計文書・ソース・テスト・matrix・attestation を型付き事実グラフとして抽出し、pin された制約を両端点対称に再評価して義務を導出する。明示実行は config に依存せず常に可能(`world.enabled` は既定 `false` で、将来の L2/L3 ゲート統合のみを制御。validator ID `L2-017` / `L3-008` は予約済み・未登録)。
333
+ World Model コマンド(ADR-037)。設計文書・ソース・テスト・matrix・attestation を型付き事実グラフとして抽出し、pin された制約を両端点対称に再評価して義務を導出する。明示実行は config に依存せず常に可能。`world.enabled` のproduct既定値は`false`で、trueの場合に登録済み`L2-017` / `L3-008`とSessionStart integrationを有効化する。phasegate self-repoはdogfoodのためtrueである。
333
334
 
334
335
  | Command | Options | Description |
335
336
  |---|---|---|
@@ -337,6 +338,16 @@ World Model コマンド(ADR-037)。設計文書・ソース・テスト・m
337
338
  | `world:pin` | `--constraint <id>`(`pgw:v1:constraint` ID, 必須) `--endpoint <claimant\|premise>`(必須) `--apply` `--format human\|json` `--json` | 制約端点の現在 digest をプレビュー。`--apply` で `phasegate.world-constraints.json` を atomic に更新 |
338
339
  | `world:derive` | `--write` `--out <path>`(`--write` 必須) `--format human\|json` `--json` | immutable な obligation report を再導出。既定は pure・read-only。`--write` で raw report を `.harness/world-obligations.json`(untracked)へ永続化 |
339
340
 
341
+ ### Automatic integration
342
+
343
+ | Surface | Contract |
344
+ |---|---|
345
+ | `L2-017 world-constraint-admission` | local fast-path。new / changed constraintのmalformed、新規pin / unpinned claimをfail-closed。adopted-legacyはwarningのみ。local resultは偽造可能でauthorityではない |
346
+ | `L3-008 world-constraint-rederivation` | current corpusとversioned control inputからauthoritativeにpure再導出。保存`.harness/world-obligations.json`は読まず、改竄・削除で結果が変わらない |
347
+ | SessionStart | blocking相当を優先して最大5件 / 2000 Unicode scalar。adopted-legacyは件数一行、全文やreasonをpromptへ注入しない。derive不能は固定warningへfail-open |
348
+ | Attestation v2 | `phasegate-attestation/v2`がcanonical`worldSnapshotRoot`一件をpin。fragment digest collectionは保存しない。既存v1のproduce / verify互換を維持 |
349
+ | Bundled `aidlc-gate` | `world.enabled:true`のprojectでmatrix生成後にpure deriveを二回実行してbyte一致を確認し、その後L3を実行。false / absentではWorld段階だけをskip |
350
+
340
351
  ### Exit code
341
352
 
342
353
  | Exit | 意味 |
@@ -76,6 +76,36 @@ The plan identifies target fields, managed artifacts, commands, validation, risk
76
76
  "format": "json",
77
77
  "outputDir": "reports"
78
78
  },
79
+ "world": {
80
+ "enabled": false,
81
+ "corpus": {
82
+ "productRoots": ["docs/product"],
83
+ "inceptionRoots": ["docs/inception"],
84
+ "adrRoots": ["docs/ADR"],
85
+ "sourceRoots": ["scripts/harness"],
86
+ "include": ["**/*"],
87
+ "exclude": []
88
+ },
89
+ "inputs": {
90
+ "matrixPath": ".harness/requirement-test-matrix.json",
91
+ "attestationPath": ".harness/attestation.json",
92
+ "integrityManifestPath": "phasegate.integrity.json"
93
+ },
94
+ "declarations": {
95
+ "constraintsPath": "phasegate.world-constraints.json",
96
+ "baselinePath": "phasegate.world-baseline.json",
97
+ "waiversPath": "phasegate.world-waivers.json",
98
+ "debtsPath": "phasegate.world-debts.json"
99
+ },
100
+ "output": {
101
+ "obligationReportPath": ".harness/world-obligations.json"
102
+ },
103
+ "sessionStart": {
104
+ "enabled": true,
105
+ "maxItems": 5,
106
+ "maxChars": 2000
107
+ }
108
+ },
79
109
  "preCommit": {
80
110
  "implementationExtensions": [".ts"]
81
111
  },
@@ -115,6 +145,8 @@ The `strict` preset also enables:
115
145
  - `bundleSizeLimit` -- 500 KB default cap
116
146
  - `deadCodeGC` -- automatic dead-code garbage collection
117
147
 
148
+ All three presets resolve the same World Model defaults with `world.enabled: false`. This switch controls future automatic L2/L3 and hook integration; it does not disable explicit `world:inspect`, `world:pin`, or `world:derive` commands. Enabling automatic World gates remains an explicit rollout decision. <!-- @work-item-id WI-300 -->
149
+
118
150
  ---
119
151
 
120
152
  ### Field Reference
@@ -216,6 +248,30 @@ Example for Python and TypeScript:
216
248
 
217
249
  The metadata validators read `@unit` and `@layer` with language-agnostic regular expressions, so Python `# @unit api` and Go `// @unit api` style comments are both valid as long as the file extension is included here.
218
250
 
251
+ #### `world`
252
+
253
+ <!-- @work-item-id WI-300 -->
254
+
255
+ `world` configures the World Model read corpus and reviewed control inputs. It is available in both v2 and v3 config schemas. Nested fields may be omitted and are resolved from the selected preset.
256
+
257
+ | Field | Default | Meaning |
258
+ |---|---|---|
259
+ | `enabled` | `false` | Enables future automatic validator/hook integration; explicit `world:*` commands remain available |
260
+ | `corpus.productRoots` | `["docs/product"]` | Canonical product corpus roots |
261
+ | `corpus.inceptionRoots` | `["docs/inception"]` | Proposal/delta corpus roots |
262
+ | `corpus.adrRoots` | `["docs/ADR"]` | ADR corpus roots |
263
+ | `corpus.sourceRoots` | `["scripts/harness"]` | Source/test corpus roots |
264
+ | `corpus.include` / `exclude` | `["**/*"]` / `[]` | Versioned selection patterns |
265
+ | `inputs.matrixPath` | `.harness/requirement-test-matrix.json` | Matrix owner projection input |
266
+ | `inputs.attestationPath` | `.harness/attestation.json` | Attestation evidence input |
267
+ | `inputs.integrityManifestPath` | `phasegate.integrity.json` | Integrity declaration input |
268
+ | `declarations.*Path` | `phasegate.world-{constraints,baseline,waivers,debts}.json` | Git-reviewed external declarations |
269
+ | `output.obligationReportPath` | `.harness/world-obligations.json` | Generated, non-authoritative report path |
270
+ | `sessionStart.enabled` | `true` | Allows the bounded World summary when session integration is installed |
271
+ | `sessionStart.maxItems` / `maxChars` | `5` / `2000` | Summary caps; valid ranges are 1–20 and 1–8000 |
272
+
273
+ All paths are project-relative POSIX paths. Absolute paths, backslashes, `.` / `..` segments, cross-role corpus root overlap, and case-fold collisions are rejected. When the matching World field is omitted, legacy `paths.designDocs`, `paths.inceptionDocs`, and `layers.L3.requirementMatrixPath` remain compatible inputs. A present but invalid `world` section fails closed; it is never replaced with defaults silently.
274
+
219
275
  #### `phase2Extensions`
220
276
 
221
277
  <!-- @work-item-id WI-170 -->
@@ -7,8 +7,10 @@
7
7
  # 実行内容:
8
8
  # 1. bypass:audit — bypass trailer / evidence 監査
9
9
  # 2. phasegate lint — L1 Biome AST ルール検証
10
- # 3. phasegate:ci-check L3 CI バリデータ(security / performance / coverage / nyquist)
11
- # 4. 失敗時: PR にエラーサマリーをコメント
10
+ # 3. requirement-test matrix をcurrent testsから再生成
11
+ # 4. world.enabled=true の場合、world:derive を2回実行してbyte一致を検証
12
+ # 5. phasegate:ci-check — L3 CI バリデータ(security / performance / coverage / nyquist / World)
13
+ # 6. 失敗時: PR にエラーサマリーをコメント
12
14
 
13
15
  name: AIDLC Quality Gate
14
16
 
@@ -77,6 +79,44 @@ jobs:
77
79
  echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT
78
80
  exit $EXIT_CODE
79
81
 
82
+ # L3-004 consumes the generated requirement-test matrix. Always rebuild it
83
+ # from this checkout instead of trusting a stale or persisted artifact.
84
+ - name: Generate requirement-test matrix
85
+ if: always()
86
+ run: npx phasegate phasegate:generate-matrix
87
+
88
+ # Automatic World integration is selected only by an explicit true value.
89
+ # Missing/false keeps existing projects compatible; invalid JSON is a hard
90
+ # configuration error and must not be laundered into a disabled result.
91
+ - name: Detect World Model enablement
92
+ id: world_config
93
+ if: always()
94
+ shell: bash
95
+ run: |
96
+ set -euo pipefail
97
+ ENABLED=$(node --input-type=module <<'NODE'
98
+ import { existsSync, readFileSync } from 'node:fs';
99
+ if (!existsSync('phasegate.config.json')) {
100
+ process.stdout.write('false');
101
+ } else {
102
+ const config = JSON.parse(readFileSync('phasegate.config.json', 'utf8'));
103
+ process.stdout.write(config.world?.enabled === true ? 'true' : 'false');
104
+ }
105
+ NODE
106
+ )
107
+ echo "enabled=$ENABLED" >> "$GITHUB_OUTPUT"
108
+
109
+ - name: World derive determinism
110
+ if: steps.world_config.outputs.enabled == 'true'
111
+ shell: bash
112
+ run: |
113
+ set -euo pipefail
114
+ FIRST="$RUNNER_TEMP/phasegate-world-first.json"
115
+ SECOND="$RUNNER_TEMP/phasegate-world-second.json"
116
+ npx phasegate world:derive --json > "$FIRST"
117
+ npx phasegate world:derive --json > "$SECOND"
118
+ cmp --silent "$FIRST" "$SECOND"
119
+
80
120
  # L3: CI バリデータ(security / performance / coverage / nyquist)
81
121
  - name: L3 CI Check
82
122
  id: ci_check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phasegate",
3
- "version": "0.254.0",
3
+ "version": "0.264.0",
4
4
  "packageManager": "pnpm@10.30.1",
5
5
  "description": "Phasegate — AI-agnostic quality defense toolkit. Enforces structural integrity between design intent and code.",
6
6
  "license": "MIT",
@@ -0,0 +1,30 @@
1
+ // @unit agent-integration
2
+ // @layer application
3
+ // @work-item-id WI-304
4
+
5
+ export type OpenWorldObligationClassification =
6
+ | "new-structural"
7
+ | "invalid-declaration"
8
+ | "expired-waiver"
9
+ | "policy-diagnostic"
10
+ | "cleanup-required"
11
+ | "waived";
12
+
13
+ export interface OpenWorldObligationContextItemDto {
14
+ readonly kind: "structural" | "cleanup-required" | "policy-diagnostic";
15
+ readonly classification: OpenWorldObligationClassification;
16
+ readonly ruleId: string | null;
17
+ readonly constraintId: string | null;
18
+ readonly violationFingerprint: string | null;
19
+ readonly subjectId: string | null;
20
+ readonly policyCode?: string | null;
21
+ }
22
+
23
+ export type OpenWorldObligationsContextDto =
24
+ | { readonly status: "disabled" }
25
+ | { readonly status: "unavailable" }
26
+ | {
27
+ readonly status: "available";
28
+ readonly entries: readonly OpenWorldObligationContextItemDto[];
29
+ readonly adoptedLegacyCount: number;
30
+ };
@@ -0,0 +1,30 @@
1
+ // @unit agent-integration
2
+ // @layer application
3
+ // @work-item-id WI-304
4
+
5
+ export type QueriedWorldObligationClassification =
6
+ | "adopted-legacy"
7
+ | "new-structural"
8
+ | "invalid-declaration"
9
+ | "expired-waiver"
10
+ | "policy-diagnostic"
11
+ | "cleanup-required"
12
+ | "waived";
13
+
14
+ export interface QueriedWorldObligationEntry {
15
+ readonly kind: "structural" | "cleanup-required" | "policy-diagnostic";
16
+ readonly classification: QueriedWorldObligationClassification;
17
+ readonly ruleId: string | null;
18
+ readonly constraintId: string | null;
19
+ readonly violationFingerprint: string | null;
20
+ readonly subjectId?: string | null;
21
+ readonly policyCode?: string | null;
22
+ }
23
+
24
+ export type WorldObligationsQueryResult =
25
+ | { readonly status: "available"; readonly entries: readonly QueriedWorldObligationEntry[] }
26
+ | { readonly status: "unavailable" };
27
+
28
+ export interface WorldObligationsQueryPort {
29
+ query(): Promise<WorldObligationsQueryResult>;
30
+ }
@@ -0,0 +1,66 @@
1
+ // @unit agent-integration
2
+ // @layer application
3
+ // @work-item-id WI-304
4
+
5
+ import type {
6
+ OpenWorldObligationContextItemDto,
7
+ OpenWorldObligationsContextDto,
8
+ } from "../dto/open-world-obligations-context-dto.js";
9
+ import type { QueriedWorldObligationEntry, WorldObligationsQueryPort } from "../ports/world-obligations-query-port.js";
10
+
11
+ interface Dependencies {
12
+ readonly worldObligationsQueryPort: WorldObligationsQueryPort;
13
+ }
14
+
15
+ const priority = (entry: OpenWorldObligationContextItemDto): number => {
16
+ if (entry.classification === "new-structural" || entry.classification === "invalid-declaration") return 0;
17
+ if (entry.classification === "expired-waiver" || entry.classification === "policy-diagnostic") return 1;
18
+ if (entry.classification === "cleanup-required") return 2;
19
+ return 3;
20
+ };
21
+
22
+ const stableKey = (entry: OpenWorldObligationContextItemDto): string =>
23
+ [
24
+ priority(entry).toString().padStart(2, "0"),
25
+ entry.ruleId ?? "",
26
+ entry.constraintId ?? "",
27
+ entry.violationFingerprint ?? "",
28
+ entry.subjectId ?? "",
29
+ entry.policyCode ?? "",
30
+ ].join("\u0000");
31
+
32
+ type DisplayableQueriedEntry = QueriedWorldObligationEntry & {
33
+ readonly classification: Exclude<QueriedWorldObligationEntry["classification"], "adopted-legacy">;
34
+ };
35
+
36
+ const isDisplayable = (entry: QueriedWorldObligationEntry): entry is DisplayableQueriedEntry =>
37
+ entry.classification !== "adopted-legacy";
38
+
39
+ const toContextItem = (entry: DisplayableQueriedEntry): OpenWorldObligationContextItemDto => ({
40
+ kind: entry.kind,
41
+ classification: entry.classification,
42
+ ruleId: entry.ruleId,
43
+ constraintId: entry.constraintId,
44
+ violationFingerprint: entry.violationFingerprint,
45
+ subjectId: entry.subjectId ?? null,
46
+ policyCode: entry.policyCode ?? null,
47
+ });
48
+
49
+ export class GetOpenWorldObligationsContextUseCase {
50
+ constructor(private readonly dependencies: Dependencies) {}
51
+
52
+ async execute(input: { readonly enabled: boolean }): Promise<OpenWorldObligationsContextDto> {
53
+ if (!input.enabled) return { status: "disabled" };
54
+
55
+ const result = await this.dependencies.worldObligationsQueryPort.query();
56
+ if (result.status === "unavailable") return { status: "unavailable" };
57
+
58
+ const adoptedLegacyCount = result.entries.filter((entry) => entry.classification === "adopted-legacy").length;
59
+ const entries = result.entries
60
+ .filter(isDisplayable)
61
+ .map(toContextItem)
62
+ .sort((left, right) => (stableKey(left) < stableKey(right) ? -1 : stableKey(left) > stableKey(right) ? 1 : 0));
63
+
64
+ return { status: "available", entries: Object.freeze(entries), adoptedLegacyCount };
65
+ }
66
+ }
@@ -0,0 +1,58 @@
1
+ // @unit agent-integration
2
+ // @layer infrastructure
3
+ // @work-item-id WI-304
4
+
5
+ import { createWorldModelModule, type WorldResolvedConfigInput } from "../../../world-model/index.js";
6
+ import type {
7
+ QueriedWorldObligationEntry,
8
+ WorldObligationsQueryPort,
9
+ WorldObligationsQueryResult,
10
+ } from "../../application/ports/world-obligations-query-port.js";
11
+
12
+ interface Options {
13
+ readonly rootDir: string;
14
+ readonly resolvedConfig?: WorldResolvedConfigInput;
15
+ }
16
+
17
+ export class WorldModelOpenObligationsQueryAdapter implements WorldObligationsQueryPort {
18
+ constructor(private readonly options: Options) {}
19
+
20
+ async query(): Promise<WorldObligationsQueryResult> {
21
+ try {
22
+ const world = createWorldModelModule(this.options);
23
+ const derived = await world.deriveWorldObligationsUseCase.execute({ writeReport: false });
24
+ if (derived.status !== "derived") return { status: "unavailable" };
25
+
26
+ const report = derived.result.report;
27
+ const entries: QueriedWorldObligationEntry[] = [
28
+ ...report.structuralObligations.map((entry) => ({
29
+ kind: "structural" as const,
30
+ classification: entry.classification,
31
+ ruleId: entry.ruleId,
32
+ constraintId: entry.constraintId,
33
+ violationFingerprint: entry.violationFingerprint,
34
+ })),
35
+ ...report.repaidBaselineEntries.map((entry) => ({
36
+ kind: "cleanup-required" as const,
37
+ classification: "cleanup-required" as const,
38
+ ruleId: entry.ruleId,
39
+ constraintId: entry.constraintId,
40
+ violationFingerprint: entry.violationFingerprint,
41
+ })),
42
+ ...report.policyDiagnostics.map((entry) => ({
43
+ kind: "policy-diagnostic" as const,
44
+ classification:
45
+ entry.code === "expired-waiver" ? ("expired-waiver" as const) : ("policy-diagnostic" as const),
46
+ ruleId: null,
47
+ constraintId: null,
48
+ violationFingerprint: null,
49
+ subjectId: entry.subjectId,
50
+ policyCode: entry.code,
51
+ })),
52
+ ];
53
+ return { status: "available", entries: Object.freeze(entries) };
54
+ } catch {
55
+ return { status: "unavailable" };
56
+ }
57
+ }
58
+ }