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,106 @@
1
+ {
2
+ "schema_version": "full-reverse.inventory/1",
3
+ "investigation_id": "inv_20260115-example",
4
+ "created_at": "2026-01-15T10:00:00Z",
5
+ "inputs": {
6
+ "evidence_index": {
7
+ "path": "evidence/index.json",
8
+ "sha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
9
+ }
10
+ },
11
+ "artifacts": [
12
+ {
13
+ "build_id": "bld_app-asar",
14
+ "artifact_kind": "javascript-electron",
15
+ "format": "asar",
16
+ "architecture": null,
17
+ "version": "1.4.2",
18
+ "components": [
19
+ {
20
+ "component_id": "cmp_main-process",
21
+ "kind": "javascript-module",
22
+ "path": "main.js",
23
+ "sha256": null,
24
+ "description": "Electron main-process entry",
25
+ "evidence": [
26
+ {
27
+ "kind": "canonical",
28
+ "file": "evidence/records/0123456789abcdef-analyze-javascript-application.json",
29
+ "sha256": "1111111111111111111111111111111111111111111111111111111111111111",
30
+ "evidence_id": "ev_2222222222222222222222222222222222222222222222222222222222222222",
31
+ "selectors": [
32
+ {
33
+ "type": "json-pointer",
34
+ "pointer": "/normalized_result/graph/modules/0/path",
35
+ "role": "path",
36
+ "expect": {
37
+ "equals": "main.js"
38
+ }
39
+ }
40
+ ]
41
+ }
42
+ ]
43
+ }
44
+ ],
45
+ "capabilities": [
46
+ {
47
+ "capability": "static-javascript-analysis",
48
+ "status": "available",
49
+ "detail": "rea analyze-javascript-application completed",
50
+ "evidence": [
51
+ {
52
+ "kind": "canonical",
53
+ "file": "evidence/records/0123456789abcdef-analyze-javascript-application.json",
54
+ "sha256": "1111111111111111111111111111111111111111111111111111111111111111",
55
+ "evidence_id": "ev_2222222222222222222222222222222222222222222222222222222222222222",
56
+ "selectors": [
57
+ {
58
+ "type": "json-pointer",
59
+ "pointer": "/normalized_result/summary/module_count",
60
+ "role": "count",
61
+ "expect": {
62
+ "equals": 42
63
+ }
64
+ }
65
+ ]
66
+ }
67
+ ]
68
+ },
69
+ {
70
+ "capability": "native-disassembly",
71
+ "status": "unavailable",
72
+ "detail": "No native binary in this artifact",
73
+ "evidence": []
74
+ }
75
+ ],
76
+ "evidence": [
77
+ {
78
+ "kind": "canonical",
79
+ "file": "evidence/records/0123456789abcdef-analyze-javascript-application.json",
80
+ "sha256": "1111111111111111111111111111111111111111111111111111111111111111",
81
+ "evidence_id": "ev_2222222222222222222222222222222222222222222222222222222222222222",
82
+ "selectors": [
83
+ {
84
+ "type": "json-pointer",
85
+ "pointer": "/normalized_result/summary/module_count",
86
+ "role": "count",
87
+ "expect": {
88
+ "equals": 42
89
+ }
90
+ }
91
+ ]
92
+ }
93
+ ],
94
+ "unknowns": []
95
+ }
96
+ ],
97
+ "unknowns": [
98
+ {
99
+ "unknown_id": "unk_server-side",
100
+ "text": "Server-side pricing is not visible from the client artifact.",
101
+ "question_ids": [
102
+ "q_server-pricing"
103
+ ]
104
+ }
105
+ ]
106
+ }
@@ -0,0 +1,159 @@
1
+ {
2
+ "schema_version": "full-reverse.investigation/1",
3
+ "investigation_id": "inv_20260115-example",
4
+ "created_at": "2026-01-15T10:00:00Z",
5
+ "objective": "Explain how the packaged application computes the discount shown at checkout.",
6
+ "non_goals": [
7
+ "Reconstruct the original source",
8
+ "Prove equivalence of a replica"
9
+ ],
10
+ "workspace": {
11
+ "path": "/work/investigations/example",
12
+ "allowed_output_paths": [
13
+ "/work/investigations/example"
14
+ ]
15
+ },
16
+ "builds": [
17
+ {
18
+ "build_id": "bld_app-asar",
19
+ "kind": "file",
20
+ "name": "app.asar",
21
+ "version_label": "1.4.2",
22
+ "identity": {
23
+ "method": "file-sha256",
24
+ "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
25
+ "bytes": 1048576,
26
+ "coverage": "complete",
27
+ "rea_format": "asar",
28
+ "note": "Full streamed SHA-256 of the ASAR file."
29
+ },
30
+ "local_path": "/apps/Example/resources/app.asar",
31
+ "parent_build_id": null
32
+ },
33
+ {
34
+ "build_id": "bld_app-dir",
35
+ "kind": "directory",
36
+ "name": "Example app directory",
37
+ "identity": {
38
+ "method": "rea-subject-digest",
39
+ "sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
40
+ "bytes": null,
41
+ "coverage": "unknown",
42
+ "rea_format": "directory",
43
+ "note": "Digest REA reported as the subject of the directory analysis; manifest coverage not established."
44
+ },
45
+ "local_path": null,
46
+ "parent_build_id": null
47
+ }
48
+ ],
49
+ "questions": [
50
+ {
51
+ "question_id": "q_discount-rule",
52
+ "text": "Which module computes the checkout discount?",
53
+ "status": "answered",
54
+ "reason": null,
55
+ "claim_ids": [
56
+ "clm_discount-module"
57
+ ],
58
+ "feature": "discount",
59
+ "build_ids": [
60
+ "bld_app-asar"
61
+ ]
62
+ },
63
+ {
64
+ "question_id": "q_server-pricing",
65
+ "text": "Does the client contact a pricing service?",
66
+ "status": "unresolved",
67
+ "reason": "Only static evidence is available; runtime observation was not authorized.",
68
+ "claim_ids": [
69
+ "clm_pricing-unknown"
70
+ ],
71
+ "feature": null
72
+ }
73
+ ],
74
+ "authorizations": [
75
+ {
76
+ "grant_id": "auth_launch-sandbox",
77
+ "user_instruction": "You may launch the app copy in /tmp/sandbox with no network to observe checkout.",
78
+ "conversation_ref": "message 12",
79
+ "recorded_at": "2026-01-15T10:00:00Z",
80
+ "build_id": "bld_app-asar",
81
+ "permitted_effects": [
82
+ "launch",
83
+ "file-write"
84
+ ],
85
+ "environment_boundary": "Disposable copy; no network",
86
+ "storage_boundary": "Writes only under /tmp/sandbox and the investigation workspace",
87
+ "valid_scope": "This investigation, build bld_app-asar only",
88
+ "persistence": "session",
89
+ "reconfirmed_at": null
90
+ }
91
+ ],
92
+ "tools": [
93
+ {
94
+ "name": "rea",
95
+ "version": "6.4.0",
96
+ "observed_at": "2026-01-15T10:00:00Z",
97
+ "note": "rea --version"
98
+ }
99
+ ],
100
+ "phase": "inspect",
101
+ "steps": [
102
+ {
103
+ "step_id": "step_inspect-js-1",
104
+ "specialist": "inspect",
105
+ "question_ids": [
106
+ "q_discount-rule"
107
+ ],
108
+ "operation": "analyze-javascript-application",
109
+ "attempt": 1,
110
+ "supersedes_step_id": null,
111
+ "status": "completed",
112
+ "build_id": "bld_app-asar",
113
+ "effects": [],
114
+ "authorization_grant_id": null,
115
+ "inputs": [
116
+ {
117
+ "path": "inventory.json",
118
+ "sha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
119
+ }
120
+ ],
121
+ "outputs": [
122
+ {
123
+ "path": "evidence/records/0123456789abcdef-analyze-javascript-application.json",
124
+ "sha256": "1111111111111111111111111111111111111111111111111111111111111111"
125
+ }
126
+ ],
127
+ "started_at": "2026-01-15T10:00:00Z",
128
+ "finished_at": "2026-01-15T10:05:00Z",
129
+ "note": ""
130
+ },
131
+ {
132
+ "step_id": "step_observe-checkout-1",
133
+ "specialist": "observe",
134
+ "question_ids": [
135
+ "q_server-pricing"
136
+ ],
137
+ "operation": "capture-process",
138
+ "attempt": 1,
139
+ "supersedes_step_id": null,
140
+ "status": "planned",
141
+ "build_id": "bld_app-asar",
142
+ "effects": [
143
+ "launch",
144
+ "file-write"
145
+ ],
146
+ "authorization_grant_id": "auth_launch-sandbox",
147
+ "inputs": [],
148
+ "outputs": [],
149
+ "started_at": "2026-01-15T10:10:00Z",
150
+ "finished_at": null,
151
+ "note": "Waiting for user reconfirmation after resume."
152
+ }
153
+ ],
154
+ "lifecycle": {
155
+ "last_resumed_at": null,
156
+ "review_sha256": null,
157
+ "updated_at": "2026-01-15T10:00:00Z"
158
+ }
159
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "schema_version": "full-reverse.review/1",
3
+ "investigation_id": "inv_20260115-example",
4
+ "reviewed_at": "2026-01-15T12:00:00Z",
5
+ "reviewer": "full-reverse-verify",
6
+ "reviewed_inputs": {
7
+ "inventory": {
8
+ "path": "inventory.json",
9
+ "sha256": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
10
+ },
11
+ "evidence_index": {
12
+ "path": "evidence/index.json",
13
+ "sha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
14
+ },
15
+ "claims": {
16
+ "path": "claims.json",
17
+ "sha256": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
18
+ },
19
+ "specs": [
20
+ {
21
+ "path": "specs/discount/requirements.md",
22
+ "sha256": "6666666666666666666666666666666666666666666666666666666666666666"
23
+ },
24
+ {
25
+ "path": "specs/discount/reference-design.md",
26
+ "sha256": "7777777777777777777777777777777777777777777777777777777777777777"
27
+ },
28
+ {
29
+ "path": "specs/index.md",
30
+ "sha256": "8888888888888888888888888888888888888888888888888888888888888888"
31
+ }
32
+ ],
33
+ "scope": {
34
+ "sha256": "9999999999999999999999999999999999999999999999999999999999999999"
35
+ }
36
+ },
37
+ "validator_report": {
38
+ "mode": "closure",
39
+ "outcome": "pass",
40
+ "failed": 0,
41
+ "unverified": 0,
42
+ "note": "validate --mode closure exit 0"
43
+ },
44
+ "dispositions": [
45
+ {
46
+ "question_id": "q_discount-rule",
47
+ "disposition": "answered",
48
+ "reason": "Module located with verified selectors; purpose remains an inference.",
49
+ "claim_ids": [
50
+ "clm_discount-module",
51
+ "clm_discount-purpose"
52
+ ]
53
+ },
54
+ {
55
+ "question_id": "q_server-pricing",
56
+ "disposition": "unresolved",
57
+ "reason": "No runtime evidence was authorized.",
58
+ "claim_ids": [
59
+ "clm_pricing-unknown"
60
+ ]
61
+ }
62
+ ],
63
+ "findings": [
64
+ {
65
+ "finding_id": "fnd_purpose-inference",
66
+ "severity": "minor",
67
+ "category": "semantic-overclaim",
68
+ "claim_id": "clm_discount-purpose",
69
+ "text": "Purpose is inferred from names only; spec must keep the Inferred: prefix.",
70
+ "status": "accepted-limitation",
71
+ "route_to": null
72
+ }
73
+ ],
74
+ "verdict": "approved-with-limits"
75
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://full-reverse.local/schemas/external-evidence.schema.json",
4
+ "title": "Full Reverse external evidence record",
5
+ "description": "One evidence file collected outside REA (screenshot, log, trace, note). Embedded in evidence/index.json as entry.external. ext_id is ext_ + the SHA-256 of the file bytes; the helper derives ext_id, file and registered_at.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "ext_id", "file", "media_type", "observation_kind", "description", "acquisition", "sensitivity",
10
+ "target_association", "limitations", "registered_at"
11
+ ],
12
+ "properties": {
13
+ "ext_id": { "$ref": "common.schema.json#/$defs/externalId" },
14
+ "file": {
15
+ "type": "object",
16
+ "additionalProperties": false,
17
+ "required": ["path", "sha256", "bytes"],
18
+ "properties": {
19
+ "path": { "$ref": "common.schema.json#/$defs/relativePath" },
20
+ "sha256": { "$ref": "common.schema.json#/$defs/sha256" },
21
+ "bytes": { "type": "integer", "minimum": 0 }
22
+ }
23
+ },
24
+ "media_type": { "type": "string", "description": "IANA media type when known, otherwise application/octet-stream." },
25
+ "observation_kind": {
26
+ "enum": ["screenshot", "screen-recording", "log", "trace", "network-log", "packet-capture-original", "crash-dump-original", "note", "user-supplied-document", "other"]
27
+ },
28
+ "description": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
29
+ "acquisition": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["provenance_status", "method", "tool", "acquired_by", "acquired_at", "scenario_id"],
33
+ "properties": {
34
+ "provenance_status": {
35
+ "enum": ["known", "partial", "unknown"],
36
+ "description": "unknown limits supported claims to state inferred; partial to derived at most."
37
+ },
38
+ "method": { "type": ["string", "null"] },
39
+ "tool": { "type": ["string", "null"], "description": "Tool and version used to collect the file, if known." },
40
+ "acquired_by": { "type": ["string", "null"] },
41
+ "acquired_at": { "oneOf": [{ "$ref": "common.schema.json#/$defs/timestamp" }, { "type": "null" }] },
42
+ "scenario_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/scenarioId" }, { "type": "null" }] }
43
+ }
44
+ },
45
+ "sensitivity": {
46
+ "type": "object",
47
+ "additionalProperties": false,
48
+ "required": ["classification", "contains_secrets_or_personal_data", "sharing"],
49
+ "properties": {
50
+ "classification": { "enum": ["public", "internal", "confidential", "restricted", "unknown"] },
51
+ "contains_secrets_or_personal_data": { "enum": ["yes", "no", "unknown"] },
52
+ "sharing": { "type": "string", "description": "Storage and sharing boundary agreed for this file." }
53
+ }
54
+ },
55
+ "target_association": {
56
+ "type": "object",
57
+ "additionalProperties": false,
58
+ "required": ["status", "build_id", "rationale"],
59
+ "properties": {
60
+ "status": { "enum": ["declared", "unbound", "unknown"] },
61
+ "build_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/buildId" }, { "type": "null" }] },
62
+ "rationale": { "type": "string" }
63
+ }
64
+ },
65
+ "limitations": { "type": "array", "items": { "type": "string" } },
66
+ "registered_at": { "$ref": "common.schema.json#/$defs/timestamp" }
67
+ }
68
+ }
@@ -0,0 +1,91 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://full-reverse.local/schemas/inventory.schema.json",
4
+ "title": "Full Reverse artifact inventory (inventory.json)",
5
+ "description": "Written only by the inventory specialist. Artifact-aware facts with evidence references and explicit unknowns. No fact may be present without evidence or a stated user/environment source.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema_version", "investigation_id", "created_at", "inputs", "artifacts", "unknowns"],
9
+ "properties": {
10
+ "schema_version": { "const": "full-reverse.inventory/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": ["evidence_index"],
17
+ "properties": {
18
+ "evidence_index": {
19
+ "oneOf": [{ "$ref": "common.schema.json#/$defs/fileDigest" }, { "type": "null" }],
20
+ "description": "Digest of evidence/index.json the inventory was derived from."
21
+ }
22
+ }
23
+ },
24
+ "artifacts": {
25
+ "type": "array",
26
+ "items": {
27
+ "type": "object",
28
+ "additionalProperties": false,
29
+ "required": ["build_id", "artifact_kind", "format", "architecture", "version", "components", "capabilities", "evidence", "unknowns"],
30
+ "properties": {
31
+ "build_id": { "$ref": "common.schema.json#/$defs/buildId" },
32
+ "artifact_kind": {
33
+ "enum": ["native-binary", "javascript-electron", "managed-assembly", "android-package", "package-or-installer", "web-capture", "recorded-evidence", "firmware", "wasm", "database", "other", "unknown"]
34
+ },
35
+ "format": { "type": ["string", "null"] },
36
+ "architecture": { "type": ["string", "null"] },
37
+ "version": { "type": ["string", "null"] },
38
+ "components": {
39
+ "type": "array",
40
+ "items": {
41
+ "type": "object",
42
+ "additionalProperties": false,
43
+ "required": ["component_id", "kind", "path", "sha256", "evidence"],
44
+ "properties": {
45
+ "component_id": { "type": "string", "pattern": "^cmp_[a-z0-9][a-z0-9_-]{0,62}$" },
46
+ "kind": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
47
+ "path": { "type": ["string", "null"] },
48
+ "sha256": { "oneOf": [{ "$ref": "common.schema.json#/$defs/sha256" }, { "type": "null" }] },
49
+ "description": { "type": "string" },
50
+ "evidence": { "type": "array", "minItems": 1, "items": { "$ref": "common.schema.json#/$defs/evidenceRef" } }
51
+ }
52
+ }
53
+ },
54
+ "capabilities": {
55
+ "type": "array",
56
+ "items": {
57
+ "type": "object",
58
+ "additionalProperties": false,
59
+ "required": ["capability", "status", "detail", "evidence"],
60
+ "properties": {
61
+ "capability": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
62
+ "status": { "enum": ["available", "unavailable", "unknown"] },
63
+ "detail": { "type": "string" },
64
+ "evidence": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidenceRef" } }
65
+ }
66
+ }
67
+ },
68
+ "evidence": {
69
+ "type": "array",
70
+ "items": { "$ref": "common.schema.json#/$defs/evidenceRef" },
71
+ "description": "Evidence supporting artifact-level facts (kind, format, architecture, version)."
72
+ },
73
+ "unknowns": { "type": "array", "items": { "$ref": "#/$defs/unknown" } }
74
+ }
75
+ }
76
+ },
77
+ "unknowns": { "type": "array", "items": { "$ref": "#/$defs/unknown" } }
78
+ },
79
+ "$defs": {
80
+ "unknown": {
81
+ "type": "object",
82
+ "additionalProperties": false,
83
+ "required": ["unknown_id", "text"],
84
+ "properties": {
85
+ "unknown_id": { "type": "string", "pattern": "^unk_[a-z0-9][a-z0-9_-]{0,62}$" },
86
+ "text": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
87
+ "question_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/questionId" } }
88
+ }
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,142 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://full-reverse.local/schemas/investigation.schema.json",
4
+ "title": "Full Reverse investigation state (investigation.json)",
5
+ "description": "Owned and written only by the entry skill. Records scope, builds, questions, authorization grants, steps/attempts and lifecycle checkpoints.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schema_version", "investigation_id", "created_at", "objective", "non_goals", "workspace",
10
+ "builds", "questions", "authorizations", "tools", "phase", "steps", "lifecycle"
11
+ ],
12
+ "properties": {
13
+ "schema_version": { "const": "full-reverse.investigation/1" },
14
+ "investigation_id": { "$ref": "common.schema.json#/$defs/investigationId" },
15
+ "created_at": { "$ref": "common.schema.json#/$defs/timestamp" },
16
+ "objective": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
17
+ "non_goals": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/nonEmptyString" } },
18
+ "workspace": {
19
+ "type": "object",
20
+ "additionalProperties": false,
21
+ "required": ["path", "allowed_output_paths"],
22
+ "properties": {
23
+ "path": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
24
+ "allowed_output_paths": {
25
+ "type": "array",
26
+ "items": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
27
+ "description": "Absolute paths (workspace included) where analyst-controlled outputs may be written."
28
+ }
29
+ }
30
+ },
31
+ "builds": {
32
+ "type": "array",
33
+ "items": { "$ref": "common.schema.json#/$defs/build" }
34
+ },
35
+ "questions": {
36
+ "type": "array",
37
+ "items": {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["question_id", "text", "status", "reason", "claim_ids", "feature"],
41
+ "properties": {
42
+ "question_id": { "$ref": "common.schema.json#/$defs/questionId" },
43
+ "text": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
44
+ "status": { "enum": ["pending", "answered", "partial", "unresolved"] },
45
+ "reason": { "type": ["string", "null"] },
46
+ "claim_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/claimId" } },
47
+ "feature": { "type": ["string", "null"], "pattern": "^[a-z0-9][a-z0-9-]{0,62}$" },
48
+ "build_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/buildId" } }
49
+ }
50
+ }
51
+ },
52
+ "authorizations": {
53
+ "type": "array",
54
+ "items": {
55
+ "type": "object",
56
+ "additionalProperties": false,
57
+ "required": [
58
+ "grant_id", "user_instruction", "conversation_ref", "recorded_at", "build_id",
59
+ "permitted_effects", "environment_boundary", "storage_boundary", "valid_scope",
60
+ "persistence", "reconfirmed_at"
61
+ ],
62
+ "properties": {
63
+ "grant_id": { "$ref": "common.schema.json#/$defs/grantId" },
64
+ "user_instruction": {
65
+ "$ref": "common.schema.json#/$defs/nonEmptyString",
66
+ "description": "The user's own words granting the effect. A persisted record is evidence of a grant, never authority to create one."
67
+ },
68
+ "conversation_ref": { "type": ["string", "null"] },
69
+ "recorded_at": { "$ref": "common.schema.json#/$defs/timestamp" },
70
+ "build_id": { "$ref": "common.schema.json#/$defs/buildId" },
71
+ "permitted_effects": {
72
+ "type": "array",
73
+ "uniqueItems": true,
74
+ "items": { "enum": ["launch", "attach", "instrument", "ui-action", "file-write", "network", "device", "storage", "mount"] }
75
+ },
76
+ "environment_boundary": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
77
+ "storage_boundary": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
78
+ "valid_scope": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
79
+ "persistence": { "enum": ["session", "persistent"] },
80
+ "reconfirmed_at": { "oneOf": [{ "$ref": "common.schema.json#/$defs/timestamp" }, { "type": "null" }] }
81
+ }
82
+ }
83
+ },
84
+ "tools": {
85
+ "type": "array",
86
+ "items": {
87
+ "type": "object",
88
+ "additionalProperties": false,
89
+ "required": ["name", "version", "observed_at"],
90
+ "properties": {
91
+ "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
92
+ "version": { "type": ["string", "null"] },
93
+ "observed_at": { "$ref": "common.schema.json#/$defs/timestamp" },
94
+ "note": { "type": "string" }
95
+ }
96
+ }
97
+ },
98
+ "phase": { "enum": ["scope", "inventory", "inspect", "observe", "model", "verify", "complete"] },
99
+ "steps": {
100
+ "type": "array",
101
+ "items": {
102
+ "type": "object",
103
+ "additionalProperties": false,
104
+ "required": [
105
+ "step_id", "specialist", "question_ids", "operation", "attempt", "supersedes_step_id", "status",
106
+ "build_id", "effects", "authorization_grant_id", "inputs", "outputs", "started_at", "finished_at", "note"
107
+ ],
108
+ "properties": {
109
+ "step_id": { "$ref": "common.schema.json#/$defs/stepId" },
110
+ "specialist": { "enum": ["entry", "inventory", "inspect", "observe", "model", "verify"] },
111
+ "question_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/questionId" } },
112
+ "operation": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
113
+ "attempt": { "type": "integer", "minimum": 1 },
114
+ "supersedes_step_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/stepId" }, { "type": "null" }] },
115
+ "status": { "enum": ["planned", "running", "completed", "interrupted", "failed", "superseded"] },
116
+ "build_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/buildId" }, { "type": "null" }] },
117
+ "effects": {
118
+ "type": "array",
119
+ "uniqueItems": true,
120
+ "items": { "enum": ["launch", "attach", "instrument", "ui-action", "file-write", "network", "device", "storage", "mount"] }
121
+ },
122
+ "authorization_grant_id": { "oneOf": [{ "$ref": "common.schema.json#/$defs/grantId" }, { "type": "null" }] },
123
+ "inputs": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/fileDigest" } },
124
+ "outputs": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/fileDigest" } },
125
+ "started_at": { "$ref": "common.schema.json#/$defs/timestamp" },
126
+ "finished_at": { "oneOf": [{ "$ref": "common.schema.json#/$defs/timestamp" }, { "type": "null" }] },
127
+ "note": { "type": "string" }
128
+ }
129
+ }
130
+ },
131
+ "lifecycle": {
132
+ "type": "object",
133
+ "additionalProperties": false,
134
+ "required": ["last_resumed_at", "review_sha256", "updated_at"],
135
+ "properties": {
136
+ "last_resumed_at": { "oneOf": [{ "$ref": "common.schema.json#/$defs/timestamp" }, { "type": "null" }] },
137
+ "review_sha256": { "oneOf": [{ "$ref": "common.schema.json#/$defs/sha256" }, { "type": "null" }] },
138
+ "updated_at": { "$ref": "common.schema.json#/$defs/timestamp" }
139
+ }
140
+ }
141
+ }
142
+ }