@tiphys/kernel 0.0.0 → 0.1.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.
- package/AGENTS.md +611 -0
- package/LICENSE +202 -0
- package/assurance-modes.yaml +278 -0
- package/checklists/clean-room.yaml +325 -0
- package/checklists/env-failure-diagnosis.yaml +68 -0
- package/checklists/flake-playbook.yaml +68 -0
- package/checklists/hazard-review.yaml +144 -0
- package/checklists/plan-review.yaml +103 -0
- package/dist/bin/tiphys.d.ts +2 -0
- package/dist/bin/tiphys.js +14 -0
- package/dist/src/brief.d.ts +32 -0
- package/dist/src/brief.js +59 -0
- package/dist/src/checklists.d.ts +169 -0
- package/dist/src/checklists.js +310 -0
- package/dist/src/checks.d.ts +828 -0
- package/dist/src/checks.js +3314 -0
- package/dist/src/cli.d.ts +9 -0
- package/dist/src/cli.js +57 -0
- package/dist/src/commands/brief.d.ts +92 -0
- package/dist/src/commands/brief.js +320 -0
- package/dist/src/commands/checklist.d.ts +42 -0
- package/dist/src/commands/checklist.js +168 -0
- package/dist/src/commands/doctor.d.ts +35 -0
- package/dist/src/commands/doctor.js +605 -0
- package/dist/src/commands/gates.d.ts +9 -0
- package/dist/src/commands/gates.js +360 -0
- package/dist/src/commands/init.d.ts +30 -0
- package/dist/src/commands/init.js +128 -0
- package/dist/src/commands/lock.d.ts +1 -0
- package/dist/src/commands/lock.js +229 -0
- package/dist/src/commands/mode.d.ts +40 -0
- package/dist/src/commands/mode.js +134 -0
- package/dist/src/commands/plan.d.ts +20 -0
- package/dist/src/commands/plan.js +105 -0
- package/dist/src/commands/pool.d.ts +1 -0
- package/dist/src/commands/pool.js +128 -0
- package/dist/src/commands/spawn.d.ts +1 -0
- package/dist/src/commands/spawn.js +146 -0
- package/dist/src/commands/status.d.ts +19 -0
- package/dist/src/commands/status.js +120 -0
- package/dist/src/commands/teardown.d.ts +1 -0
- package/dist/src/commands/teardown.js +79 -0
- package/dist/src/commands/tuition.d.ts +21 -0
- package/dist/src/commands/tuition.js +218 -0
- package/dist/src/commands/validate.d.ts +78 -0
- package/dist/src/commands/validate.js +360 -0
- package/dist/src/commands/watch.d.ts +1 -0
- package/dist/src/commands/watch.js +172 -0
- package/dist/src/exec/env.d.ts +128 -0
- package/dist/src/exec/env.js +190 -0
- package/dist/src/fleet.d.ts +51 -0
- package/dist/src/fleet.js +80 -0
- package/dist/src/gates/adapters/http-json.d.ts +5 -0
- package/dist/src/gates/adapters/http-json.js +283 -0
- package/dist/src/gates/adapters/migrations-command.d.ts +1 -0
- package/dist/src/gates/adapters/migrations-command.js +373 -0
- package/dist/src/gates/citations.d.ts +408 -0
- package/dist/src/gates/citations.js +1163 -0
- package/dist/src/gates/coverage.d.ts +284 -0
- package/dist/src/gates/coverage.js +701 -0
- package/dist/src/gates/credentials.d.ts +74 -0
- package/dist/src/gates/credentials.js +533 -0
- package/dist/src/gates/deploy.d.ts +1 -0
- package/dist/src/gates/deploy.js +33 -0
- package/dist/src/gates/manifest.d.ts +99 -0
- package/dist/src/gates/manifest.js +208 -0
- package/dist/src/gates/migrations.d.ts +1 -0
- package/dist/src/gates/migrations.js +36 -0
- package/dist/src/gates/pin.d.ts +114 -0
- package/dist/src/gates/pin.js +154 -0
- package/dist/src/gates/red-witness.d.ts +22 -0
- package/dist/src/gates/red-witness.js +390 -0
- package/dist/src/gates/release.d.ts +283 -0
- package/dist/src/gates/release.js +820 -0
- package/dist/src/gates/result.d.ts +116 -0
- package/dist/src/gates/result.js +91 -0
- package/dist/src/gates/run.d.ts +566 -0
- package/dist/src/gates/run.js +1536 -0
- package/dist/src/gates/schemas/citation-config.schema.json +59 -0
- package/dist/src/gates/schemas/coverage-config.schema.json +77 -0
- package/dist/src/gates/schemas/gate-manifest.schema.json +125 -0
- package/dist/src/gates/schemas/gate-result.schema.json +160 -0
- package/dist/src/gates/schemas/phase-declaration.schema.json +42 -0
- package/dist/src/gates/schemas/release-record.schema.json +119 -0
- package/dist/src/gates/schemas/verifier-config.schema.json +101 -0
- package/dist/src/gates/schemas/witness-spec.schema.json +110 -0
- package/dist/src/gates/scope.d.ts +131 -0
- package/dist/src/gates/scope.js +1018 -0
- package/dist/src/gates/suite.d.ts +217 -0
- package/dist/src/gates/suite.js +927 -0
- package/dist/src/gates/validate.d.ts +121 -0
- package/dist/src/gates/validate.js +414 -0
- package/dist/src/hooks.d.ts +32 -0
- package/dist/src/hooks.js +62 -0
- package/dist/src/liveness.d.ts +321 -0
- package/dist/src/liveness.js +396 -0
- package/dist/src/lock.d.ts +178 -0
- package/dist/src/lock.js +500 -0
- package/dist/src/modes.d.ts +149 -0
- package/dist/src/modes.js +258 -0
- package/dist/src/path-identity.d.ts +2 -0
- package/dist/src/path-identity.js +10 -0
- package/dist/src/plan.d.ts +73 -0
- package/dist/src/plan.js +153 -0
- package/dist/src/pool.d.ts +130 -0
- package/dist/src/pool.js +721 -0
- package/dist/src/roles.d.ts +430 -0
- package/dist/src/roles.js +734 -0
- package/dist/src/spawn.d.ts +177 -0
- package/dist/src/spawn.js +332 -0
- package/dist/src/status.d.ts +91 -0
- package/dist/src/status.js +119 -0
- package/dist/src/task.d.ts +264 -0
- package/dist/src/task.js +305 -0
- package/dist/src/teardown.d.ts +32 -0
- package/dist/src/teardown.js +314 -0
- package/dist/src/tuition.d.ts +159 -0
- package/dist/src/tuition.js +311 -0
- package/dist/src/validate.d.ts +230 -0
- package/dist/src/validate.js +732 -0
- package/dist/src/version.d.ts +3 -0
- package/dist/src/version.js +38 -0
- package/dist/src/watcher.d.ts +275 -0
- package/dist/src/watcher.js +859 -0
- package/dist/src/witness/run.d.ts +274 -0
- package/dist/src/witness/run.js +1327 -0
- package/dist/src/witness/spec.d.ts +102 -0
- package/dist/src/witness/spec.js +253 -0
- package/dist/tsconfig.src.tsbuildinfo +1 -0
- package/gate-registry.yaml +390 -0
- package/gates.manifest.json +195 -0
- package/package.json +57 -3
- package/role-model-config.yaml +88 -0
- package/roles/README.md +128 -0
- package/roles/_shared-dispatch-contract.md +87 -0
- package/roles/adversarial-plan-reviewer.md +80 -0
- package/roles/clean-room-reviewer.md +140 -0
- package/roles/implementer.md +460 -0
- package/roles/investigator.md +138 -0
- package/roles/plan-writer.md +95 -0
- package/schemas/README.md +81 -0
- package/schemas/assurance-modes.schema.json +264 -0
- package/schemas/charter.schema.json +166 -0
- package/schemas/checklist.schema.json +114 -0
- package/schemas/decision-record.schema.json +88 -0
- package/schemas/final-report.schema.json +90 -0
- package/schemas/finding.schema.json +106 -0
- package/schemas/gate-registry.schema.json +260 -0
- package/schemas/mechanism-index.schema.json +94 -0
- package/schemas/plan.schema.json +300 -0
- package/schemas/report.schema.json +579 -0
- package/schemas/role-brief.schema.json +105 -0
- package/schemas/role-model-config.schema.json +90 -0
- package/schemas/status-line.schema.json +40 -0
- package/schemas/tuition.schema.json +191 -0
- package/schemas/verdict.schema.json +289 -0
- package/schemas/work-history.schema.json +183 -0
- package/templates/charter.example.yaml +54 -0
- package/templates/decision-record.example.yaml +27 -0
- package/templates/final-report.example.yaml +80 -0
- package/templates/plan.example.yaml +87 -0
- package/templates/report.example.yaml +236 -0
- package/templates/warnings.md +74 -0
- package/templates/work-history.example.yaml +185 -0
- package/tuition/README.md +76 -0
- package/tuition/T-001.yaml +48 -0
- package/tuition/T-002.yaml +51 -0
- package/tuition/T-003.yaml +100 -0
- package/tuition/T-004.yaml +52 -0
- package/tuition/T-005.yaml +72 -0
- package/tuition/T-006.yaml +81 -0
- package/tuition/T-007.yaml +56 -0
- package/tuition/T-008.yaml +111 -0
- package/tuition/T-009.yaml +50 -0
- package/tuition/T-015.yaml +36 -0
- package/tuition/T-016.yaml +36 -0
- package/tuition/T-017.yaml +46 -0
- package/tuition/T-018.yaml +84 -0
- package/tuition/T-021.yaml +40 -0
- package/tuition/T-022.yaml +36 -0
- package/tuition/mechanism-index.yaml +256 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://tiphys.dev/schemas/checklist.schema.json",
|
|
4
|
+
"title": "Tiphys review checklist",
|
|
5
|
+
"$comment": "R-026b, R-027, R-028a, R-050b, R-053, R-054, R-055, R-056a, R-057b, R-059, R-066, R-093. Kernel plan M3, M3-P7 steps 1 and 5. A CHECKLIST IS A PROBE LIST WITH DECLARED ENTRY POINTS. THE HAZARD THIS DOCUMENT EXISTS AGAINST is the phase's own: a checklist whose probes are present, unique, resolvable and USELESS. This schema reaches four of the seven ways that happens and reaches none of the other three, which is stated here rather than left for a reader to assume. WHAT IT REACHES: a probe with no question, no scope or no evidence policy (required plus minLength); an `applies-to` token that is prose rather than a scope a resolver can group by (pattern); a framing with no entry point or that orders nothing (required plus minItems); a `verifies-gate` that is blank. WHAT IT CANNOT REACH, each with the instrument that does. (1) Whether a probe's TEXT is specific enough to need opening a file: that is a property of prose, it is criterion 3b's registered tests for the five probe sets the plan names, and for the rest it is risk 2 and the suggested-tier note. (2) Whether two probes share an `id`: `uniqueItems` compares WHOLE array items, so two probes differing in any other field are already unique to it; that is the Kind B check `checklist-probe-ids-unique`. (2a) THE SAME THING ONE ARRAY ALONG, missed until fix round 2 because the keyword limitation was recorded for probes and not generalised: two FRAMINGS sharing an id, which is the check `checklist-framing-ids-unique`. (3) Whether a `verifies-gate` names a gate that exists, or whether a probe named by the registry carries the back-reference at all: both are cross-document and are the Kind B check `gate-probes-resolve`, running in both directions.",
|
|
6
|
+
"description": "A review checklist: a list of probes a reviewer answers, plus the framings that decide which probe they answer first.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"required": ["kind", "id", "applies-to", "probes"],
|
|
10
|
+
"properties": {
|
|
11
|
+
"kind": {
|
|
12
|
+
"$comment": "R-016's discriminator, so `tiphys validate --type auto` resolves this document without being told, and M3R-001's rule that a type is registered with the validator in the same step that ships its schema is satisfied in both halves. A per-phase extra probe file (R-054, `checklist resolve --extra`) is ALSO a checklist document and carries this same kind, which is what makes an extra probe set independently validatable instead of a fragment only one command can read.",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"const": "checklist"
|
|
15
|
+
},
|
|
16
|
+
"id": {
|
|
17
|
+
"$comment": "The name `tiphys checklist resolve --checklist <id>` takes, and the basename of the shipped file. A TOKEN rather than free prose, because the resolver looks it up.",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1,
|
|
20
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
21
|
+
},
|
|
22
|
+
"applies-to": {
|
|
23
|
+
"$comment": "What kind of review this whole list is for, in one sentence. Prose, deliberately: this one is read by a human deciding which checklist to run and is never grouped on.",
|
|
24
|
+
"type": "string",
|
|
25
|
+
"minLength": 1,
|
|
26
|
+
"pattern": "\\S"
|
|
27
|
+
},
|
|
28
|
+
"probes": {
|
|
29
|
+
"$comment": "`uniqueItems` is here and it is NOT the id-uniqueness rule. It compares whole items, so it catches a probe pasted twice verbatim and nothing else. Two probes sharing an id and differing in their question are unique to this keyword and are exactly the dangerous instance, which is why criterion 1's rejection is the derived check and not this line.",
|
|
30
|
+
"type": "array",
|
|
31
|
+
"minItems": 1,
|
|
32
|
+
"uniqueItems": true,
|
|
33
|
+
"items": {
|
|
34
|
+
"$ref": "#/$defs/probe"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"framings": {
|
|
38
|
+
"$comment": "T-001's second data point (M3R-004): the M1-P4 dual review found different defects because the two reviewers were given different STARTING QUESTIONS, and T-001's own words are that the checklists should vary the entry point rather than only the reviewer. A framing is therefore data in the artifact rather than a sentence in a dispatch prompt. Optional, because `checklists/flake-playbook.yaml` and `checklists/env-failure-diagnosis.yaml` are single-entry-point procedures and inventing framings for them would be ceremony. `uniqueItems` is here and, exactly as on `probes` above, it is NOT the id-uniqueness rule: it compares whole items, so two framings sharing an id and differing in their entry point are unique to it and are the dangerous instance, since `resolveChecklist` looks a framing up by id and first match wins. That is the derived check `checklist-framing-ids-unique`, added in fix round 2.",
|
|
39
|
+
"type": "array",
|
|
40
|
+
"minItems": 1,
|
|
41
|
+
"uniqueItems": true,
|
|
42
|
+
"items": {
|
|
43
|
+
"$ref": "#/$defs/framing"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"$defs": {
|
|
48
|
+
"probe": {
|
|
49
|
+
"$comment": "One question, its scope, and whether an answer must cite something.",
|
|
50
|
+
"type": "object",
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"required": ["id", "probe", "applies-to", "evidence-required"],
|
|
53
|
+
"properties": {
|
|
54
|
+
"id": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"minLength": 1,
|
|
57
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
58
|
+
},
|
|
59
|
+
"probe": {
|
|
60
|
+
"$comment": "THE QUESTION. Prose, and the one field this schema can say least about: `minLength` stops it being empty and nothing here stops it being generic. That gap is the phase's whole hazard class and the instrument is criterion 3b.",
|
|
61
|
+
"type": "string",
|
|
62
|
+
"minLength": 1,
|
|
63
|
+
"pattern": "\\S"
|
|
64
|
+
},
|
|
65
|
+
"applies-to": {
|
|
66
|
+
"$comment": "THE SCOPE TOKEN, and it is a token rather than prose because the resolver GROUPS ON IT. A framing's `orders-probes` names scopes, so this field is what makes `--framing` reorder the list rather than decorate it. A probe whose scope does not apply is still answerable ('not applicable, no destructive command in the diff'), so this is a grouping key and never a filter that silently drops a probe.",
|
|
67
|
+
"type": "string",
|
|
68
|
+
"minLength": 1,
|
|
69
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
70
|
+
},
|
|
71
|
+
"evidence-required": {
|
|
72
|
+
"$comment": "R-054's second failure mode: an extra probe merged in without this field. A boolean rather than an optional flag, so a probe cannot be silently opinion-only. True means the answer must cite a path, a line, a captured command or an exit code.",
|
|
73
|
+
"type": "boolean"
|
|
74
|
+
},
|
|
75
|
+
"verifies-gate": {
|
|
76
|
+
"$comment": "NEW at revision 3, criterion 3c. The id of the `gate-registry.yaml` entry whose `verified-by: clean-room-checklist` names this probe. OPTIONAL because most probes verify no gate, and it is what makes the checklist-to-registry direction computable at all: without a back-reference there is nothing to resolve and an orphaned probe stays invisible by construction. That every registry-named probe MUST carry it is an `if`/`then` across two documents, which no keyword here reaches; it is enforced by `gate-probes-resolve`.",
|
|
77
|
+
"type": "string",
|
|
78
|
+
"minLength": 1,
|
|
79
|
+
"pattern": "\\S"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"framing": {
|
|
84
|
+
"$comment": "One declared entry point into the same probe list.",
|
|
85
|
+
"type": "object",
|
|
86
|
+
"additionalProperties": false,
|
|
87
|
+
"required": ["id", "entry-point", "orders-probes"],
|
|
88
|
+
"properties": {
|
|
89
|
+
"id": {
|
|
90
|
+
"type": "string",
|
|
91
|
+
"minLength": 1,
|
|
92
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
93
|
+
},
|
|
94
|
+
"entry-point": {
|
|
95
|
+
"$comment": "The starting question this framing hands the reviewer, printed at the head of the resolved list. T-001's two real examples are walking the acceptance criteria as a contract, and starting from where this can destroy something or claim a guarantee it does not have.",
|
|
96
|
+
"type": "string",
|
|
97
|
+
"minLength": 1,
|
|
98
|
+
"pattern": "\\S"
|
|
99
|
+
},
|
|
100
|
+
"orders-probes": {
|
|
101
|
+
"$comment": "The probe SCOPES, in the order this framing wants them, each naming an `applies-to` token. Probes in a named scope lead, scope by scope, and inside one scope the FILE ORDER decides; every probe in no named scope follows in file order. Ordering by scope rather than by probe id is what makes criterion 4d falsifiable: `CLAUDE.md` says the reviewer's FIRST check is item 3, and with a scope list the first resolved probe is the first `fix-round` probe IN THE FILE, so moving it later changes the answer. A framing that listed probe ids instead would pin the head no matter where the probe sat, which is the hazard class's 'ordering expressed as a comment rather than as position' wearing a schema's clothes.",
|
|
102
|
+
"type": "array",
|
|
103
|
+
"minItems": 1,
|
|
104
|
+
"uniqueItems": true,
|
|
105
|
+
"items": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"minLength": 1,
|
|
108
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://tiphys.dev/schemas/decision-record.schema.json",
|
|
4
|
+
"title": "Tiphys decision record",
|
|
5
|
+
"description": "Blueprint section 7's field list, plus the fields R-063 and R-090 need in order to be checkable rather than habitual. An OPEN QUESTION is a record with status open (D-7), so there is one register and never two.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"kind",
|
|
10
|
+
"id",
|
|
11
|
+
"project",
|
|
12
|
+
"task",
|
|
13
|
+
"question",
|
|
14
|
+
"options",
|
|
15
|
+
"reversibility",
|
|
16
|
+
"vetoable",
|
|
17
|
+
"revert-cost",
|
|
18
|
+
"status",
|
|
19
|
+
"decided",
|
|
20
|
+
"date"
|
|
21
|
+
],
|
|
22
|
+
"properties": {
|
|
23
|
+
"kind": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"const": "decision-record"
|
|
26
|
+
},
|
|
27
|
+
"id": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"pattern": "^DR-[0-9]{4}$"
|
|
30
|
+
},
|
|
31
|
+
"project": { "type": "string", "minLength": 1 },
|
|
32
|
+
"task": { "type": "string", "minLength": 1 },
|
|
33
|
+
"question": { "type": "string", "minLength": 1 },
|
|
34
|
+
"options": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"minItems": 1,
|
|
37
|
+
"items": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"additionalProperties": false,
|
|
40
|
+
"required": ["label", "consequence"],
|
|
41
|
+
"properties": {
|
|
42
|
+
"label": { "type": "string", "minLength": 1 },
|
|
43
|
+
"consequence": { "type": "string", "minLength": 1 }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"reversibility": {
|
|
48
|
+
"$comment": "R-063. Exactly three values, so the cost of being wrong is stated rather than implied.",
|
|
49
|
+
"type": "string",
|
|
50
|
+
"enum": ["reversible", "costly", "irreversible"]
|
|
51
|
+
},
|
|
52
|
+
"vetoable": {
|
|
53
|
+
"$comment": "R-090: a forced owner-adjacent call is decided, FLAGGED VETOABLE, and made trivially revertible. This field and revert-cost are what turn that sentence from a habit into a required field.",
|
|
54
|
+
"type": "boolean"
|
|
55
|
+
},
|
|
56
|
+
"revert-cost": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"minLength": 1
|
|
59
|
+
},
|
|
60
|
+
"status": {
|
|
61
|
+
"$comment": "D-7: an open question is a record with status open.",
|
|
62
|
+
"type": "string",
|
|
63
|
+
"enum": ["open", "deferred", "decided"]
|
|
64
|
+
},
|
|
65
|
+
"decided": {
|
|
66
|
+
"$comment": "The answer in the decider's own terms. Empty while the record is open or deferred; a record with status decided and an empty decided field is a record that claims an answer it does not carry, which is the Kind A pair the if/then below enforces.",
|
|
67
|
+
"type": "string"
|
|
68
|
+
},
|
|
69
|
+
"date": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
|
|
72
|
+
},
|
|
73
|
+
"evidence": {
|
|
74
|
+
"type": "array",
|
|
75
|
+
"items": { "type": "string", "minLength": 1 }
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"if": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"required": ["status"],
|
|
81
|
+
"properties": { "status": { "const": "decided" } }
|
|
82
|
+
},
|
|
83
|
+
"then": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"required": ["decided"],
|
|
86
|
+
"properties": { "decided": { "type": "string", "minLength": 1 } }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://tiphys.dev/schemas/final-report.schema.json",
|
|
4
|
+
"title": "Tiphys final report",
|
|
5
|
+
"$comment": "R-089a. Kernel plan M3, M3-P4 step 2. THE FINAL REPORT IS A PROJECTION, NOT A SUMMARY, and that property is load-bearing beyond this phase. Every field here is DERIVED from records that already exist (findings, verdicts, decisions, work histories), which is the same relation M3-P8's mechanism index has to the tuition feed. That relation is what makes a dense read layer possible on top of a verbose archive: the projections are consumed at every dispatch and must stay dense, while the raw entries are read only in dispute. M3 BUILDS NO COMPACTOR AND THIS SCHEMA PROPOSES NONE; what it does is make the distinction structural, so a later compaction is a question about which layer a file is in rather than a judgement about which files look like filler. SILENCE AND EMPTINESS ARE DISTINGUISHABLE: each of the four enumerable sections is a two-branch oneOf, so `none: true` carries NO entries key at all and `none: false` carries at least one entry. That closes BOTH directions of the relation rather than one: an empty list without a marker is a rejection, and a `none: true` marker sitting on top of real entries is also a rejection. THE PARITY BETWEEN `inputs[]` AND `input-findings[]` IS NOT HERE: cross-array completeness is not a keyword property (M3R-002), so it is the derived check `final-report-finding-parity` in src/checks.ts, and it is checked a second time by the M2-P6 coverage checker's finding-to-outcome parity mode because the artifact should be self-checking AND the independent checker is the one the pipeline runs.",
|
|
6
|
+
"description": "One document per delivery. Every input finding mapped to an outcome, plus the decisions owed, the owner verifications outstanding, the infrastructure left behind, and anything done out of band.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"required": [
|
|
10
|
+
"kind",
|
|
11
|
+
"subject",
|
|
12
|
+
"inputs",
|
|
13
|
+
"input-findings",
|
|
14
|
+
"decisions-owed",
|
|
15
|
+
"owner-verification",
|
|
16
|
+
"infrastructure-left",
|
|
17
|
+
"out-of-band"
|
|
18
|
+
],
|
|
19
|
+
"properties": {
|
|
20
|
+
"kind": {
|
|
21
|
+
"description": "The artifact type, so `tiphys validate --type auto` resolves this document without being told.",
|
|
22
|
+
"type": "string",
|
|
23
|
+
"const": "final-report"
|
|
24
|
+
},
|
|
25
|
+
"subject": {
|
|
26
|
+
"description": "What this report is the final report OF.",
|
|
27
|
+
"type": "string",
|
|
28
|
+
"minLength": 1,
|
|
29
|
+
"pattern": "\\S"
|
|
30
|
+
},
|
|
31
|
+
"inputs": {
|
|
32
|
+
"$comment": "The finding ids this delivery took in. Kept SEPARATE from `input-findings[]` on purpose: a table that is its own inventory cannot be incomplete, which is the circularity scripts/check-clause-map.mjs's header names one level up. The derived check compares the two.",
|
|
33
|
+
"type": "array",
|
|
34
|
+
"items": { "type": "string", "minLength": 1, "pattern": "\\S" },
|
|
35
|
+
"uniqueItems": true
|
|
36
|
+
},
|
|
37
|
+
"input-findings": {
|
|
38
|
+
"$comment": "R-089a's table. Every id in `inputs[]` lands in exactly one row here with a non-empty outcome.",
|
|
39
|
+
"type": "array",
|
|
40
|
+
"items": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"required": ["id", "outcome"],
|
|
44
|
+
"properties": {
|
|
45
|
+
"id": { "type": "string", "minLength": 1, "pattern": "\\S" },
|
|
46
|
+
"outcome": { "type": "string", "minLength": 1, "pattern": "\\S" }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"decisions-owed": { "$ref": "#/$defs/enumerableSection" },
|
|
51
|
+
"owner-verification": { "$ref": "#/$defs/enumerableSection" },
|
|
52
|
+
"infrastructure-left": { "$ref": "#/$defs/enumerableSection" },
|
|
53
|
+
"out-of-band": { "$ref": "#/$defs/enumerableSection" }
|
|
54
|
+
},
|
|
55
|
+
"$defs": {
|
|
56
|
+
"enumerableSection": {
|
|
57
|
+
"$comment": "ALLOWED TO BE EMPTY ONLY WITH AN EXPLICIT MARKER, so silence and emptiness are distinguishable (plan step 2). The two branches are exclusive by construction: branch 1 permits `none: true` AND NOTHING ELSE, so a marker sitting on top of real entries is a rejection; branch 2 requires `none: false` with at least one entry, so an empty list hiding behind a false marker is a rejection too. Both directions, rather than the one the requirement's letter names. RESIDUE, ADDED IN M3-P4 FIX ROUND 2 BY THE CR-002 ENUMERATION: this is the same mechanism CR-002 named one document over. The branch is picked by A VALUE THE AUTHOR WRITES, and branch 1 owes NOTHING, so an author with three real decisions owed writes `none: true` and the schema is satisfied. What the two branches close is INTERNAL CONTRADICTION (a marker over entries, entries with no marker); what neither reaches is a marker over a truth outside the document. Nothing in this schema could reach it, because there is no second record here to compare against; the derived check `final-report-finding-parity` is what that comparison looks like where a second record exists, and `decisions-owed` has none.",
|
|
58
|
+
"oneOf": [
|
|
59
|
+
{
|
|
60
|
+
"type": "object",
|
|
61
|
+
"additionalProperties": false,
|
|
62
|
+
"required": ["none"],
|
|
63
|
+
"properties": { "none": { "type": "boolean", "const": true } }
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"required": ["none", "entries"],
|
|
69
|
+
"properties": {
|
|
70
|
+
"none": { "type": "boolean", "const": false },
|
|
71
|
+
"entries": {
|
|
72
|
+
"type": "array",
|
|
73
|
+
"minItems": 1,
|
|
74
|
+
"items": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": false,
|
|
77
|
+
"required": ["statement"],
|
|
78
|
+
"properties": {
|
|
79
|
+
"id": { "type": "string", "minLength": 1, "pattern": "\\S" },
|
|
80
|
+
"statement": { "type": "string", "minLength": 1, "pattern": "\\S" },
|
|
81
|
+
"owner": { "type": "string", "minLength": 1, "pattern": "\\S" }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://tiphys.dev/schemas/finding.schema.json",
|
|
4
|
+
"title": "Tiphys finding set",
|
|
5
|
+
"$comment": "R-029. Kernel plan M3, M3-P5 step 5. THE OUTPUT OF A REVIEW: a verdict, the model family that produced it, and a severity-ranked list of findings each of which names the plan edit it demands. THE HAZARD THIS DOCUMENT EXISTS AGAINST is the one the phase's hazard-class table names: a schema that admits an EMPTY review as a thorough one. A review that found nothing and a review that looked at nothing produce the same JSON unless the empty case is made to say so, and `no-findings-statement` plus the `oneOf` below is what makes them different documents. WHAT THIS SCHEMA CANNOT DO. (1) It cannot tell a real `concrete-edit` from a restatement of the finding; that is M3-P7's probe territory, and what is bought here is that the field cannot be absent or blank. (2) It cannot tell a real `produced-by` from a guess; T-001's ask was that the family be RECORDED, and recorded is what `required` buys. (3) It cannot rank severities: `enum` is an unordered set and the rank is stated in this comment, low < medium < high < critical, the same four names schemas/plan.schema.json uses so the two documents do not carry two vocabularies. (4) It cannot see whether the same finding id appears twice; comparing array elements to each other is Kind B and this phase adds no Kind B row (criterion 5).",
|
|
6
|
+
"description": "A finding set: the artifact an adversarial plan review or a clean-room review outputs.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"required": ["kind", "verdict", "produced-by", "findings"],
|
|
10
|
+
"properties": {
|
|
11
|
+
"kind": {
|
|
12
|
+
"$comment": "R-016's discriminator, so `tiphys validate --type auto` resolves this document without being told, and M3R-001's rule that a type is registered with the validator in the same step that ships its schema is satisfied in both halves rather than one. A finding set is a YAML or JSON document, so unlike a role brief it CAN carry a kind.",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"const": "finding"
|
|
15
|
+
},
|
|
16
|
+
"verdict": {
|
|
17
|
+
"$comment": "R-029's `verdict`, required. A NON-EMPTY STRING rather than an enum, deliberately: M3-P7 ships the verdict contract and its closed vocabulary, and inventing a second one here would be the two-vocabularies failure this file's kind field exists to avoid. `pattern: \\S` because `required` alone is satisfied by the empty string.",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1,
|
|
20
|
+
"pattern": "\\S"
|
|
21
|
+
},
|
|
22
|
+
"produced-by": {
|
|
23
|
+
"$comment": "T-001's second ask, recorded in delivery/tuition/T-001-cross-model-review-catches.md: record in the review header which family produced it. DR-0012 condition 1 then makes the two clean-room reviews of one head differ in this field, and that comparison is between two DOCUMENTS and is therefore not reachable from inside either of them. What is reachable is that the field cannot be absent, which is what this is.",
|
|
24
|
+
"type": "string",
|
|
25
|
+
"minLength": 1,
|
|
26
|
+
"pattern": "\\S"
|
|
27
|
+
},
|
|
28
|
+
"findings": {
|
|
29
|
+
"type": "array",
|
|
30
|
+
"items": {
|
|
31
|
+
"$ref": "#/$defs/finding"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"no-findings-statement": {
|
|
35
|
+
"$comment": "The empty review's own sentence: what was looked at, and why nothing was found. Required exactly when `findings` is empty, by the `oneOf` below.",
|
|
36
|
+
"type": "string",
|
|
37
|
+
"minLength": 1,
|
|
38
|
+
"pattern": "\\S"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"oneOf": [
|
|
42
|
+
{
|
|
43
|
+
"$comment": "Branch A: the set carries at least one finding. `type: array` is RESTATED here and that is not redundancy: measured against ajv 8.20.0 under this validator's `strict: true`, a `minItems` inside a subschema whose type is declared only at the outer level is refused with `schema uses keyword minItems without declaring type array`.",
|
|
44
|
+
"properties": {
|
|
45
|
+
"findings": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"minItems": 1
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"$comment": "Branch B: the set carries no finding and therefore must say what was looked at. `no-findings-statement` is RESTATED in a sibling `properties` here and that is not redundancy either: measured against the same engine, a `required` naming a property not declared in `properties` at the same level fails COMPILATION under strictRequired with `strict mode: required property \"no-findings-statement\" is not defined`. WHY `oneOf` AND NOT THE `if`/`then` THE PLAN'S PARENTHETICAL NAMES. The obligation is `findings` EMPTY implies a sibling required, so the `if` would have to match emptiness. The closed authoring vocabulary (schemas/README.md) has no `not` and no `maxItems`; `minItems: 1` and `contains` both match the NON-empty case, which is the wrong polarity, and `then` cannot remove an obligation. `oneOf` is in the vocabulary and does express it. The declared deviation and its captured probe output are in delivery/work-history/m3-p5.md. ONE CONSEQUENCE BEYOND WHAT CRITERION 5(b) ASKED FOR, recorded rather than discovered: a set carrying BOTH findings and a no-findings statement matches both branches and is therefore invalid too. That is the same both-directions property M3-P4's report contract reaches with a derived check.",
|
|
53
|
+
"required": ["no-findings-statement"],
|
|
54
|
+
"properties": {
|
|
55
|
+
"no-findings-statement": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"minLength": 1,
|
|
58
|
+
"pattern": "\\S"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"$defs": {
|
|
64
|
+
"finding": {
|
|
65
|
+
"$comment": "R-029's severity-ranked findings with concrete plan edits.",
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"required": ["id", "severity", "evidence", "concrete-edit"],
|
|
69
|
+
"properties": {
|
|
70
|
+
"id": {
|
|
71
|
+
"$comment": "The stable id the arbitration and the fix round cite. The identifier schemes are CLAUDE.md's; this schema does not pick one, because CR-nnn, PR-nnn and EXT-F-nn are all real and all cited.",
|
|
72
|
+
"type": "string",
|
|
73
|
+
"minLength": 1,
|
|
74
|
+
"pattern": "\\S"
|
|
75
|
+
},
|
|
76
|
+
"severity": {
|
|
77
|
+
"$comment": "Ranked low < medium < high < critical. Same four names as schemas/plan.schema.json's phase severity.",
|
|
78
|
+
"type": "string",
|
|
79
|
+
"enum": ["low", "medium", "high", "critical"]
|
|
80
|
+
},
|
|
81
|
+
"evidence": {
|
|
82
|
+
"$comment": "Evidence beats assertion: exit codes, counts, file paths with line numbers, captured output, URLs. `minItems: 1` is the whole point, because a finding with no evidence is an opinion and this repository treats an agent's claim with no verifiable artifact behind it as unknown.",
|
|
83
|
+
"type": "array",
|
|
84
|
+
"minItems": 1,
|
|
85
|
+
"items": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"minLength": 1,
|
|
88
|
+
"pattern": "\\S"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"concrete-edit": {
|
|
92
|
+
"$comment": "R-029's `concrete plan edits`. The edit the finding DEMANDS, not a description of the problem. Required on EVERY finding regardless of severity, which is strictly stronger than criterion 5(a)'s dangerous instance (a `severity: high` finding with no `concrete-edit`) and is stronger on purpose: a low finding with no proposed edit is a remark, and a review made of remarks is the empty review with extra steps.",
|
|
93
|
+
"type": "string",
|
|
94
|
+
"minLength": 1,
|
|
95
|
+
"pattern": "\\S"
|
|
96
|
+
},
|
|
97
|
+
"analysis": {
|
|
98
|
+
"$comment": "Section 1.5's finding-set row: what is not enumerable is the ARGUMENT behind one finding, which is why it lives inside a field rather than becoming structure. Optional, and non-empty when present.",
|
|
99
|
+
"type": "string",
|
|
100
|
+
"minLength": 1,
|
|
101
|
+
"pattern": "\\S"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|