@tiphys/kernel 0.1.0 → 0.2.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 +56 -4
- package/assurance-modes.yaml +23 -2
- package/dist/bin/tiphys.js +86 -8
- package/dist/src/adapters/load.d.ts +202 -0
- package/dist/src/adapters/load.js +440 -0
- package/dist/src/brief.js +27 -20
- package/dist/src/checks.d.ts +720 -9
- package/dist/src/checks.js +1874 -163
- package/dist/src/cli.js +11 -0
- package/dist/src/commands/brief.js +27 -4
- package/dist/src/commands/cutover.d.ts +35 -0
- package/dist/src/commands/cutover.js +448 -0
- package/dist/src/commands/doctor.d.ts +229 -0
- package/dist/src/commands/doctor.js +968 -27
- package/dist/src/commands/init.d.ts +3 -3
- package/dist/src/commands/init.js +57 -8
- package/dist/src/commands/lock.d.ts +33 -0
- package/dist/src/commands/lock.js +117 -6
- package/dist/src/commands/next.d.ts +130 -0
- package/dist/src/commands/next.js +597 -0
- package/dist/src/commands/pool.js +12 -1
- package/dist/src/commands/resume.d.ts +1 -0
- package/dist/src/commands/resume.js +88 -0
- package/dist/src/commands/spawn.js +51 -2
- package/dist/src/commands/status.d.ts +6 -4
- package/dist/src/commands/status.js +6 -4
- package/dist/src/commands/sync.d.ts +47 -0
- package/dist/src/commands/sync.js +341 -0
- package/dist/src/commands/teardown.js +10 -2
- package/dist/src/commands/validate.js +70 -0
- package/dist/src/cutover.d.ts +584 -0
- package/dist/src/cutover.js +1444 -0
- package/dist/src/exclusion.d.ts +389 -0
- package/dist/src/exclusion.js +843 -0
- package/dist/src/exec/env.d.ts +152 -2
- package/dist/src/exec/env.js +146 -2
- package/dist/src/fleet.d.ts +172 -0
- package/dist/src/fleet.js +219 -1
- package/dist/src/gates/citations.js +7 -1
- package/dist/src/gates/coverage.d.ts +113 -22
- package/dist/src/gates/coverage.js +166 -31
- package/dist/src/gates/credentials.d.ts +159 -0
- package/dist/src/gates/credentials.js +221 -2
- package/dist/src/gates/gate-classes.d.ts +56 -0
- package/dist/src/gates/gate-classes.js +633 -0
- package/dist/src/gates/merge-preconditions.d.ts +319 -0
- package/dist/src/gates/merge-preconditions.js +932 -0
- package/dist/src/gates/red-witness.js +105 -13
- package/dist/src/gates/run.d.ts +49 -1
- package/dist/src/gates/run.js +83 -5
- package/dist/src/gates/schemas/phase-declaration.schema.json +45 -0
- package/dist/src/gates/suite.js +48 -7
- package/dist/src/hooks.d.ts +55 -3
- package/dist/src/hooks.js +69 -6
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.js +30 -0
- package/dist/src/lock.d.ts +82 -4
- package/dist/src/lock.js +314 -22
- package/dist/src/model-resolution.d.ts +159 -0
- package/dist/src/model-resolution.js +307 -0
- package/dist/src/path-identity.d.ts +32 -0
- package/dist/src/path-identity.js +38 -0
- package/dist/src/pool.d.ts +197 -1
- package/dist/src/pool.js +289 -22
- package/dist/src/roles.d.ts +31 -0
- package/dist/src/roles.js +42 -0
- package/dist/src/spawn.d.ts +307 -2
- package/dist/src/spawn.js +690 -19
- package/dist/src/status.d.ts +27 -2
- package/dist/src/status.js +34 -5
- package/dist/src/task.d.ts +295 -55
- package/dist/src/task.js +125 -123
- package/dist/src/teardown.d.ts +7 -0
- package/dist/src/teardown.js +120 -12
- package/dist/src/validate.d.ts +44 -11
- package/dist/src/validate.js +44 -34
- package/dist/src/watcher.js +1 -11
- package/dist/src/witness/run.d.ts +32 -7
- package/dist/src/witness/run.js +76 -30
- package/dist/src/witness/spec.d.ts +168 -0
- package/dist/src/witness/spec.js +240 -18
- package/dist/tsconfig.src.tsbuildinfo +1 -1
- package/gate-registry.yaml +136 -0
- package/gates.manifest.json +63 -1
- package/package.json +18 -3
- package/roles/implementer.md +3 -0
- package/schemas/README.md +1 -0
- package/schemas/assurance-modes.schema.json +1 -1
- package/schemas/charter.schema.json +19 -0
- package/schemas/cutover-state.schema.json +64 -0
- package/schemas/executor-record.schema.json +36 -0
- package/schemas/model-resolution.schema.json +362 -0
- package/schemas/verdict.schema.json +9 -3
- package/schemas/write-bypass.schema.json +69 -0
package/gate-registry.yaml
CHANGED
|
@@ -181,6 +181,7 @@ gates:
|
|
|
181
181
|
paths:
|
|
182
182
|
- src/
|
|
183
183
|
- bin/
|
|
184
|
+
- plugin/
|
|
184
185
|
|
|
185
186
|
# NEW IN M3-P2, entry one of three.
|
|
186
187
|
- id: agent-rules-drift
|
|
@@ -281,12 +282,31 @@ gates:
|
|
|
281
282
|
question is whether any verdict DOCUMENT exists under `delivery/review/`
|
|
282
283
|
and not whether that directory does; this repository has the directory and
|
|
283
284
|
has never had a verdict document in it.
|
|
285
|
+
THE COMMIT UNDER AUDIT IS A PARAMETER, AND ITS ABSENCE WAS THE DR-0047
|
|
286
|
+
SWEEP'S ONE HIGH FINDING (CR-VS-001). Without it the check grouped by the
|
|
287
|
+
head THE VERDICT DOCUMENTS THEMSELVES DECLARE, and nothing compared that
|
|
288
|
+
to the commit the gate was running against or established that it named a
|
|
289
|
+
commit at all. Reproduced: two decorrelated APPROVE verdicts naming
|
|
290
|
+
`deadbeefdeadbeefdeadbeefdeadbeefdeadbeef`, a sha `git cat-file -t`
|
|
291
|
+
reports as not an object, gave `check-dual-review: green`, 2 units, exit
|
|
292
|
+
0, in a repository whose HEAD was a real commit and carried a further
|
|
293
|
+
commit of work no verdict mentioned. So ONE committed approving pair
|
|
294
|
+
turned this gate green for that phase at every later head, indefinitely.
|
|
295
|
+
The runner already had the mechanism: `scope` has declared
|
|
296
|
+
`parameters: [base, head]` since M2 and the runner appends the flags to
|
|
297
|
+
the gate command. This entry simply never declared it. With `--head` the
|
|
298
|
+
audited commit comes from the RUN and the declared head comes from the
|
|
299
|
+
EVIDENCE, and the second is measured against the first instead of
|
|
300
|
+
replacing it. With no `--head` the script falls back to the commit the
|
|
301
|
+
context's own HEAD resolves to, which is what keeps the direct workflow
|
|
302
|
+
step in `.github/workflows/gates.yml` correct.
|
|
284
303
|
command: [node, scripts/check-dual-review.mjs, .]
|
|
285
304
|
unitLabel: review verdicts examined for decorrelation
|
|
286
305
|
applicability: conditional
|
|
287
306
|
verified-by: script
|
|
288
307
|
modes: [full, direct-pr]
|
|
289
308
|
events: [pull_request]
|
|
309
|
+
parameters: [head]
|
|
290
310
|
precondition:
|
|
291
311
|
id: dual-review-verdicts-present
|
|
292
312
|
kind: command-exit-zero
|
|
@@ -331,6 +351,122 @@ gates:
|
|
|
331
351
|
modes: [full, direct-pr, local-only]
|
|
332
352
|
events: [pull_request, push]
|
|
333
353
|
|
|
354
|
+
# NEW IN M4-P14, entry one of two (R-041, DR-0028, DR-0029, M4-P13).
|
|
355
|
+
- id: typecheck
|
|
356
|
+
$comment: >-
|
|
357
|
+
R-041, retargeted by M4-P13 under DR-0028. The kernel ships the gate
|
|
358
|
+
CLASS and no command; the project ships the command. This repository is
|
|
359
|
+
the project, so this is the kernel dogfooding the extension point rather
|
|
360
|
+
than being exempt from it (DR-0029: "the kernel becomes just another
|
|
361
|
+
project under the scheme, with its own registry"). The subject is the one
|
|
362
|
+
M4 has, package.json's build script, which CLAUDE.md already calls the
|
|
363
|
+
type gate. WHY IT IS NOT THE SAME THING AS THE `build` PREFLIGHT STEP:
|
|
364
|
+
preflight is an ordered local command with no record, no units and no
|
|
365
|
+
vacuity protection, so nothing downstream can tell a build that checked
|
|
366
|
+
the whole project from one that checked nothing. This entry produces a
|
|
367
|
+
GateResult whose `units` is the count of distinct paths `tsc --listFiles`
|
|
368
|
+
PRINTED, so a compiler that read no file is error rather than green.
|
|
369
|
+
WHY `--force` IS IN THE COMMAND: without it `tsc -b` is incremental and
|
|
370
|
+
the printed file list depends on the state of `dist/`, which would make
|
|
371
|
+
the unit count a property of the runner's working directory instead of
|
|
372
|
+
the code. `events: [pull_request]` alone, and it is derived rather than
|
|
373
|
+
assigned: `scripts/m2-exit-test.sh` declares the push arm's gate set once
|
|
374
|
+
in MAIN_ONLY_GATES and this id is not in it, so the push arm cannot run
|
|
375
|
+
it and test/gate-registry.test.ts asserts `events` against that harness.
|
|
376
|
+
command: [node, src/gates/gate-classes.ts, typecheck, --project, tsconfig.src.json, --project, tsconfig.test.json, --project, plugin/tsconfig.json]
|
|
377
|
+
unitLabel: source files type-checked
|
|
378
|
+
applicability: required
|
|
379
|
+
verified-by: script
|
|
380
|
+
modes: [full, direct-pr, local-only]
|
|
381
|
+
events: [pull_request]
|
|
382
|
+
|
|
383
|
+
# NEW IN M4-P14, entry two of two (DR-0029 part 2a, M4-P13).
|
|
384
|
+
- id: gate-classes
|
|
385
|
+
$comment: >-
|
|
386
|
+
DR-0029 part 2a made executable. A PHASE declares at least one gate in
|
|
387
|
+
each required class (`correctness`, `scope`, `review`), or declares an
|
|
388
|
+
escape that is DATA: `not-applicable` WITH a recorded reason, or
|
|
389
|
+
`not-yet-establishable` NAMING the phase that will establish it. The
|
|
390
|
+
requirement attaches to the phase and not to the project, because "this
|
|
391
|
+
project must have a correctness gate" is unsatisfiable on day zero while
|
|
392
|
+
"this phase either asserts correctness or declares when it will" is
|
|
393
|
+
satisfiable from the first commit. The property protected, in DR-0029's
|
|
394
|
+
words: you can start from nothing; you can never SILENTLY have nothing.
|
|
395
|
+
THE ESCAPES ARE PRINTED ON THE GREEN ARM, not merely permitted, which is
|
|
396
|
+
the same disclosure trade src/gates/scope.ts makes for a declaration
|
|
397
|
+
addition under M3-P11 change B: a reviewer who does not read the printed
|
|
398
|
+
line gets no protection from it. The PRECONDITION is branch-matches, the
|
|
399
|
+
same one `scope` carries and for the same reason: a phase declaration is
|
|
400
|
+
selected by phase id, and a non-phase branch has none, so the gate
|
|
401
|
+
reports not-applicable with an evaluated precondition rather than a
|
|
402
|
+
vacuous green (SC-011, M2-C-3). `events: [pull_request]` alone because
|
|
403
|
+
the push arm of scripts/m2-exit-test.sh passes no `--phase` at all, so
|
|
404
|
+
there is no declaration for it to select.
|
|
405
|
+
command: [node, src/gates/gate-classes.ts, gate-classes, --declarations, delivery/plan/phase-declarations, --registry, gate-registry.yaml]
|
|
406
|
+
unitLabel: declared gate classes checked
|
|
407
|
+
applicability: required
|
|
408
|
+
verified-by: script
|
|
409
|
+
modes: [full, direct-pr]
|
|
410
|
+
events: [pull_request]
|
|
411
|
+
parameters: [phase]
|
|
412
|
+
precondition:
|
|
413
|
+
id: gate-classes-branch-is-a-phase-branch
|
|
414
|
+
kind: branch-matches
|
|
415
|
+
pattern: claude/m[0-9]+-p[0-9]+-.*
|
|
416
|
+
|
|
417
|
+
# NEW IN M4-P12 (DR-0012, DR-0036, T-009, R-064, R-065a).
|
|
418
|
+
- id: merge-preconditions
|
|
419
|
+
$comment: >-
|
|
420
|
+
M4-P12. The artifact DR-0012's delegated grant has never had: one record
|
|
421
|
+
per condition, each carrying the HEAD SHA it was evaluated against, so
|
|
422
|
+
that "the six conditions held" stops being a sentence somebody wrote and
|
|
423
|
+
becomes a thing a reader can check. It is a PRECONDITION READER and not a
|
|
424
|
+
merge command: M4-D-09 puts the merge capability in the plugin at cutover
|
|
425
|
+
and DR-0036 keeps merge authority with the current process for the whole
|
|
426
|
+
of M4, so the orchestrator reads this record before merging, by hand.
|
|
427
|
+
CONDITIONS 1 AND 2 ARE COMPOSED, NOT REIMPLEMENTED. M4-P10 shipped
|
|
428
|
+
`dual-review-decorrelation` and `verdict-pair-approves` as derived checks
|
|
429
|
+
in src/checks.ts; this gate is a second caller of the same exported
|
|
430
|
+
primitives and runs those checks BY ID, so deregistering either one is
|
|
431
|
+
visible here as an `error` rather than absorbed as a pass.
|
|
432
|
+
`applicability: conditional`, AND THE PRECONDITION IS ANSWERED IN TWO
|
|
433
|
+
PLACES BECAUSE IT IS TWO QUESTIONS. The declared `command-exit-zero` block
|
|
434
|
+
is the SAME probe check-dual-review declares, and it answers the question
|
|
435
|
+
a registry precondition can answer: does this project have any committed
|
|
436
|
+
review verdict at all. The narrower question, whether a verdict names THIS
|
|
437
|
+
head, needs the run's `--head`, and a precondition command is spawned
|
|
438
|
+
without it (src/gates/run.ts:1524 appends the parameter flags to the GATE
|
|
439
|
+
command, not to the precondition's). So the gate answers that half itself
|
|
440
|
+
and emits its own PreconditionRecord with `met: false`, which is SC-011's
|
|
441
|
+
requirement that not-applicable ASSERT an evaluated precondition rather
|
|
442
|
+
than stand for silence. Both arms are not-applicable and each names which
|
|
443
|
+
question was unmet, so a reader is never told only that the gate did not
|
|
444
|
+
run.
|
|
445
|
+
`events: [pull_request]` ALONE, and it is derived rather than assigned:
|
|
446
|
+
scripts/m2-exit-test.sh declares the push arm's gate set once in
|
|
447
|
+
MAIN_ONLY_GATES and this id is not in it, so the push arm cannot run it,
|
|
448
|
+
and test/gate-registry.test.ts asserts `events` against that harness
|
|
449
|
+
rather than against a wish. It is ALSO in gates.manifest.json, because CI
|
|
450
|
+
invokes the runner with `--manifest`: a gate declared only here is
|
|
451
|
+
declared and never executed, which is a gate that cannot go red.
|
|
452
|
+
THE API IS PROBED, NEVER ASSUMED. CLAUDE.md standing warning 6 records
|
|
453
|
+
REST reachability here measured both ways on different days with the
|
|
454
|
+
cause unestablished, so the gate probes first and reports `error` with
|
|
455
|
+
units 0 when it cannot reach the API. Never `not-applicable`, never green:
|
|
456
|
+
M2-C-3, and the hazard this whole entry exists against is a merge
|
|
457
|
+
precondition check that is green because it could not look.
|
|
458
|
+
command: [node, src/gates/merge-preconditions.ts]
|
|
459
|
+
unitLabel: merge preconditions evaluated
|
|
460
|
+
applicability: conditional
|
|
461
|
+
verified-by: script
|
|
462
|
+
modes: [full, direct-pr]
|
|
463
|
+
events: [pull_request]
|
|
464
|
+
parameters: [head, phase]
|
|
465
|
+
precondition:
|
|
466
|
+
id: merge-preconditions-verdicts-present
|
|
467
|
+
kind: command-exit-zero
|
|
468
|
+
command: [node, scripts/check-dual-review.mjs, --precondition, .]
|
|
469
|
+
|
|
334
470
|
# NEW IN M3-P2, entry two of three (R-043, D-11).
|
|
335
471
|
- id: unit-tests-for-changed-service-methods
|
|
336
472
|
$comment: >-
|
package/gates.manifest.json
CHANGED
|
@@ -171,7 +171,8 @@
|
|
|
171
171
|
"kind": "diff-touches",
|
|
172
172
|
"paths": [
|
|
173
173
|
"src/",
|
|
174
|
-
"bin/"
|
|
174
|
+
"bin/",
|
|
175
|
+
"plugin/"
|
|
175
176
|
]
|
|
176
177
|
}
|
|
177
178
|
},
|
|
@@ -184,6 +185,67 @@
|
|
|
184
185
|
],
|
|
185
186
|
"unitLabel": "generated brief gate rows compared",
|
|
186
187
|
"applicability": "required"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "typecheck",
|
|
191
|
+
"command": [
|
|
192
|
+
"node",
|
|
193
|
+
"src/gates/gate-classes.ts",
|
|
194
|
+
"typecheck",
|
|
195
|
+
"--project",
|
|
196
|
+
"tsconfig.src.json",
|
|
197
|
+
"--project",
|
|
198
|
+
"tsconfig.test.json",
|
|
199
|
+
"--project",
|
|
200
|
+
"plugin/tsconfig.json"
|
|
201
|
+
],
|
|
202
|
+
"unitLabel": "source files type-checked",
|
|
203
|
+
"applicability": "required"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"id": "gate-classes",
|
|
207
|
+
"command": [
|
|
208
|
+
"node",
|
|
209
|
+
"src/gates/gate-classes.ts",
|
|
210
|
+
"gate-classes",
|
|
211
|
+
"--declarations",
|
|
212
|
+
"delivery/plan/phase-declarations",
|
|
213
|
+
"--registry",
|
|
214
|
+
"gate-registry.yaml"
|
|
215
|
+
],
|
|
216
|
+
"unitLabel": "declared gate classes checked",
|
|
217
|
+
"applicability": "required",
|
|
218
|
+
"parameters": [
|
|
219
|
+
"phase"
|
|
220
|
+
],
|
|
221
|
+
"precondition": {
|
|
222
|
+
"id": "gate-classes-branch-is-a-phase-branch",
|
|
223
|
+
"kind": "branch-matches",
|
|
224
|
+
"pattern": "claude/m[0-9]+-p[0-9]+-.*"
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"id": "merge-preconditions",
|
|
229
|
+
"command": [
|
|
230
|
+
"node",
|
|
231
|
+
"src/gates/merge-preconditions.ts"
|
|
232
|
+
],
|
|
233
|
+
"unitLabel": "merge preconditions evaluated",
|
|
234
|
+
"applicability": "conditional",
|
|
235
|
+
"parameters": [
|
|
236
|
+
"head",
|
|
237
|
+
"phase"
|
|
238
|
+
],
|
|
239
|
+
"precondition": {
|
|
240
|
+
"id": "merge-preconditions-verdicts-present",
|
|
241
|
+
"kind": "command-exit-zero",
|
|
242
|
+
"command": [
|
|
243
|
+
"node",
|
|
244
|
+
"scripts/check-dual-review.mjs",
|
|
245
|
+
"--precondition",
|
|
246
|
+
"."
|
|
247
|
+
]
|
|
248
|
+
}
|
|
187
249
|
}
|
|
188
250
|
],
|
|
189
251
|
"destructiveCommands": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiphys/kernel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Tiphys kernel: the fleet orchestration toolbelt, delivered as an npm package.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -14,6 +14,15 @@
|
|
|
14
14
|
"bin": {
|
|
15
15
|
"tiphys": "dist/bin/tiphys.js"
|
|
16
16
|
},
|
|
17
|
+
"main": "./dist/src/index.js",
|
|
18
|
+
"types": "./dist/src/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/src/index.d.ts",
|
|
22
|
+
"default": "./dist/src/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./package.json": "./package.json"
|
|
25
|
+
},
|
|
17
26
|
"files": [
|
|
18
27
|
"dist",
|
|
19
28
|
"!dist/node_modules",
|
|
@@ -29,10 +38,16 @@
|
|
|
29
38
|
"templates",
|
|
30
39
|
"tuition"
|
|
31
40
|
],
|
|
41
|
+
"workspaces": [
|
|
42
|
+
"plugin"
|
|
43
|
+
],
|
|
44
|
+
"overrides": {
|
|
45
|
+
"@tiphys/kernel": "file:."
|
|
46
|
+
},
|
|
32
47
|
"scripts": {
|
|
33
|
-
"build": "tsc -b tsconfig.src.json tsconfig.test.json && npm run build:schemas && npm run build:runtime-deps",
|
|
48
|
+
"build": "tsc -b tsconfig.src.json tsconfig.test.json plugin/tsconfig.json && npm run build:schemas && npm run build:runtime-deps",
|
|
34
49
|
"build:schemas": "node --input-type=module -e \"import { cpSync } from 'node:fs'; cpSync('src/gates/schemas', 'dist/src/gates/schemas', { recursive: true });\"",
|
|
35
|
-
"build:runtime-deps": "node --input-type=module -e \"import { cpSync, readFileSync } from 'node:fs'; const lock = JSON.parse(readFileSync('node_modules/.package-lock.json', 'utf8')); for (const [path, entry] of Object.entries(lock.packages ?? {})) { if (!path.startsWith('node_modules/') || entry?.dev === true) continue; cpSync(path, 'dist/' + path, { recursive: true }); }\"",
|
|
50
|
+
"build:runtime-deps": "node --input-type=module -e \"import { cpSync, readFileSync } from 'node:fs'; const lock = JSON.parse(readFileSync('node_modules/.package-lock.json', 'utf8')); for (const [path, entry] of Object.entries(lock.packages ?? {})) { if (!path.startsWith('node_modules/') || entry?.dev === true || entry?.link === true) continue; cpSync(path, 'dist/' + path, { recursive: true }); }\"",
|
|
36
51
|
"test": "node --test \"test/**/*.test.ts\"",
|
|
37
52
|
"gate:suite": "node src/gates/suite.ts --pin-root src --pin-root bin --pin-root test",
|
|
38
53
|
"prepack": "npm run build",
|
package/roles/implementer.md
CHANGED
|
@@ -394,6 +394,9 @@ Then the gates `full` mode selects, run by `tiphys gates run --registry gate-reg
|
|
|
394
394
|
| `check-agents-references` | script | required | references resolved |
|
|
395
395
|
| `check-dual-review` | script | conditional | review verdicts examined for decorrelation |
|
|
396
396
|
| `license` | script | required | production packages licensed |
|
|
397
|
+
| `typecheck` | script | required | source files type-checked |
|
|
398
|
+
| `gate-classes` | script | required | declared gate classes checked |
|
|
399
|
+
| `merge-preconditions` | script | conditional | merge preconditions evaluated |
|
|
397
400
|
| `unit-tests-for-changed-service-methods` | clean-room-checklist (probe `unit-tests-for-changed-service-methods`) | conditional | changed service methods checked |
|
|
398
401
|
| `fixtures-for-changed-component-states` | clean-room-checklist (probe `fixtures-for-changed-component-states`) | conditional | changed component states checked |
|
|
399
402
|
|
package/schemas/README.md
CHANGED
|
@@ -46,6 +46,7 @@ test (`test/schemas.test.ts`).
|
|
|
46
46
|
| `const` | |
|
|
47
47
|
| `items` | |
|
|
48
48
|
| `minItems` | |
|
|
49
|
+
| `uniqueItems` | boolean only; used by five shipped schemas here and MISSING FROM THIS TABLE from the day M3-P1 wrote both halves until the DR-0047 sweep, because nothing asserted the two agreed |
|
|
49
50
|
| `minLength` | |
|
|
50
51
|
| `pattern` | |
|
|
51
52
|
| `$ref` | local references only; a remote reference fails compilation |
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
],
|
|
249
249
|
"properties": {
|
|
250
250
|
"max-fix-rounds-after-review": {
|
|
251
|
-
"description": "How many fix rounds may follow the first dual review before the bound fires. DR-0012
|
|
251
|
+
"description": "How many fix rounds may follow the first dual review before the bound fires. DR-0012 set two; DR-0035 replaced the single bound with a table running from one round (a zero or small subject) to three (a large subject at high impact), so what a mode records here is that table's CEILING rather than one phase's budget.",
|
|
252
252
|
"type": "integer"
|
|
253
253
|
},
|
|
254
254
|
"recurrence-of-high-in-one-component": {
|
|
@@ -151,6 +151,25 @@
|
|
|
151
151
|
}
|
|
152
152
|
]
|
|
153
153
|
},
|
|
154
|
+
"review-families": {
|
|
155
|
+
"$comment": "DR-0038's DECLARATION, and it is a declaration rather than the exception itself (M4-D-28, kernel plan M4 section 4.2.6). DR-0012 condition 1 requires two clean-room reviews produced on different model FAMILIES. A project with one family available can satisfy that only by recording something false, and the shipped check makes it worse: it compares canonicalised STRINGS, so two models of one family compare as distinct and the pair reports decorrelated. This field is where a project states WHICH families its environment actually has. The schema does not encode the exception: single-family is `available.length === 1`, and what that then means is `dual-review-decorrelation`'s business. OPTIONAL, AND ITS ABSENCE IS NOT PERMISSION: an absent `review-families` leaves the cross-family requirement applying unchanged, so a same-family pair stays red (src/gates/release.ts:1037 states the same rule for the sibling case). WHY THE CHARTER AND NOT assurance-modes.yaml: DR-0029's split asks whether a fact is process or predicate, and 'which model families exist in this environment' is a fact about the PROJECT's environment, so it belongs to the project's own declaration; the assurance-mode vocabularies are closed by DR-0020 and bound to a derived check.",
|
|
156
|
+
"type": "object",
|
|
157
|
+
"additionalProperties": false,
|
|
158
|
+
"required": ["available", "reason"],
|
|
159
|
+
"properties": {
|
|
160
|
+
"available": {
|
|
161
|
+
"$comment": "The model families this environment can actually dispatch a clean-room review on. NOT an enum: no closed vocabulary of model families can be kept current, and a stale enum here would refuse a true declaration. The check canonicalises each entry the same way it canonicalises a verdict's `produced-by`, so the two are comparable.",
|
|
162
|
+
"type": "array",
|
|
163
|
+
"minItems": 1,
|
|
164
|
+
"items": { "type": "string", "minLength": 1 }
|
|
165
|
+
},
|
|
166
|
+
"reason": {
|
|
167
|
+
"$comment": "Investigation defence 2, the same rule release-verification mode none is held to: narrowing an owner-reserved merge condition costs a stated reason. A declaration nobody has to justify is the shape DR-0038 exists to replace.",
|
|
168
|
+
"type": "string",
|
|
169
|
+
"minLength": 1
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
154
173
|
"retention": {
|
|
155
174
|
"$comment": "Consumed by M3-P8 for R-098.",
|
|
156
175
|
"type": "object",
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://tiphys.dev/schemas/cutover-state.schema.json",
|
|
4
|
+
"title": "Cutover state",
|
|
5
|
+
"description": "The fleet's cutover.json: the five freeze switches and what each of them records. Kernel plan M4, M4-P25 acceptance criterion 4.",
|
|
6
|
+
"$comment": "THE WIRE NAMES ARE camelCase AND THAT IS ESTABLISHED, NOT CHOSEN HERE. The M4 plan section spells the fields flipped-at, flipped-by, reason and restore-to; the document M4-P26 already writes and reads spells them flippedAt, flippedBy, reason and restoreTo (src/cutover.ts:98 declares the interface and src/cutover.ts:152 validates it). A schema that pinned the kebab spelling would refuse every document the shipped writer produces, so this pins what the document uses and the plan's spelling is read as prose naming the four fields rather than as their serialised keys.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"required": ["switches"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"switches": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"description": "One record per switch. The five names are a CLOSED list: a sixth name is a plan revision, not a document edit, because every rollback trigger enumerates them.",
|
|
13
|
+
"required": [
|
|
14
|
+
"planning-and-scope",
|
|
15
|
+
"review-and-arbitration",
|
|
16
|
+
"credentials-and-refs",
|
|
17
|
+
"salvage-and-recovery",
|
|
18
|
+
"closeout"
|
|
19
|
+
],
|
|
20
|
+
"properties": {
|
|
21
|
+
"planning-and-scope": { "$ref": "#/$defs/switchRecord" },
|
|
22
|
+
"review-and-arbitration": { "$ref": "#/$defs/switchRecord" },
|
|
23
|
+
"credentials-and-refs": { "$ref": "#/$defs/switchRecord" },
|
|
24
|
+
"salvage-and-recovery": { "$ref": "#/$defs/switchRecord" },
|
|
25
|
+
"closeout": { "$ref": "#/$defs/switchRecord" }
|
|
26
|
+
},
|
|
27
|
+
"additionalProperties": false
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"additionalProperties": true,
|
|
31
|
+
"$defs": {
|
|
32
|
+
"switchRecord": {
|
|
33
|
+
"$comment": "additionalProperties is TRUE here and at the document level, against the schemas/README.md preference for false at every object level, and the deviation is deliberate rather than an omission. M4-P26 shipped a rollback that CARRIES document keys it does not own, at both levels, and registered that behaviour as a guarded test (test/cutover.test.ts:974). Closing either level would make the shipped writer refuse its own preserved keys, so this document is open by decision and the closed half is the switch NAME list one level up, which is the vocabulary that actually has to be closed.",
|
|
34
|
+
"type": "object",
|
|
35
|
+
"required": ["state", "flippedAt", "flippedBy", "reason", "restoreTo"],
|
|
36
|
+
"properties": {
|
|
37
|
+
"state": {
|
|
38
|
+
"description": "Which process holds the authority this switch governs.",
|
|
39
|
+
"enum": ["current", "kernel"]
|
|
40
|
+
},
|
|
41
|
+
"flippedAt": {
|
|
42
|
+
"description": "When the switch was last written, as an ISO 8601 instant.",
|
|
43
|
+
"type": "string",
|
|
44
|
+
"minLength": 1
|
|
45
|
+
},
|
|
46
|
+
"flippedBy": {
|
|
47
|
+
"description": "Who or what performed the write.",
|
|
48
|
+
"type": "string",
|
|
49
|
+
"minLength": 1
|
|
50
|
+
},
|
|
51
|
+
"reason": {
|
|
52
|
+
"description": "Why the switch was written.",
|
|
53
|
+
"type": "string",
|
|
54
|
+
"minLength": 1
|
|
55
|
+
},
|
|
56
|
+
"restoreTo": {
|
|
57
|
+
"description": "The value the switch held BEFORE the write. It is what makes rollback a matter of reading a recorded value rather than reconstructing an intent, and a record without it cannot be rolled back at all.",
|
|
58
|
+
"enum": ["current", "kernel"]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"additionalProperties": true
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://tiphys.dev/schemas/executor-record.schema.json",
|
|
4
|
+
"title": "Tiphys executor launch record",
|
|
5
|
+
"description": "tasks/<id>/executor.json, the record an ExecutorAdapter writes at launch (DR-0006 for the format, PR-207 for the shape, M4-P3 for the contract). Until M4-P3 this document was written by the kernel and validated by nothing, which is the state delivery/plan/m4-intake.md:272 names. It is written BEFORE the payload starts, which is what makes a failure to write it provably a launch failure and therefore safe to roll back.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["adapter", "launchedAt"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"adapter": {
|
|
11
|
+
"$comment": "The adapter that wrote this record, by its own `name`. REQUIRED: a launch record that does not say what launched it cannot be attributed, and attribution is the whole reason an operator opens this file.",
|
|
12
|
+
"type": "string",
|
|
13
|
+
"minLength": 1
|
|
14
|
+
},
|
|
15
|
+
"launchedAt": {
|
|
16
|
+
"$comment": "RFC 3339 UTC, the same spelling every other Tiphys record uses, so two records from two machines sort. Written from `new Date().toISOString()`.",
|
|
17
|
+
"type": "string",
|
|
18
|
+
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$"
|
|
19
|
+
},
|
|
20
|
+
"deadline": {
|
|
21
|
+
"$comment": "PR-207. The absolute instant by which the task must have completed, present ONLY when --deadline was passed. Recorded as an instant rather than as raw seconds so the watcher compares it against the clock directly instead of re-deriving it from launchedAt.",
|
|
22
|
+
"type": "string",
|
|
23
|
+
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$"
|
|
24
|
+
},
|
|
25
|
+
"requestedTier": {
|
|
26
|
+
"$comment": "M4-P3 criterion 6. THE DECLARED TIER THE REQUEST CARRIED, VERBATIM, AND NEVER A MODEL NAME. Whatever role-model-config.yaml declares crosses the seam unaltered; the tier-to-model mapping lives in the plugin and never in src/, which is what keeps a harness that is not the one named possible at all (delivery/plan/m4-intake.md:377). The schema does not enum this value, because the vocabulary belongs to the plugin and an enum here would be that mapping's first half.",
|
|
27
|
+
"type": "string",
|
|
28
|
+
"minLength": 1
|
|
29
|
+
},
|
|
30
|
+
"requestedRole": {
|
|
31
|
+
"$comment": "M4-P3 criterion 6. The role the request carried, verbatim. Not enumerated here for the same reason requestedTier is not: roles/ is a shipped directory and the role-to-brief mapping is the plugin's.",
|
|
32
|
+
"type": "string",
|
|
33
|
+
"minLength": 1
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|