full-reverse 0.0.0-stage → 1.0.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 (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -2
  3. package/THIRD_PARTY_NOTICES.md +63 -0
  4. package/VERIFICATION.md +156 -0
  5. package/bin/full-reverse.mjs +253 -0
  6. package/package.json +30 -4
  7. package/skills/full-reverse/LICENSE +21 -0
  8. package/skills/full-reverse/README.md +116 -0
  9. package/skills/full-reverse/SKILL.md +173 -0
  10. package/skills/full-reverse/THIRD_PARTY_NOTICES.md +63 -0
  11. package/skills/full-reverse/VERIFICATION.md +156 -0
  12. package/skills/full-reverse/agents/openai.yaml +3 -0
  13. package/skills/full-reverse/package-lock.json +75 -0
  14. package/skills/full-reverse/package.json +21 -0
  15. package/skills/full-reverse/references/investigation-contract.md +171 -0
  16. package/skills/full-reverse/references/workflow-example.md +148 -0
  17. package/skills/full-reverse/references/workspace-layout.md +83 -0
  18. package/skills/full-reverse/schemas/claims.schema.json +123 -0
  19. package/skills/full-reverse/schemas/common.schema.json +305 -0
  20. package/skills/full-reverse/schemas/evidence-index.schema.json +135 -0
  21. package/skills/full-reverse/schemas/examples/claims.example.json +355 -0
  22. package/skills/full-reverse/schemas/examples/evidence-index.example.json +254 -0
  23. package/skills/full-reverse/schemas/examples/external-evidence.example.json +33 -0
  24. package/skills/full-reverse/schemas/examples/inventory.example.json +106 -0
  25. package/skills/full-reverse/schemas/examples/investigation.example.json +159 -0
  26. package/skills/full-reverse/schemas/examples/review.example.json +75 -0
  27. package/skills/full-reverse/schemas/external-evidence.schema.json +68 -0
  28. package/skills/full-reverse/schemas/inventory.schema.json +91 -0
  29. package/skills/full-reverse/schemas/investigation.schema.json +142 -0
  30. package/skills/full-reverse/schemas/review.schema.json +78 -0
  31. package/skills/full-reverse/scripts/lib/cli.mjs +254 -0
  32. package/skills/full-reverse/scripts/lib/jsonscan.mjs +285 -0
  33. package/skills/full-reverse/scripts/lib/rea.mjs +496 -0
  34. package/skills/full-reverse/scripts/lib/schemas.mjs +79 -0
  35. package/skills/full-reverse/scripts/lib/scope.mjs +59 -0
  36. package/skills/full-reverse/scripts/lib/selectors.mjs +256 -0
  37. package/skills/full-reverse/scripts/lib/util.mjs +333 -0
  38. package/skills/full-reverse/scripts/lib/validate.mjs +1133 -0
  39. package/skills/full-reverse/scripts/lib/workspace.mjs +861 -0
  40. package/skills/full-reverse/scripts/validate-investigation.mjs +28 -0
  41. package/skills/full-reverse-inspect/SKILL.md +119 -0
  42. package/skills/full-reverse-inspect/agents/openai.yaml +5 -0
  43. package/skills/full-reverse-inspect/references/android.md +84 -0
  44. package/skills/full-reverse-inspect/references/evidence-workflows.md +170 -0
  45. package/skills/full-reverse-inspect/references/javascript-electron.md +146 -0
  46. package/skills/full-reverse-inspect/references/managed.md +59 -0
  47. package/skills/full-reverse-inspect/references/native.md +290 -0
  48. package/skills/full-reverse-inspect/references/packages-and-specialized-artifacts.md +93 -0
  49. package/skills/full-reverse-inspect/references/recorded-evidence.md +118 -0
  50. package/skills/full-reverse-inventory/SKILL.md +134 -0
  51. package/skills/full-reverse-inventory/agents/openai.yaml +5 -0
  52. package/skills/full-reverse-model/SKILL.md +148 -0
  53. package/skills/full-reverse-model/agents/openai.yaml +5 -0
  54. package/skills/full-reverse-model/references/claim-classification.md +85 -0
  55. package/skills/full-reverse-model/references/specification-template.md +199 -0
  56. package/skills/full-reverse-observe/SKILL.md +97 -0
  57. package/skills/full-reverse-observe/agents/openai.yaml +5 -0
  58. package/skills/full-reverse-observe/references/runtime-scope.md +301 -0
  59. package/skills/full-reverse-verify/SKILL.md +111 -0
  60. package/skills/full-reverse-verify/agents/openai.yaml +5 -0
  61. package/skills/full-reverse-verify/references/review-checklist.md +99 -0
@@ -0,0 +1,123 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://full-reverse.local/schemas/claims.schema.json",
4
+ "title": "Full Reverse claims (claims.json)",
5
+ "description": "Written only by the model specialist. Each claim links statements to immutable evidence by file digest, evidence ID and RFC 6901 selectors. The validator checks state/basis/coverage consistency and resolves selectors against saved evidence; it does not judge whether evidence supports the statement.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema_version", "investigation_id", "created_at", "inputs", "claims"],
9
+ "properties": {
10
+ "schema_version": { "const": "full-reverse.claims/1" },
11
+ "investigation_id": { "$ref": "common.schema.json#/$defs/investigationId" },
12
+ "created_at": { "$ref": "common.schema.json#/$defs/timestamp" },
13
+ "inputs": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "required": ["inventory", "evidence_index"],
17
+ "properties": {
18
+ "inventory": { "oneOf": [{ "$ref": "common.schema.json#/$defs/fileDigest" }, { "type": "null" }] },
19
+ "evidence_index": { "$ref": "common.schema.json#/$defs/fileDigest" }
20
+ }
21
+ },
22
+ "claims": {
23
+ "type": "array",
24
+ "items": {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": [
28
+ "claim_id", "statement", "state", "basis", "polarity", "question_ids", "build_id",
29
+ "comparison_build_ids", "context", "evidence", "locations", "coverage", "limitations",
30
+ "contradicts", "derivation", "inference", "unavailable_reason", "user_statement"
31
+ ],
32
+ "properties": {
33
+ "claim_id": { "$ref": "common.schema.json#/$defs/claimId" },
34
+ "statement": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
35
+ "state": { "enum": ["observed", "derived", "inferred", "unknown", "unavailable"] },
36
+ "basis": { "enum": ["static", "runtime", "recorded", "external", "user-statement"] },
37
+ "polarity": { "enum": ["presence", "absence"] },
38
+ "question_ids": { "type": "array", "minItems": 1, "items": { "$ref": "common.schema.json#/$defs/questionId" } },
39
+ "build_id": { "$ref": "common.schema.json#/$defs/buildId" },
40
+ "comparison_build_ids": {
41
+ "type": "array",
42
+ "items": { "$ref": "common.schema.json#/$defs/buildId" },
43
+ "description": "Additional builds this claim compares. Empty for single-build claims; evidence from any other build is a cross-target citation and fails."
44
+ },
45
+ "context": {
46
+ "type": "object",
47
+ "additionalProperties": false,
48
+ "required": ["question", "bounds"],
49
+ "properties": {
50
+ "question": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
51
+ "bounds": { "$ref": "common.schema.json#/$defs/nonEmptyString", "description": "The explicit scope the statement addresses (build, component, scenario, collection)." }
52
+ }
53
+ },
54
+ "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidenceRef" } },
55
+ "locations": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/location" } },
56
+ "coverage": {
57
+ "type": "object",
58
+ "additionalProperties": false,
59
+ "required": ["status", "scope", "evidence"],
60
+ "properties": {
61
+ "status": { "enum": ["complete", "partial", "unknown", "unavailable"] },
62
+ "scope": { "type": "string", "description": "Exact scope the coverage status applies to. Page exhaustion is not source completeness." },
63
+ "evidence": {
64
+ "type": "array",
65
+ "items": { "$ref": "common.schema.json#/$defs/evidenceRef" },
66
+ "description": "Evidence refs with selectors (role coverage) that expose the completeness fields of the saved record."
67
+ }
68
+ }
69
+ },
70
+ "limitations": { "type": "array", "items": { "type": "string" } },
71
+ "contradicts": {
72
+ "type": "array",
73
+ "items": { "$ref": "common.schema.json#/$defs/claimId" }
74
+ },
75
+ "derivation": {
76
+ "oneOf": [
77
+ { "type": "null" },
78
+ {
79
+ "type": "object",
80
+ "additionalProperties": false,
81
+ "required": ["input_claim_ids", "input_evidence", "procedure"],
82
+ "properties": {
83
+ "input_claim_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/claimId" } },
84
+ "input_evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidenceRef" } },
85
+ "procedure": { "$ref": "common.schema.json#/$defs/nonEmptyString", "description": "Reproducible derivation steps." }
86
+ }
87
+ }
88
+ ]
89
+ },
90
+ "inference": {
91
+ "oneOf": [
92
+ { "type": "null" },
93
+ {
94
+ "type": "object",
95
+ "additionalProperties": false,
96
+ "required": ["rationale", "uncertainty"],
97
+ "properties": {
98
+ "rationale": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
99
+ "uncertainty": { "$ref": "common.schema.json#/$defs/nonEmptyString" }
100
+ }
101
+ }
102
+ ]
103
+ },
104
+ "unavailable_reason": { "type": ["string", "null"] },
105
+ "user_statement": {
106
+ "oneOf": [
107
+ { "type": "null" },
108
+ {
109
+ "type": "object",
110
+ "additionalProperties": false,
111
+ "required": ["conversation_ref", "recorded_at"],
112
+ "properties": {
113
+ "conversation_ref": { "type": ["string", "null"] },
114
+ "recorded_at": { "$ref": "common.schema.json#/$defs/timestamp" }
115
+ }
116
+ }
117
+ ]
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
@@ -0,0 +1,305 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://full-reverse.local/schemas/common.schema.json",
4
+ "title": "Full Reverse shared definitions",
5
+ "description": "Identifiers, digests, evidence references, selectors, locations and build identities shared by every Full Reverse schema.",
6
+ "$defs": {
7
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
8
+ "timestamp": {
9
+ "type": "string",
10
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$"
11
+ },
12
+ "relativePath": {
13
+ "type": "string",
14
+ "minLength": 1,
15
+ "maxLength": 1024,
16
+ "pattern": "^(?!/)(?![A-Za-z]:)[^\\\\\\u0000]+$"
17
+ },
18
+ "nonEmptyString": { "type": "string", "minLength": 1 },
19
+ "investigationId": { "type": "string", "pattern": "^inv_[a-z0-9][a-z0-9_-]{2,62}$" },
20
+ "buildId": { "type": "string", "pattern": "^bld_[a-z0-9][a-z0-9_-]{0,62}$" },
21
+ "questionId": { "type": "string", "pattern": "^q_[a-z0-9][a-z0-9_-]{0,62}$" },
22
+ "claimId": { "type": "string", "pattern": "^clm_[a-z0-9][a-z0-9_-]{0,62}$" },
23
+ "stepId": { "type": "string", "pattern": "^step_[a-z0-9][a-z0-9_-]{0,62}$" },
24
+ "grantId": { "type": "string", "pattern": "^auth_[a-z0-9][a-z0-9_-]{0,62}$" },
25
+ "findingId": { "type": "string", "pattern": "^fnd_[a-z0-9][a-z0-9_-]{0,62}$" },
26
+ "scenarioId": { "type": "string", "pattern": "^scn_[a-z0-9][a-z0-9_-]{0,62}$" },
27
+ "entryId": { "type": "string", "pattern": "^ei_[0-9a-f]{16}$" },
28
+ "evidenceId": { "type": "string", "pattern": "^ev_[0-9a-f]{64}$" },
29
+ "externalId": { "type": "string", "pattern": "^ext_[0-9a-f]{64}$" },
30
+ "jsonPointer": {
31
+ "type": "string",
32
+ "pattern": "^(/([^~/]|~[01])*)*$"
33
+ },
34
+ "fileDigest": {
35
+ "type": "object",
36
+ "additionalProperties": false,
37
+ "required": ["path", "sha256"],
38
+ "properties": {
39
+ "path": { "$ref": "#/$defs/relativePath" },
40
+ "sha256": { "$ref": "#/$defs/sha256" }
41
+ }
42
+ },
43
+ "jsonPointerSelector": {
44
+ "type": "object",
45
+ "additionalProperties": false,
46
+ "required": ["type", "pointer", "role"],
47
+ "properties": {
48
+ "type": { "const": "json-pointer" },
49
+ "pointer": {
50
+ "$ref": "#/$defs/jsonPointer",
51
+ "description": "RFC 6901 pointer relative to the cited evidence record root (not the bundle root)."
52
+ },
53
+ "role": {
54
+ "enum": ["identity", "address", "path", "collection", "value", "count", "line-count", "event", "coverage", "other"]
55
+ },
56
+ "expect": {
57
+ "description": "Assertion about the value at pointer. equals: exact JSON value; exists: pointer must resolve; sha256: SHA-256 hex of REA canonical JSON of the value (keys sorted by UTF-16 code unit, ECMAScript JSON.stringify scalars, no whitespace; values must be finite and safe).",
58
+ "oneOf": [
59
+ {
60
+ "type": "object",
61
+ "additionalProperties": false,
62
+ "required": ["equals"],
63
+ "properties": { "equals": {} }
64
+ },
65
+ {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": ["exists"],
69
+ "properties": { "exists": { "const": true } }
70
+ },
71
+ {
72
+ "type": "object",
73
+ "additionalProperties": false,
74
+ "required": ["sha256"],
75
+ "properties": { "sha256": { "$ref": "#/$defs/sha256" } }
76
+ }
77
+ ]
78
+ },
79
+ "note": { "type": "string" }
80
+ }
81
+ },
82
+ "externalSelector": {
83
+ "oneOf": [
84
+ {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "required": ["type", "start", "end"],
88
+ "properties": {
89
+ "type": { "const": "line-range" },
90
+ "start": { "type": "integer", "minimum": 1 },
91
+ "end": { "type": "integer", "minimum": 1 },
92
+ "note": { "type": "string" }
93
+ }
94
+ },
95
+ {
96
+ "type": "object",
97
+ "additionalProperties": false,
98
+ "required": ["type", "start", "end"],
99
+ "properties": {
100
+ "type": { "const": "byte-range" },
101
+ "start": { "type": "integer", "minimum": 0 },
102
+ "end": { "type": "integer", "minimum": 0, "description": "Exclusive end offset." },
103
+ "note": { "type": "string" }
104
+ }
105
+ },
106
+ {
107
+ "type": "object",
108
+ "additionalProperties": false,
109
+ "required": ["type", "x", "y", "width", "height"],
110
+ "properties": {
111
+ "type": { "const": "image-region" },
112
+ "x": { "type": "integer", "minimum": 0 },
113
+ "y": { "type": "integer", "minimum": 0 },
114
+ "width": { "type": "integer", "minimum": 1 },
115
+ "height": { "type": "integer", "minimum": 1 },
116
+ "note": { "type": "string" }
117
+ }
118
+ },
119
+ {
120
+ "type": "object",
121
+ "additionalProperties": false,
122
+ "required": ["type", "ordinal"],
123
+ "properties": {
124
+ "type": { "const": "event-ordinal" },
125
+ "ordinal": { "type": "integer", "minimum": 0, "description": "Zero-based event index in a JSONL/NDJSON file or top-level JSON array." },
126
+ "note": { "type": "string" }
127
+ }
128
+ },
129
+ {
130
+ "type": "object",
131
+ "additionalProperties": false,
132
+ "required": ["type", "start_ms", "end_ms"],
133
+ "properties": {
134
+ "type": { "const": "time-range" },
135
+ "start_ms": { "type": "number", "minimum": 0 },
136
+ "end_ms": { "type": "number", "minimum": 0 },
137
+ "note": { "type": "string" }
138
+ }
139
+ },
140
+ {
141
+ "type": "object",
142
+ "additionalProperties": false,
143
+ "required": ["type"],
144
+ "properties": {
145
+ "type": { "const": "whole-file" },
146
+ "note": { "type": "string" }
147
+ }
148
+ }
149
+ ]
150
+ },
151
+ "canonicalRef": {
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "required": ["kind", "file", "sha256", "evidence_id"],
155
+ "properties": {
156
+ "kind": { "const": "canonical" },
157
+ "file": { "$ref": "#/$defs/relativePath" },
158
+ "sha256": { "$ref": "#/$defs/sha256", "description": "SHA-256 of the immutable evidence file." },
159
+ "evidence_id": { "$ref": "#/$defs/evidenceId" },
160
+ "selectors": { "type": "array", "items": { "$ref": "#/$defs/jsonPointerSelector" } }
161
+ }
162
+ },
163
+ "externalRef": {
164
+ "type": "object",
165
+ "additionalProperties": false,
166
+ "required": ["kind", "file", "sha256", "ext_id"],
167
+ "properties": {
168
+ "kind": { "const": "external" },
169
+ "file": { "$ref": "#/$defs/relativePath" },
170
+ "sha256": { "$ref": "#/$defs/sha256" },
171
+ "ext_id": { "$ref": "#/$defs/externalId" },
172
+ "selectors": { "type": "array", "items": { "$ref": "#/$defs/externalSelector" } }
173
+ }
174
+ },
175
+ "evidenceRef": {
176
+ "oneOf": [{ "$ref": "#/$defs/canonicalRef" }, { "$ref": "#/$defs/externalRef" }]
177
+ },
178
+ "buildIdentity": {
179
+ "type": "object",
180
+ "additionalProperties": false,
181
+ "required": ["method", "sha256", "bytes", "coverage", "rea_format", "note"],
182
+ "properties": {
183
+ "method": {
184
+ "enum": ["file-sha256", "rea-subject-digest", "archive-member"],
185
+ "description": "file-sha256: full streamed SHA-256 of one file. rea-subject-digest: the subject.digest.sha256 REA reported for a directory/bundle/app (with declared coverage). archive-member: SHA-256 of a member extracted from the parent build."
186
+ },
187
+ "sha256": { "$ref": "#/$defs/sha256" },
188
+ "bytes": { "type": ["integer", "null"], "minimum": 0 },
189
+ "coverage": {
190
+ "enum": ["complete", "partial", "unknown"],
191
+ "description": "Coverage of the identity. A partial or unknown manifest is never a whole-directory fingerprint."
192
+ },
193
+ "rea_format": { "type": ["string", "null"] },
194
+ "note": { "type": "string" }
195
+ }
196
+ },
197
+ "build": {
198
+ "type": "object",
199
+ "additionalProperties": false,
200
+ "required": ["build_id", "kind", "name", "identity", "parent_build_id"],
201
+ "properties": {
202
+ "build_id": { "$ref": "#/$defs/buildId" },
203
+ "kind": { "enum": ["file", "directory", "bundle", "archive", "member"] },
204
+ "name": { "$ref": "#/$defs/nonEmptyString" },
205
+ "version_label": { "type": "string" },
206
+ "identity": { "$ref": "#/$defs/buildIdentity" },
207
+ "local_path": {
208
+ "type": ["string", "null"],
209
+ "description": "Absolute path of the target at identification time, used only to re-check identity on resume. Not proof of identity."
210
+ },
211
+ "parent_build_id": { "oneOf": [{ "$ref": "#/$defs/buildId" }, { "type": "null" }] }
212
+ }
213
+ },
214
+ "location": {
215
+ "type": "object",
216
+ "required": ["kind", "evidence"],
217
+ "properties": {
218
+ "kind": { "enum": ["artifact-member", "source-range", "native-procedure", "resource-node", "runtime-event"] },
219
+ "evidence": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/evidenceRef" } }
220
+ },
221
+ "oneOf": [
222
+ {
223
+ "type": "object",
224
+ "additionalProperties": false,
225
+ "required": ["kind", "member_path", "evidence"],
226
+ "properties": {
227
+ "kind": { "const": "artifact-member" },
228
+ "member_path": { "$ref": "#/$defs/nonEmptyString" },
229
+ "container_sha256": { "$ref": "#/$defs/sha256" },
230
+ "member_sha256": { "$ref": "#/$defs/sha256" },
231
+ "evidence": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/evidenceRef" } }
232
+ }
233
+ },
234
+ {
235
+ "type": "object",
236
+ "additionalProperties": false,
237
+ "required": ["kind", "path", "start_line", "end_line", "origin", "evidence"],
238
+ "properties": {
239
+ "kind": { "const": "source-range" },
240
+ "path": { "$ref": "#/$defs/nonEmptyString" },
241
+ "start_line": { "type": "integer", "minimum": 1 },
242
+ "end_line": { "type": "integer", "minimum": 1 },
243
+ "origin": { "const": "recovered", "description": "Lines of recovered/decompiled/unpacked text, never original-source lines." },
244
+ "member_sha256": { "$ref": "#/$defs/sha256" },
245
+ "evidence": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/evidenceRef" } }
246
+ }
247
+ },
248
+ {
249
+ "type": "object",
250
+ "additionalProperties": false,
251
+ "required": ["kind", "target_sha256", "provider", "address_space", "address", "evidence"],
252
+ "properties": {
253
+ "kind": { "const": "native-procedure" },
254
+ "target_sha256": { "$ref": "#/$defs/sha256" },
255
+ "provider": {
256
+ "type": "object",
257
+ "additionalProperties": false,
258
+ "required": ["id", "version"],
259
+ "properties": {
260
+ "id": { "$ref": "#/$defs/nonEmptyString" },
261
+ "version": { "type": ["string", "null"] }
262
+ }
263
+ },
264
+ "address_space": {
265
+ "$ref": "#/$defs/nonEmptyString",
266
+ "description": "Use provider-reported when the address is exactly what the provider reported and no mapping is claimed. Any other value (for example image or file) must be asserted by a verified role=identity selector, otherwise the validator reports it unverified."
267
+ },
268
+ "address": { "$ref": "#/$defs/nonEmptyString" },
269
+ "procedure": { "type": "string" },
270
+ "file_offset": { "type": "integer", "minimum": 0 },
271
+ "mapping": {
272
+ "type": "string",
273
+ "description": "Required with file_offset: how the offset maps to the address (observed mapping reported by evidence)."
274
+ },
275
+ "evidence": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/evidenceRef" } }
276
+ },
277
+ "dependentRequired": { "file_offset": ["mapping"] }
278
+ },
279
+ {
280
+ "type": "object",
281
+ "additionalProperties": false,
282
+ "required": ["kind", "node_id", "evidence"],
283
+ "properties": {
284
+ "kind": { "const": "resource-node" },
285
+ "node_id": { "$ref": "#/$defs/nonEmptyString" },
286
+ "member_path": { "type": "string" },
287
+ "member_sha256": { "$ref": "#/$defs/sha256" },
288
+ "evidence": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/evidenceRef" } }
289
+ }
290
+ },
291
+ {
292
+ "type": "object",
293
+ "additionalProperties": false,
294
+ "required": ["kind", "scenario_id", "event_id", "evidence"],
295
+ "properties": {
296
+ "kind": { "const": "runtime-event" },
297
+ "scenario_id": { "$ref": "#/$defs/scenarioId" },
298
+ "event_id": { "type": ["string", "integer"] },
299
+ "evidence": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/evidenceRef" } }
300
+ }
301
+ }
302
+ ]
303
+ }
304
+ }
305
+ }
@@ -0,0 +1,135 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://full-reverse.local/schemas/evidence-index.schema.json",
4
+ "title": "Full Reverse evidence index (evidence/index.json)",
5
+ "description": "Sidecar index of immutable evidence files. Written only by the helper (init-workspace, publish-evidence, register-external). Canonical REA records are never modified; custom metadata lives only here. Intrinsic fields are recomputed from the saved file during validation, so labels here are never proof of identity.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema_version", "investigation_id", "updated_at", "entries"],
9
+ "properties": {
10
+ "schema_version": { "const": "full-reverse.evidence-index/1" },
11
+ "investigation_id": { "$ref": "common.schema.json#/$defs/investigationId" },
12
+ "updated_at": { "$ref": "common.schema.json#/$defs/timestamp" },
13
+ "entries": { "type": "array", "items": { "$ref": "#/$defs/entry" } }
14
+ },
15
+ "$defs": {
16
+ "recordSummary": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["evidence_id", "pointer", "operation", "predicate_type", "confidence", "authority", "binding_digests", "parent_evidence_id"],
20
+ "properties": {
21
+ "evidence_id": { "$ref": "common.schema.json#/$defs/evidenceId" },
22
+ "pointer": { "$ref": "common.schema.json#/$defs/jsonPointer", "description": "Location of the record in the file: empty for a single-record file, /records/N in a bundle." },
23
+ "operation": { "type": "string" },
24
+ "predicate_type": { "type": "string" },
25
+ "confidence": { "enum": ["observed", "derived", "inferred"] },
26
+ "authority": { "type": "string" },
27
+ "binding_digests": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/sha256" } },
28
+ "parent_evidence_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/evidenceId" }, { "type": "null" }] }
29
+ }
30
+ },
31
+ "entry": {
32
+ "type": "object",
33
+ "additionalProperties": false,
34
+ "required": [
35
+ "entry_id", "kind", "file", "sha256", "bytes", "status", "content_type", "producer", "operation",
36
+ "predicate_type", "records", "records_truncated", "id_authentication", "invocation", "target",
37
+ "external", "published_at", "note"
38
+ ],
39
+ "properties": {
40
+ "entry_id": { "$ref": "common.schema.json#/$defs/entryId" },
41
+ "kind": { "enum": ["canonical-record", "canonical-bundle", "derived-view", "external", "diagnostic", "interrupted-output"] },
42
+ "file": { "$ref": "common.schema.json#/$defs/relativePath" },
43
+ "sha256": { "$ref": "common.schema.json#/$defs/sha256" },
44
+ "bytes": { "type": "integer", "minimum": 0 },
45
+ "status": { "enum": ["complete", "error", "interrupted"] },
46
+ "content_type": { "enum": ["rea-record", "rea-bundle", "rea-error", "jsonl", "json", "text", "binary", "empty"] },
47
+ "producer": {
48
+ "type": "object",
49
+ "additionalProperties": false,
50
+ "required": ["name", "version", "provider"],
51
+ "properties": {
52
+ "name": { "type": ["string", "null"] },
53
+ "version": { "type": ["string", "null"] },
54
+ "provider": {
55
+ "oneOf": [
56
+ { "type": "null" },
57
+ {
58
+ "type": "object",
59
+ "additionalProperties": false,
60
+ "required": ["id", "name", "version"],
61
+ "properties": {
62
+ "id": { "type": "string" },
63
+ "name": { "type": "string" },
64
+ "version": { "type": ["string", "null"] }
65
+ }
66
+ }
67
+ ]
68
+ }
69
+ }
70
+ },
71
+ "operation": { "type": ["string", "null"] },
72
+ "predicate_type": { "type": ["string", "null"] },
73
+ "records": {
74
+ "type": "array",
75
+ "items": { "$ref": "#/$defs/recordSummary" },
76
+ "description": "Records in a canonical file/bundle/view. Empty for external, diagnostic and interrupted entries."
77
+ },
78
+ "records_truncated": { "type": "boolean" },
79
+ "id_authentication": {
80
+ "type": "object",
81
+ "additionalProperties": false,
82
+ "required": ["status", "reason"],
83
+ "properties": {
84
+ "status": { "enum": ["verified", "unverified", "failed", "not-applicable"] },
85
+ "reason": { "type": ["string", "null"] }
86
+ },
87
+ "description": "Result when the helper recomputed every record's semantic evidence_id at publication."
88
+ },
89
+ "invocation": {
90
+ "type": "object",
91
+ "additionalProperties": false,
92
+ "required": ["source", "command", "exit_code", "stderr_file", "stderr_sha256", "step_id"],
93
+ "properties": {
94
+ "source": { "enum": ["cli", "session", "export", "external", "unknown"] },
95
+ "command": { "oneOf": [{ "type": "array", "items": { "type": "string" } }, { "type": "null" }] },
96
+ "exit_code": { "type": ["integer", "null"] },
97
+ "stderr_file": { "oneOf": [{ "$ref": "common.schema.json#/$defs/relativePath" }, { "type": "null" }] },
98
+ "stderr_sha256": { "oneOf": [{ "$ref": "common.schema.json#/$defs/sha256" }, { "type": "null" }] },
99
+ "step_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/stepId" }, { "type": "null" }] }
100
+ }
101
+ },
102
+ "target": {
103
+ "type": "object",
104
+ "additionalProperties": false,
105
+ "required": ["association", "build_id", "binding_source", "binding_digests", "identity_state"],
106
+ "properties": {
107
+ "association": {
108
+ "enum": ["intrinsic", "declared", "unbound"],
109
+ "description": "intrinsic: the saved record itself carries a digest (REA subject, or a process-capture manifest executable digest) and it equals the build identity. declared: build_id was supplied by the analyst because the record carries no digest; corroborated only procedurally. unbound: none."
110
+ },
111
+ "build_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/buildId" }, { "type": "null" }] },
112
+ "binding_source": {
113
+ "enum": ["subject", "process-capture-manifest", "none"],
114
+ "description": "Where the binding digests were read from in the saved record."
115
+ },
116
+ "binding_digests": {
117
+ "type": "array",
118
+ "items": { "$ref": "common.schema.json#/$defs/sha256" },
119
+ "description": "Digests extracted intrinsically from every record in the file."
120
+ },
121
+ "identity_state": {
122
+ "type": ["string", "null"],
123
+ "description": "Executable identity state reported by the producer (for example path_metadata_unchanged); preserved, never strengthened."
124
+ }
125
+ }
126
+ },
127
+ "external": {
128
+ "oneOf": [{ "type": "null" }, { "$ref": "external-evidence.schema.json" }]
129
+ },
130
+ "published_at": { "$ref": "common.schema.json#/$defs/timestamp" },
131
+ "note": { "type": "string" }
132
+ }
133
+ }
134
+ }
135
+ }