phasegate 0.229.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 (154) hide show
  1. package/CHANGELOG.md +73 -1
  2. package/README.ja.md +31 -1
  3. package/README.md +30 -0
  4. package/docs/ADR/031-world-model-ownership-and-corpus-lifecycle.md +155 -0
  5. package/docs/ADR/032-world-node-identity.md +198 -0
  6. package/docs/ADR/033-world-snapshot-canonicalization.md +246 -0
  7. package/docs/ADR/034-world-constraint-semantics.md +218 -0
  8. package/docs/ADR/035-world-adoption-baseline-and-waiver.md +341 -0
  9. package/docs/ADR/036-world-model-and-doc-freshness.md +169 -0
  10. package/docs/ADR/037-world-cli-and-output-contract.md +398 -0
  11. package/docs/contracts/attestation-v2.schema.json +110 -0
  12. package/docs/contracts/requirement-test-matrix.schema.json +15 -0
  13. package/docs/contracts/world-baseline.schema.json +35 -0
  14. package/docs/contracts/world-constraints.schema.json +56 -0
  15. package/docs/contracts/world-debts.schema.json +32 -0
  16. package/docs/contracts/world-obligation-report.schema.json +259 -0
  17. package/docs/contracts/world-waivers.schema.json +32 -0
  18. package/docs/guide/cli-reference.md +45 -0
  19. package/docs/guide/configuration.md +56 -0
  20. package/docs/templates/ci/aidlc-gate.yml +42 -2
  21. package/package.json +1 -1
  22. package/scripts/harness/agent-integration/application/dto/open-world-obligations-context-dto.ts +30 -0
  23. package/scripts/harness/agent-integration/application/ports/world-obligations-query-port.ts +30 -0
  24. package/scripts/harness/agent-integration/application/usecases/get-open-world-obligations-context-usecase.ts +66 -0
  25. package/scripts/harness/agent-integration/infrastructure/adapters/world-model-open-obligations-query-adapter.ts +58 -0
  26. package/scripts/harness/agent-integration/presentation/session-start-hook.ts +37 -1
  27. package/scripts/harness/agent-integration/presentation/world-obligations-session-context.ts +60 -0
  28. package/scripts/harness/attestation/application/dto/attestation-document.ts +17 -4
  29. package/scripts/harness/attestation/application/mappers/attestation-record-mapper.ts +55 -4
  30. package/scripts/harness/attestation/application/ports/sha256-capability.ts +25 -0
  31. package/scripts/harness/attestation/application/ports/world-snapshot-root-provider.ts +10 -0
  32. package/scripts/harness/attestation/application/usecases/produce-attestation-usecase.ts +33 -7
  33. package/scripts/harness/attestation/composition-root.ts +19 -4
  34. package/scripts/harness/attestation/domain/entities/attestation-record.ts +37 -2
  35. package/scripts/harness/attestation/index.ts +13 -2
  36. package/scripts/harness/attestation/infrastructure/adapters/node-crypto-content-hasher-adapter.ts +6 -6
  37. package/scripts/harness/attestation/infrastructure/adapters/node-crypto-sha256-capability.ts +19 -0
  38. package/scripts/harness/attestation/presentation/handlers/attest-handler.ts +5 -2
  39. package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +35 -8
  40. package/scripts/harness/config-foundation/application/mappers/world-model-config-mapper.ts +15 -0
  41. package/scripts/harness/config-foundation/domain/harness-config.ts +67 -87
  42. package/scripts/harness/config-foundation/domain/services/preset-resolution-service.ts +77 -88
  43. package/scripts/harness/config-foundation/domain/value-objects/world-config.ts +198 -0
  44. package/scripts/harness/config-foundation/index.ts +14 -15
  45. package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +24 -0
  46. package/scripts/harness/config-foundation/infrastructure/presets/standard.json +24 -0
  47. package/scripts/harness/config-foundation/infrastructure/presets/strict.json +24 -0
  48. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +83 -0
  49. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +83 -0
  50. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +18 -4
  51. package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +4 -1
  52. package/scripts/harness/integrations/pre-commit.ts +169 -27
  53. package/scripts/harness/main.ts +276 -126
  54. package/scripts/harness/nyquist-validation/application/dto/generate-matrix-output.ts +11 -0
  55. package/scripts/harness/nyquist-validation/application/usecases/check-ac-coverage-gate-usecase.ts +6 -0
  56. package/scripts/harness/nyquist-validation/application/usecases/generate-requirement-test-matrix-usecase.ts +8 -4
  57. package/scripts/harness/nyquist-validation/domain/entities/story-mapping.ts +29 -2
  58. package/scripts/harness/nyquist-validation/domain/services/ac-coverage-gate-policy.ts +28 -0
  59. package/scripts/harness/nyquist-validation/infrastructure/adapters/markdown-requirement-source-adapter.ts +71 -4
  60. package/scripts/harness/nyquist-validation/infrastructure/schema/matrix-schema-loader.ts +4 -0
  61. package/scripts/harness/traceability-model/application/dto/changed-design-fragment-dto.ts +31 -0
  62. package/scripts/harness/traceability-model/application/dto/traceability-world-read-dto.ts +67 -0
  63. package/scripts/harness/traceability-model/application/facades/design-change-read-facade.ts +14 -0
  64. package/scripts/harness/traceability-model/application/facades/traceability-world-read-facade.ts +372 -0
  65. package/scripts/harness/traceability-model/application/ports/staged-design-change-source-port.ts +9 -0
  66. package/scripts/harness/traceability-model/application/ports/traceability-world-read-source-port.ts +61 -0
  67. package/scripts/harness/traceability-model/composition-root.ts +26 -5
  68. package/scripts/harness/traceability-model/index.ts +26 -6
  69. package/scripts/harness/traceability-model/infrastructure/adapters/file-system-traceability-world-read-adapter.ts +223 -0
  70. package/scripts/harness/traceability-model/infrastructure/adapters/git-staged-design-change-adapter.ts +155 -0
  71. package/scripts/harness/traceability-model/infrastructure/parsers/story-catalog-parser.ts +86 -8
  72. package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +31 -0
  73. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +34 -0
  74. package/scripts/harness/validator-system/composition-root.ts +21 -6
  75. package/scripts/harness/validator-system/domain/ports/world-constraint-admission-policy-port.ts +28 -0
  76. package/scripts/harness/validator-system/domain/ports/world-constraint-rederivation-policy-port.ts +11 -0
  77. package/scripts/harness/validator-system/domain/services/design-change-declaration-policy.ts +75 -0
  78. package/scripts/harness/validator-system/domain/services/world-constraint-admission-service.ts +78 -0
  79. package/scripts/harness/validator-system/domain/services/world-constraint-rederivation-service.ts +76 -0
  80. package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +4 -0
  81. package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +38 -16
  82. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-admission-adapter.ts +56 -0
  83. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-rederivation-adapter.ts +56 -0
  84. package/scripts/harness/world-model/application/dto/pinned-design-endpoint-dto.ts +19 -0
  85. package/scripts/harness/world-model/application/dto/world-inspection-dto.ts +43 -0
  86. package/scripts/harness/world-model/application/dto/world-obligation-report-dto.ts +54 -0
  87. package/scripts/harness/world-model/application/dto/world-resolved-config-input.ts +127 -0
  88. package/scripts/harness/world-model/application/dto/world-snapshot-root-dto.ts +8 -0
  89. package/scripts/harness/world-model/application/facades/pinned-design-endpoint-facade.ts +63 -0
  90. package/scripts/harness/world-model/application/facades/world-snapshot-root-facade.ts +19 -0
  91. package/scripts/harness/world-model/application/ports/obligation-report-writer-port.ts +7 -0
  92. package/scripts/harness/world-model/application/ports/world-control-declaration-repository-port.ts +57 -0
  93. package/scripts/harness/world-model/application/ports/world-fact-source-port.ts +17 -0
  94. package/scripts/harness/world-model/application/usecases/build-snapshot-use-case.ts +111 -0
  95. package/scripts/harness/world-model/application/usecases/derive-obligations-use-case.ts +155 -0
  96. package/scripts/harness/world-model/application/usecases/derive-world-obligations-use-case.ts +146 -0
  97. package/scripts/harness/world-model/application/usecases/inspect-world-use-case.ts +74 -0
  98. package/scripts/harness/world-model/application/usecases/pin-constraint-endpoint-use-case.ts +139 -0
  99. package/scripts/harness/world-model/composition-root.ts +247 -0
  100. package/scripts/harness/world-model/domain/entities/constraint-record.ts +148 -0
  101. package/scripts/harness/world-model/domain/entities/control-declarations.ts +274 -0
  102. package/scripts/harness/world-model/domain/entities/edge.ts +41 -0
  103. package/scripts/harness/world-model/domain/entities/extraction-diagnostic.ts +60 -0
  104. package/scripts/harness/world-model/domain/entities/snapshot.ts +75 -0
  105. package/scripts/harness/world-model/domain/entities/world-node.ts +210 -0
  106. package/scripts/harness/world-model/domain/ports/world-hashing-port.ts +8 -0
  107. package/scripts/harness/world-model/domain/services/canonical-json-serializer.ts +113 -0
  108. package/scripts/harness/world-model/domain/services/constraint-evaluator.ts +486 -0
  109. package/scripts/harness/world-model/domain/services/obligation-derivation-service.ts +199 -0
  110. package/scripts/harness/world-model/domain/services/policy-inputs-digest-deriver.ts +66 -0
  111. package/scripts/harness/world-model/domain/services/snapshot-root-deriver.ts +218 -0
  112. package/scripts/harness/world-model/domain/services/text-content-normalizer.ts +30 -0
  113. package/scripts/harness/world-model/domain/services/violation-fingerprint-deriver.ts +183 -0
  114. package/scripts/harness/world-model/domain/value-objects/artifact-kind.ts +58 -0
  115. package/scripts/harness/world-model/domain/value-objects/change-provenance.ts +137 -0
  116. package/scripts/harness/world-model/domain/value-objects/corpus-role.ts +57 -0
  117. package/scripts/harness/world-model/domain/value-objects/declared-key.ts +35 -0
  118. package/scripts/harness/world-model/domain/value-objects/evaluation-id.ts +41 -0
  119. package/scripts/harness/world-model/domain/value-objects/explicit-constraint-relation.ts +53 -0
  120. package/scripts/harness/world-model/domain/value-objects/explicit-node-alias.ts +30 -0
  121. package/scripts/harness/world-model/domain/value-objects/node-pin.ts +34 -0
  122. package/scripts/harness/world-model/domain/value-objects/path-key.ts +103 -0
  123. package/scripts/harness/world-model/domain/value-objects/sha256-digest.ts +39 -0
  124. package/scripts/harness/world-model/domain/value-objects/violation-fingerprint.ts +36 -0
  125. package/scripts/harness/world-model/domain/value-objects/wcr-rule-id.ts +59 -0
  126. package/scripts/harness/world-model/domain/value-objects/world-node-id.ts +222 -0
  127. package/scripts/harness/world-model/index.ts +33 -0
  128. package/scripts/harness/world-model/infrastructure/adapters/adr-fact-extractor.ts +27 -0
  129. package/scripts/harness/world-model/infrastructure/adapters/assembled-world-fact-source.ts +17 -0
  130. package/scripts/harness/world-model/infrastructure/adapters/attestation-fact-extractor.ts +323 -0
  131. package/scripts/harness/world-model/infrastructure/adapters/attestation-sha256-world-hashing-adapter.ts +15 -0
  132. package/scripts/harness/world-model/infrastructure/adapters/composite-design-fact-source.ts +23 -0
  133. package/scripts/harness/world-model/infrastructure/adapters/design-corpus-fact-extractor.ts +285 -0
  134. package/scripts/harness/world-model/infrastructure/adapters/design-fact-extraction.ts +63 -0
  135. package/scripts/harness/world-model/infrastructure/adapters/file-system-obligation-report-writer-adapter.ts +37 -0
  136. package/scripts/harness/world-model/infrastructure/adapters/file-system-world-control-repository-adapters.ts +332 -0
  137. package/scripts/harness/world-model/infrastructure/adapters/integrity-manifest-fact-extractor.ts +101 -0
  138. package/scripts/harness/world-model/infrastructure/adapters/json-fact-extractor-support.ts +151 -0
  139. package/scripts/harness/world-model/infrastructure/adapters/markdown-design-fact-extractor.ts +493 -0
  140. package/scripts/harness/world-model/infrastructure/adapters/matrix-fact-extractor.ts +283 -0
  141. package/scripts/harness/world-model/infrastructure/adapters/product-fact-extractor.ts +29 -0
  142. package/scripts/harness/world-model/infrastructure/adapters/proposal-fact-extractor.ts +29 -0
  143. package/scripts/harness/world-model/infrastructure/adapters/runtime-fact-extraction.ts +19 -0
  144. package/scripts/harness/world-model/infrastructure/adapters/source-metadata-fact-extractor.ts +22 -0
  145. package/scripts/harness/world-model/infrastructure/adapters/test-reference-source-fact-extractor.ts +22 -0
  146. package/scripts/harness/world-model/infrastructure/adapters/traceability-design-fact-adapter.ts +112 -0
  147. package/scripts/harness/world-model/infrastructure/adapters/traceability-world-read-facade-merger.ts +38 -0
  148. package/scripts/harness/world-model/infrastructure/adapters/type-script-source-fact-extractor.ts +236 -0
  149. package/scripts/harness/world-model/infrastructure/adapters/unit-fact-extractor.ts +71 -0
  150. package/scripts/harness/world-model/infrastructure/adapters/world-control-declaration-mapper.ts +383 -0
  151. package/scripts/harness/world-model/presentation/cli/world-command-support.ts +60 -0
  152. package/scripts/harness/world-model/presentation/cli/world-derive-command-handler.ts +109 -0
  153. package/scripts/harness/world-model/presentation/cli/world-inspect-command-handler.ts +194 -0
  154. package/scripts/harness/world-model/presentation/cli/world-pin-command-handler.ts +100 -0
@@ -0,0 +1,198 @@
1
+ ---
2
+ adr_id: "032"
3
+ title: "World node identity と fragment locator"
4
+ status: Proposed
5
+ date: 2026-07-16
6
+ ---
7
+
8
+ # World node identity と fragment locator
9
+
10
+ <!-- @work-item-id WI-282 -->
11
+
12
+ ## Context
13
+
14
+ World Model は snapshot 間で同じ node を追跡し、constraint endpoint の missing / changed / duplicate を区別する必要がある。content digest をidentityにすると編集のたびにnodeが入れ替わり、line numberやheading textをidentityにすると文書の並べ替えや見出し修正がrenameとして誤検出される。
15
+
16
+ 現行実装には複数のidentity / locator慣行がある。
17
+
18
+ - traceability-modelは`WI-\d+` directoryとdescription frontmatter `id` の一致、inception全体の重複を検証し、`legacy_id`を保持する。
19
+ - StoryIdは`HXX-XX` / `HF\d+-XX`、WorkItem frontmatter parserはmigration互換IDも読む。
20
+ - `ProjectRelativePath`はproject-relative POSIX pathを表し、absolute path、backslash、`..`を拒否する。
21
+ - matrixのTestReferenceは`filePath`, `testType`, optional `testName`, optional `binding`を持ち、dedup時にmissing bindingを`file`へ正規化する。
22
+ - `@work-item-id`はカンマ / 空白区切りの複数参照を表し、`@attestation`はcoverage_reportのStory scope参照をline locator付きで表すが、いずれもannotation occurrence自身のstable IDを持たない。
23
+ - integrity manifestはproject-relative pathをSHA-256へpinし、include / exclude globでtargetを宣言する。
24
+
25
+ ADR-031はproductをcanonical、inceptionをproposal / deltaとして別artifactに保ち、design document / source / generated artifact / external declarationのkindを分離すると決めた。本ADRはこの非同一性を保ったまま、node identity、fragment locator、migrationを決める。
26
+
27
+ ## Decision
28
+
29
+ ### 1. Versioned World Node ID schemaを採用する
30
+
31
+ 全World IDは`pgw:v1:` prefixを持つ。ID schema versionはextractor / ruleset / snapshot schema versionとは独立に管理する。
32
+
33
+ 可変componentはURI percent-encoded UTF-8を使う。pathはexisting `ProjectRelativePath`と同じlexical contractで正規化し、各segmentをencodeして`/`を保持する。case folding、Unicode normalization、symlink resolutionはidentity生成では行わない。
34
+
35
+ ID形式:
36
+
37
+ | node | ID |
38
+ |---|---|
39
+ | Artifact | `pgw:v1:artifact:<artifact-kind>:<corpus-role>:<path-key>` |
40
+ | SourceFile | `pgw:v1:source-file:<path-key>` |
41
+ | explicit Fragment | `pgw:v1:fragment:<corpus-role>:<declared-key>` |
42
+ | legacy whole-file Fragment | `pgw:v1:fragment:legacy:<artifact-kind>:<corpus-role>:<path-key>` |
43
+ | WorkItem | `pgw:v1:work-item:<WI-ID>` |
44
+ | TestReference | `pgw:v1:test-reference:<story-id>:<ac-id>:<binding>:<test-type>:<path-key>:name:<name-key>` |
45
+ | ExplicitClaim | `pgw:v1:explicit-claim:<declared-key>` |
46
+ | Constraint | `pgw:v1:constraint:<declared-key>` |
47
+ | Snapshot | `pgw:v1:snapshot:sha256:<64-lowercase-hex>` |
48
+
49
+ `DeclaredKey`は`[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*`とし、人が明示する。headingやpathから自動slug化しない。
50
+
51
+ Artifact kind / corpus roleはADR-031に従う。SourceFileはsource kind Artifactのspecializationであり、同じfileにgeneric Artifact nodeを二重生成しない。Snapshot hashの入力bytesはADR-033が決める。
52
+
53
+ ### 2. File identityとFragment identityを分離する
54
+
55
+ Artifact / SourceFile IDはproject-relative pathをidentityに含む。rename / moveはold nodeのmissingとnew nodeのaddedとして観測し、同じdigestからrenameを推論しない。
56
+
57
+ explicit Fragment IDは`corpus-role + DeclaredKey`であり、artifact path、heading text、heading level、document order、line number、content digestを含まない。同じcorpus role内でmarker keyが維持されれば、file move、heading rename、level変更、並べ替え後も同じFragmentである。
58
+
59
+ Fragment locatorはartifact ID、marker / heading / start / end line、heading level、表示用heading textを持つ。locatorはsnapshotごとに変化でき、identityではない。
60
+
61
+ ### 3. Markdown fragment markerを定義する
62
+
63
+ ```markdown
64
+ <!-- @world-fragment-id world-model.ownership -->
65
+ ## Ownership
66
+ ```
67
+
68
+ - markerは対象ATX heading直前のcontiguous metadata preludeに置く。preludeは`@world-fragment-id` / `@world-reflects` / `@work-item-id`の単独HTML comment行だけで構成し、空行やproseを挟まない。headingはpreludeの直後に置く。
69
+ - fenced code / inline code / example comment内部は抽出しない。
70
+ - 一つのheadingにmarkerは1件。
71
+ - fragment rangeはheadingから次のmarker-bound heading直前、またはEOFまで。
72
+ - heading text / orderはlocatorでありidentityに使わない。
73
+ - 同じcorpus role内のduplicate keyはhard extraction diagnosticとし、winnerを選ばない。
74
+
75
+ markerより前のunmarked contentもArtifact全体として観測する。Fragmentがないことをcontent omissionにはしない。
76
+
77
+ ### 4. Legacy whole-file fallbackを段階移行する
78
+
79
+ 明示markerを持たないMarkdown Artifactには、Artifact tupleから導出したlegacy whole-file Fragmentを1件生成する。
80
+
81
+ 移行state:
82
+
83
+ 1. **whole-file** — markerなし。fallbackを互換targetとして観測する。
84
+ 2. **mixed** — marker導入後、completion markerがない間はexplicit fragmentsとcompatibility fallbackを併存させる。新規declarationからfallbackへの参照は禁止する。
85
+ 3. **explicit** — legacy inbound referenceが0であることをmigration gateで確認し、YAML frontmatterがあればその直後、なければ最初のheadingより前に`<!-- @world-fragment-migration complete -->`を追加する。次snapshotからfallbackを除外する。
86
+
87
+ whole-file constraintをone fragmentへ自動aliasしない。どの意味境界へ分割するかは機械では判断できないため、人が一つ以上のexplicit Fragment IDへretargetする。
88
+
89
+ completion markerがexplicit fragmentなしで宣言された場合、またはlegacy inbound referenceが残る場合はdiagnosticとする。fallback emissionはcorpus上のmarkerだけで決め、constraint declarationの有無に依存させない。
90
+
91
+ ### 5. 既存owner IDとannotationをそのまま尊重する
92
+
93
+ - WorkItem nodeはtraceability-modelが解決したcanonical `WI-\d+`をpayloadにする。`legacy_id`はaliasであり別nodeを作らない。
94
+ - TestReference IDはmatrix ownerのtuple `(storyId, acId, binding ?? "file", testType, filePath, testName)`から作る。`generatedAt`、array index、line numberを含めない。
95
+ - `@work-item-id`はWorkItem provenance / reflection reference factへ一IDずつ展開する。
96
+ - `@attestation`はStory scope evidence reference factとして観測する。
97
+ - annotation line / occurrence ordinalからstable ExplicitClaim IDを生成しない。future ExplicitClaimはexternal declarationにrequired `claimId`を持つ。
98
+ - Constraintもrequired `constraintId`からidentityを作り、violation fingerprintとは分離する。
99
+ - integrity manifestのpath / glob / digestはtarget / claim payloadであり、node identityにはしない。
100
+
101
+ ### 6. Rename / move / deleteを明示的に扱う
102
+
103
+ - path-based Artifact / SourceFile、matrix-derived TestReferenceのkey componentが変わればold missing + new added。
104
+ - explicit Fragmentは同じcorpus roleとDeclaredKeyを保つmove / heading変更ではidentityを維持する。
105
+ - productからinception、またはinceptionからproductへのrole変更は別identity。
106
+ - deleteされたnodeはcurrent snapshotから消え、参照endpointはmissingになる。
107
+ - content digest一致、類似heading、同じtest bodyからsuccessorを推論しない。
108
+
109
+ continuityが必要ならexplicit alias declarationを使う。
110
+
111
+ ### 7. Aliasはidentityでなくsingle-hop resolution ruleとする
112
+
113
+ Alias declarationは`aliasId`, `canonicalId`, `reason`, `workItemId`を必須とする。正式file name / schemaはADR-037で決める。
114
+
115
+ - aliasは新nodeを作らず、reference resolutionをcanonical nodeへ導く。
116
+ - targetはcanonical IDでなければならず、alias chain / cycleを禁止する。
117
+ - 一つのaliasIdから複数targetを禁止する。
118
+ - resolutionは`resolved-via-alias` factを残し、renameを不可視化しない。
119
+ - Fragment aliasは同じcorpus role内だけ。product / inceptionをaliasで同一化しない。
120
+ - traceability-model `legacy_id`はprovider-owned aliasとして投影する。
121
+ - digest一致からaliasを自動生成しない。
122
+
123
+ ### 8. Duplicate IDはno-winnerで扱う
124
+
125
+ WorkItem、Fragment、ExplicitClaim、Constraint、TestReferenceなど同一canonical IDが複数locatorへ解決した場合、extractorはどれかを採用せず`duplicate-node-id` diagnosticを返す。array orderやfilesystem列挙順でwinnerを選ばない。
126
+
127
+ duplicateを含むsnapshotはidentity-completeではない。どのlayerでblockingするかはvalidator-system所有であり、ADR-034以降で決める。
128
+
129
+ ### 9. ProposalとcanonicalをWorkItem hubと明示relationで接続する
130
+
131
+ 現行`@work-item-id`からartifact-level provenanceを作る。
132
+
133
+ ```text
134
+ inception proposal Artifact ──proposed-by──> WorkItem
135
+ WorkItem ──reflected-in──> product canonical Artifact / Fragment
136
+ ```
137
+
138
+ これは同じWIのprovenanceであり、fragment-to-fragment exact mappingではない。
139
+
140
+ exact mappingが必要なcanonical headingでは次を記述する。
141
+
142
+ ```markdown
143
+ <!-- @world-fragment-id world-model.ownership -->
144
+ <!-- @world-reflects inception:world-model.ownership -->
145
+ <!-- @work-item-id WI-282 -->
146
+ ## Ownership
147
+ ```
148
+
149
+ `@world-reflects`はrepeatableで、targetは`<corpus-role>:<declared-key>`。v1 source roleは`inception`、current fragmentは`product`でなければならない。World edgeは`proposal --reflected-as--> canonical`方向に作る。
150
+
151
+ same key、heading、order、digestからreflectionを推論しない。target不在、role不正、duplicate targetはdiagnosticとする。
152
+
153
+ ### 10. ADR-032 scopeの未決事項へ回答する
154
+
155
+ #### 明示fragment IDのMarkdown記法
156
+
157
+ `<!-- @world-fragment-id <DeclaredKey> -->`を採用し、ATX heading直前のcontiguous metadata preludeからbindする。HTML commentにすることでrendered proseを汚さず、既存`@work-item-id` / `@attestation`と同じ機械可読annotation慣行に合わせる。heading text / orderはidentityにしない。
158
+
159
+ #### legacy whole-fileからfragmentへのmigration
160
+
161
+ whole-file → mixed → explicitのratchetを採用する。marker導入時にfallbackを即削除せず、completion markerがない間はcompatibility nodeとして残す。新規fallback参照を禁止し、人がconstraint / pinを明示fragmentへretargetする。inbound reference 0を確認後に`<!-- @world-fragment-migration complete -->`を追加し、次snapshotでfallbackを除去する。一対一aliasや意味的自動分割は行わない。
162
+
163
+ ## Consequences
164
+
165
+ ### Positive
166
+
167
+ - prose編集やheading並べ替えでconstraint endpoint identityが不要に変わらない。
168
+ - path-based file eventとlogical fragment continuityを区別できる。
169
+ - product / inceptionのprovenanceを維持し、reflectionだけを明示factにできる。
170
+ - current annotationのlocatorをstable identityに偽装しない。
171
+ - legacy corpusを一括marker化せず段階導入できる。
172
+
173
+ ### Negative / Trade-off
174
+
175
+ - marker keyのproject-wide管理とduplicate検出が必要になる。
176
+ - path-based Artifact / SourceFileはrename時にidentityが変わり、continuityにはalias declarationが必要。
177
+ - mixed migration中はexplicit fragmentとcompatibility whole-file fragmentが併存する。
178
+ - existing annotationだけではfragment-level exact reflectionやstable ExplicitClaimを表せない。
179
+
180
+ ## Alternatives
181
+
182
+ - **content digestをnode IDにする** — 内容変更がdelete + addになりstalenessを追えないため不採用。
183
+ - **heading text / heading pathをFragment IDにする** — rename / reorderでidentityが変わり、同名headingも衝突するため不採用。
184
+ - **line number / occurrence ordinalをannotation claim IDにする** — 無関係な行挿入でidentityが変わるため不採用。
185
+ - **same key / digestでproposalとcanonicalを自動接続する** — ADR-031のcorpus role分離と「意味的伝播を機械で主張しない」原則に反するため不採用。
186
+ - **marker導入時にlegacy fallbackを即削除する** — existing constraint endpointを一斉にmissingへするため不採用。
187
+ - **whole-file fallbackを一つのfragmentへ自動aliasする** — one-to-manyの意味分割を機械が決めることになるため不採用。
188
+
189
+ ## 関連要件・文書
190
+
191
+ - `docs/inception/_cross/WI-280/delivery_plan.md` §1, §3 WM-02, §7 ADR-032, §10
192
+ - `docs/inception/_cross/WI-281/logical_design.md`
193
+ - `docs/inception/_cross/WI-282/description.md`
194
+ - `docs/inception/_cross/WI-282/domain_model.md`
195
+ - `docs/inception/_cross/WI-282/logical_design.md`
196
+ - ADR-027(成果物駆動の状態導出)
197
+ - ADR-030(明示参照と再導出)
198
+ - ADR-031(ownership、artifact kind、product / inception corpus role)
@@ -0,0 +1,246 @@
1
+ ---
2
+ adr_id: "033"
3
+ title: "World snapshot canonicalization、version roots、hashing"
4
+ status: Proposed
5
+ date: 2026-07-16
6
+ ---
7
+
8
+ # World snapshot canonicalization、version roots、hashing
9
+
10
+ <!-- @work-item-id WI-283 -->
11
+
12
+ ## Context
13
+
14
+ World Modelはclean checkoutのcorpusとdeclarationから同じfacts / obligationsを再導出しなければならない。filesystem列挙順、object insertion order、absolute checkout root、clock、generated reportがrootへ混ざると、論理入力が同じでも異なるsnapshotになる。一方、extractor、ruleset、schema、World-relevant resolved configが変われば解釈が変わるため、その差はrootへ反映しなければならない。
15
+
16
+ 既存実装には三つの重要な先例と差異がある。
17
+
18
+ - attestation `canonicalStringify`はobject keyを再帰sortし、array orderを保持し、空白なしJSONをUTF-8 SHA-256へ渡す。
19
+ - attestation / ci-governance integrityのfile digesterは`readFile` raw bytesをSHA-256へ渡す。
20
+ - requirement-test-matrixは`generatedAt`を毎回生成し、pretty JSONとして保存するため、保存bytesのhashはsemantic matrix identityにならない。
21
+
22
+ また、既存`NodeCryptoContentHasherAdapter`はattestation-local `ContentHasherPort`と`Digest`を使う。ADR-031によりworld-modelはprovider内部型をimportできず、consumer-owned portを持つ必要がある。ADR-032は`pgw:v1` node IDとPathKeyを確定済みである。
23
+
24
+ ## Decision
25
+
26
+ ### 1. Leaf digestとthree derived rootsを分離する
27
+
28
+ Artifact / Fragment contentはowner-aware normalization後のbytesをSHA-256し、leaf digest `sha256:<hex>`としてnode factへ入れる。root envelopeはfull proseを重複保持せず、stable node IDs、typed facts、leaf digests、edges、diagnosticsをcanonical JSON化する。
29
+
30
+ 三つのderived identityを定義する。
31
+
32
+ #### corpusRoot
33
+
34
+ ```text
35
+ sha256(canonicalJson({
36
+ schemaVersion,
37
+ extractorVersion,
38
+ corpusConfigDigest,
39
+ nodes,
40
+ edges,
41
+ extractionDiagnostics
42
+ }))
43
+ ```
44
+
45
+ - nodesはNode ID、edgesはtype/from/to/qualifier、diagnosticsはcode/node/path/line/payloadでsortする。
46
+ - constraints / claims / aliases / evaluation findings / obligationsを含めない。
47
+ - Snapshot IDは`pgw:v1:snapshot:<corpusRoot>`。
48
+
49
+ #### constraintRoot
50
+
51
+ ```text
52
+ sha256(canonicalJson({
53
+ schemaVersion,
54
+ rulesetVersion,
55
+ constraintConfigDigest,
56
+ constraints,
57
+ explicitClaims,
58
+ aliases,
59
+ declarationDiagnostics
60
+ }))
61
+ ```
62
+
63
+ - declarationsはstable IDでsortする。
64
+ - endpointのpinned digestはdeclaration contentなので含める。
65
+ - corpus facts、evaluation output、mutable repayment stateを含めない。
66
+
67
+ #### evaluationId
68
+
69
+ ```text
70
+ pgw:v1:evaluation:sha256(
71
+ canonicalJson({
72
+ schemaVersion,
73
+ rulesetVersion,
74
+ corpusRoot,
75
+ constraintRoot,
76
+ evaluationConfigDigest,
77
+ policyInputsDigest
78
+ })
79
+ )
80
+ ```
81
+
82
+ 外部表現は`pgw:v1:evaluation:sha256:<64 lowercase hex>`。findings、obligations、blocking decision、exit code、reportを含めない。`policyInputsDigest`はADR-035で定義するbaseline / waiver等のimmutable evaluation inputで、未導入時はcanonical empty policy objectのdigestとする。
83
+
84
+ ### 2. Canonical JSON contractを固定する
85
+
86
+ - object keyは全階層でECMAScript string ascending orderにsortする。
87
+ - serializerはarray orderを保持する。
88
+ - World-owned set-valued arraysはserializer前にstable ID / canonical tupleでsortする。
89
+ - owner-defined ordered arraysはowner orderを保持する。
90
+ - whitespace、indent、BOM、trailing newlineなし。
91
+ - string escapingとfinite JSON number renderingは`JSON.stringify` semantics。
92
+ - `undefined`, sparse array, function, symbol, bigint, `NaN`, Infinityを拒否し、silent omissionしない。
93
+ - canonical JSON bytesはUTF-8。
94
+
95
+ attestationの既存基本規則と一致させるが、serializerのownershipはworld-modelに置き、attestation domain implementationをimportしない。
96
+
97
+ ### 3. Text / bytes normalizationをartifact modeごとに決める
98
+
99
+ #### UTF-8 text / raw prose
100
+
101
+ - strict UTF-8 decode。invalid sequenceをreplacement characterへ変換しない。
102
+ - CRLFとlone CRをLFへnormalizeする。
103
+ - Unicode normalization(NFC / NFD / NFKC / NFKD)は行わない。
104
+ - BOM、trailing whitespace、final newline、zero-width characterを含む他code pointは保持する。
105
+ - normalized stringをUTF-8 encodeしてhashする。
106
+
107
+ したがってline endingだけの差はrootを変えないが、Unicode code point sequence、BOM、whitespace、final newlineの差はrootを変える。
108
+
109
+ #### Structured JSON
110
+
111
+ - strict UTF-8 decode / parse。
112
+ - ownerのversioned schema projectionでsemantic fieldsを選ぶ。
113
+ - object key / string valueへUnicode normalizationを適用しない。
114
+ - object keyをrecursive sortし、semantic set arraysをowner IDでsortする。
115
+ - unknown / unsupported fieldはgeneric name dropせずdiagnostic。
116
+
117
+ #### Binary
118
+
119
+ - extractorがbinaryと明示したartifactだけraw bytesをそのままhashする。
120
+ - extension heuristicだけでtext / binaryを決めない。
121
+
122
+ ### 4. Matrix / attestation等generated artifactをowner-aware projectionする
123
+
124
+ genericに`generatedAt`という名前のkeyを全削除しない。各owner adapterがversioned projectionを持つ。
125
+
126
+ - matrix: `generatedAt`を除外。schema version、Story / AC / TestReference semanticsを含め、Story / AC / refsをowner IDsでsortする。
127
+ - attestation: evidence semanticsとverification statusをpublic DTOから観測し、`producedAt`, `gitCommit`, producer package version、signature bytes、attestation self-digest、future `worldSnapshotRoot` self-referenceを除外する。
128
+ - World snapshot / obligation report: extractor input corpusから除外し、self-referenceを作らない。
129
+ - integrity manifest: owner declarationとしてpath / digest semanticsを観測するが、integrityのraw-byte digest contract自体は変更しない。
130
+
131
+ ### 5. Path、symlink、case semanticsを固定する
132
+
133
+ - project-relative POSIX PathKeyだけをrootへ入れる。
134
+ - `./` / duplicate separatorをnormalizeし、absolute path、drive letter、backslash、`..`を拒否する。
135
+ - cwd、realpath、temp root、absolute checkout rootを入れない。
136
+ - PathKeyのcaseとUnicode sequenceを保持し、case-sensitiveに比較する。
137
+ - symlinkをfollowしない。link entryとtarget stringをfactとして観測し、target file contentを重複hashしない。
138
+ - broken / cyclic / outside-root symlinkはdiagnosticにし、traversalしない。
139
+ - case-fold collisionはportability diagnosticにし、merge / winner選択しない。
140
+ - filesystem列挙後はPathKeyでsortする。
141
+
142
+ これによりADR-032のpath-based identityを変更せず、異なるabsolute checkoutで同じrootを得る。
143
+
144
+ ### 6. Volatile / self / deployment fieldsを明示的に除外する
145
+
146
+ root preimageから除外する:
147
+
148
+ - `generatedAt`, `producedAt`, duration等clock metadata
149
+ - absolute path、cwd、realpath、temp path
150
+ - mtime、inode、PID、host、user
151
+ - git commit
152
+ - package version、`skills/.harness-version`、`deployedAt`等deployment version stamp
153
+ - obligation report、formatter output、persisted repayment state
154
+ - 計算中の`corpusRoot`, Snapshot ID, `constraintRoot`, `evaluationId`
155
+ - attestation self-digest / signatureとfuture `worldSnapshotRoot`
156
+
157
+ 除外はowner projectionで明示し、field name一致のgeneric filterは使わない。
158
+
159
+ `schemaVersion`, `extractorVersion`, `rulesetVersion`はsemantic contract versionなので除外しない。
160
+
161
+ ### 7. Versionsとrelevant config digestをroot-localに含める
162
+
163
+ - corpusRoot: snapshot `schemaVersion`, `extractorVersion`, `corpusConfigDigest`
164
+ - constraintRoot: constraint `schemaVersion`, `rulesetVersion`, `constraintConfigDigest`
165
+ - evaluationId: evaluation `schemaVersion`, `rulesetVersion`, `evaluationConfigDigest`, `policyInputsDigest`
166
+
167
+ config digestはfull `phasegate.config.json` raw hashではなく、resolved defaults込みのscope-specific DTOをcanonical JSON化したSHA-256とする。
168
+
169
+ - corpus scope: corpus root / include-exclude / extractor options
170
+ - constraint scope: declaration locations / rule parameters
171
+ - evaluation scope: evaluation semanticsを変えるresolved options
172
+
173
+ output directory / format、UI limit、validator-system blocking / severity、unrelated layer configは除外する。config不在時は明示default projectionをhashする。
174
+
175
+ ### 8. SHA-256 providerはattestation public facadeに置く
176
+
177
+ hashing capabilityの最終所有先は**attestation public facade**とし、新shared Unitは作らない。
178
+
179
+ public contract:
180
+
181
+ ```text
182
+ Sha256Capability.hashBytes(bytes: Uint8Array): "sha256:<64 lowercase hex>"
183
+ ```
184
+
185
+ - attestation `Digest`, `ContentHasherPort`, infrastructure classをpublic contractへ露出しない。
186
+ - `hashUtf8` helperが必要なら`TextEncoder`後に`hashBytes`へ委譲する。
187
+ - WM-06で既存`NodeCryptoContentHasherAdapter`の`createHash` primitiveをこのpublic capability implementationへ移動または公開する。
188
+ - attestationはattestation-local adapter、world-modelはworld-model infrastructure adapterからcapabilityを呼び、それぞれlocal Digest VOへ変換する。
189
+ - world-model domainはconsumer-owned `WorldHashingPort`だけに依存する。
190
+ - world-modelからattestation内部Port / VO / adapterをdeep importしない。
191
+ - World導入のための新しい`node:crypto` SHA-256 call siteを増やさない。
192
+
193
+ 既存`FileSystemSourceDigesterAdapter`、ci-governance integrity、installationのhash実装を全て統合する作業はWM-06の必須scopeに広げない。
194
+
195
+ ### 9. §10の未決事項へ回答する
196
+
197
+ #### Raw prose fragment hashのUnicode normalization
198
+
199
+ **適用しない。** CRLF / CRだけをLFへtransport-normalizeし、それ以外のUnicode code point sequenceを保持したUTF-8 bytesをhashする。NFC / NFDを同一視すると、repositoryが保持する実bytes差を機械が意味的に同一と主張するため採用しない。
200
+
201
+ #### Hashing capabilityの最終所有先
202
+
203
+ **attestation public facadeを採用する。** 既存`NodeCryptoContentHasherAdapter`を唯一のWorld向けprimitiveとしてpublic plain capability化する。新shared contract / Unitは作らず、world-modelとattestationが各consumer-owned port / local Digestへadaptする。
204
+
205
+ ## Consequences
206
+
207
+ ### Positive
208
+
209
+ - clean checkout、filesystem order、absolute root、JSON key order、LF / CRLFに依存しないrootを得られる。
210
+ - corpus、constraint、evaluationの変更原因をrootで分離できる。
211
+ - generated reportやself digestを入力にする循環を防げる。
212
+ - schema / extractor / ruleset / relevant config変更を明示的にrootへ反映できる。
213
+ - attestation内部domain modelを漏らさず、`node:crypto`実装を増やさずにSHA-256を再利用できる。
214
+
215
+ ### Negative / Trade-off
216
+
217
+ - owner artifactごとにversioned semantic projectionとarray sort ruleが必要になる。
218
+ - Unicode normalizationを行わないため、見た目が同じNFC / NFD textは別digestになる。
219
+ - raw integrity digestとWorld normalized text digestは同じfileでも異なる場合がある。
220
+ - attestationがgeneric hashing capabilityのdeployment ownerとなる。
221
+ - version bump disciplineを誤ると異なるextractor / rulesetが同じversionを名乗るリスクがある。
222
+
223
+ ## Alternatives
224
+
225
+ - **full file raw bytesを全artifactでhashする** — LF / CRLF、pretty JSON、matrix `generatedAt`でlogical rootが変わるため不採用。
226
+ - **全arrayをgeneric sortする** — ordered process / prose semanticsを壊すため不採用。
227
+ - **Unicode NFCを適用する** — repository byte差を意味的同一と主張するため不採用。
228
+ - **full config raw hashをrootへ入れる** — output / unrelated validator変更でrootが不必要に変わるため不採用。
229
+ - **obligation reportをevaluation inputにする** — derived output改竄で判定を変えられるため不採用。
230
+ - **attestation内部`ContentHasherPort` / `Digest`をworld-modelからimportする** — ADR-031のownership / anti-corruption境界に反するため不採用。
231
+ - **minimal shared hashing Unitを新設する** —primitive一つに新ownershipとproduct lifecycleを追加するコストが現状のpublic facadeより大きいため不採用。
232
+ - **world-model内に新しい`node:crypto` adapterを作る** — SHA-256実装を増やすため不採用。
233
+
234
+ ## 関連要件・文書
235
+
236
+ - `docs/inception/_cross/WI-280/delivery_plan.md` §1, §3 WM-03, §7 ADR-033, §8, §10
237
+ - `docs/inception/_cross/WI-281/logical_design.md`
238
+ - `docs/inception/_cross/WI-282/domain_model.md`
239
+ - `docs/inception/_cross/WI-283/description.md`
240
+ - `docs/inception/_cross/WI-283/domain_model.md`
241
+ - `docs/inception/_cross/WI-283/logical_design.md`
242
+ - `docs/inception/_cross/WI-283/unit_test_design.md`
243
+ - ADR-027(成果物駆動の状態導出)
244
+ - ADR-030(attestation canonical payload / integrity)
245
+ - ADR-031(ownership / artifact kind / import direction)
246
+ - ADR-032(World node identity / PathKey / Snapshot ID)