@ttsc/evidence 0.26.2 → 0.28.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/README.md +82 -169
- package/lib/structures/ITtscEvidenceGraphClaimBase.d.ts +15 -5
- package/lib/structures/ITtscEvidenceGraphMarkdownReference.d.ts +70 -6
- package/lib/structures/ITtscEvidenceGraphPrismaClaim.d.ts +5 -0
- package/lib/structures/ITtscEvidenceGraphPrismaReference.d.ts +16 -5
- package/lib/structures/ITtscEvidenceGraphReferenceBase.d.ts +8 -0
- package/native/base.go +517 -22
- package/native/config.go +114 -5
- package/native/graph.go +332 -70
- package/native/graph_nodes.go +121 -0
- package/native/loader.go +30 -7
- package/native/markdown.go +91 -28
- package/native/model.go +49 -16
- package/native/prisma.go +167 -48
- package/native/prisma_cache.go +40 -16
- package/native/swagger.go +1 -1
- package/native/swagger_cache.go +1 -1
- package/native/typescript.go +120 -9
- package/package.json +5 -5
package/native/config.go
CHANGED
|
@@ -92,6 +92,7 @@ func decodeClaim(raw json.RawMessage, index int) (claimSpec, []string) {
|
|
|
92
92
|
problems = append(problems, symbolProblems...)
|
|
93
93
|
references, referenceProblems := decodeReferences(kind, object["reference"], path+".reference")
|
|
94
94
|
problems = append(problems, referenceProblems...)
|
|
95
|
+
problems = append(problems, rejectChecklistCarriers(carriers, references, path)...)
|
|
95
96
|
if len(problems) != 0 {
|
|
96
97
|
return claimSpec{}, problems
|
|
97
98
|
}
|
|
@@ -186,6 +187,7 @@ func decodeReference(
|
|
|
186
187
|
"uniqueEvidence",
|
|
187
188
|
"singleEvidencePerSymbol",
|
|
188
189
|
"requireReview",
|
|
190
|
+
"checklist",
|
|
189
191
|
"package",
|
|
190
192
|
"root",
|
|
191
193
|
"file",
|
|
@@ -204,7 +206,7 @@ func decodeReference(
|
|
|
204
206
|
}
|
|
205
207
|
root, rootProblems := decodeRoot(object["root"], kind, path+".root")
|
|
206
208
|
problems = append(problems, rootProblems...)
|
|
207
|
-
policy, policyProblems := decodeReferencePolicy(object, path)
|
|
209
|
+
policy, policyProblems := decodeReferencePolicy(object, kind, path)
|
|
208
210
|
problems = append(problems, policyProblems...)
|
|
209
211
|
files := globSet{}
|
|
210
212
|
source := ""
|
|
@@ -278,8 +280,13 @@ func decodeReference(
|
|
|
278
280
|
// before a disabled claim is filtered. Each option is a flat boolean whose
|
|
279
281
|
// false value means "not configured", so an omitted option and an explicit
|
|
280
282
|
// false preserve the original behavior identically.
|
|
283
|
+
//
|
|
284
|
+
// The reference kind is read only by `checklist`, which the other four do not
|
|
285
|
+
// need: they tighten a count that every artifact kind has, while a per-host
|
|
286
|
+
// obligation is a statement about a document that is read item by item.
|
|
281
287
|
func decodeReferencePolicy(
|
|
282
288
|
object map[string]json.RawMessage,
|
|
289
|
+
kind artifactKind,
|
|
283
290
|
path string,
|
|
284
291
|
) (referencePolicy, []string) {
|
|
285
292
|
policy := referencePolicy{}
|
|
@@ -308,9 +315,106 @@ func decodeReferencePolicy(
|
|
|
308
315
|
decodeFlag("uniqueEvidence", &policy.UniqueEvidence)
|
|
309
316
|
decodeFlag("singleEvidencePerSymbol", &policy.SingleEvidencePerSymbol)
|
|
310
317
|
decodeFlag("requireReview", &policy.RequireReview)
|
|
318
|
+
decodeFlag("checklist", &policy.Checklist)
|
|
319
|
+
problems = append(problems, rejectChecklistConflicts(policy, kind, path)...)
|
|
311
320
|
return policy, problems
|
|
312
321
|
}
|
|
313
322
|
|
|
323
|
+
// rejectChecklistCarriers refuses a checklist beside gathered exclusion
|
|
324
|
+
// carriers, which is the third combination no author can satisfy.
|
|
325
|
+
//
|
|
326
|
+
// The two state opposite intents. Carriers gather every exclusion a claim owns
|
|
327
|
+
// into one file so a reviewer reads them by opening it; a checklist makes every
|
|
328
|
+
// acknowledgement one host's own answer. Together they leave every host outside
|
|
329
|
+
// the carrier globs with no way to say an item does not apply: the tag written
|
|
330
|
+
// beside the host is refused as misplaced, and the tag written in the carrier
|
|
331
|
+
// answers for no host. Measured, the two diagnostics name each other's file, so
|
|
332
|
+
// an author following either repair is sent back to the other.
|
|
333
|
+
//
|
|
334
|
+
// Refused here rather than as coverage for the same reason the cardinality
|
|
335
|
+
// pairs are: it is a property of the configuration, and a claim whose every
|
|
336
|
+
// host happens to sit in a carrier file satisfies it by accident.
|
|
337
|
+
func rejectChecklistCarriers(
|
|
338
|
+
carriers globSet,
|
|
339
|
+
references []referenceSpec,
|
|
340
|
+
path string,
|
|
341
|
+
) []string {
|
|
342
|
+
if len(carriers.Patterns) == 0 {
|
|
343
|
+
return nil
|
|
344
|
+
}
|
|
345
|
+
for _, reference := range references {
|
|
346
|
+
// A reference refusing exclusions outright has nothing for the carriers to
|
|
347
|
+
// confine, so the impossibility this refuses does not arise there and the
|
|
348
|
+
// carriers are governing some other reference's exclusions, which is the
|
|
349
|
+
// ledger the property exists for. Refusing that pair would contradict the
|
|
350
|
+
// published guidance that `checklist` and `noEvidenceExclude` are the
|
|
351
|
+
// intended pairing.
|
|
352
|
+
if !reference.Policy.Checklist || reference.Policy.NoExclude {
|
|
353
|
+
continue
|
|
354
|
+
}
|
|
355
|
+
where := path + ".reference"
|
|
356
|
+
if len(references) > 1 {
|
|
357
|
+
where += "[" + decimal(reference.Index) + "]"
|
|
358
|
+
}
|
|
359
|
+
return []string{configurationProblem(
|
|
360
|
+
graphRuleName,
|
|
361
|
+
path+".evidenceExcludeCarriers",
|
|
362
|
+
"a checklist reference cannot be gathered into exclusion carriers: "+where+
|
|
363
|
+
" makes every acknowledgement one host's own answer, while these globs confine exclusions to other files, so no host outside them can record that an item does not apply. Drop the carriers, drop `checklist` from that reference, or give it `noEvidenceExclude` so it accepts no exclusion to gather.",
|
|
364
|
+
)}
|
|
365
|
+
}
|
|
366
|
+
return nil
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// rejectChecklistConflicts refuses the two combinations no author can satisfy
|
|
370
|
+
// and the artifact kinds a checklist is not a statement about.
|
|
371
|
+
//
|
|
372
|
+
// The kind refusal is silent when the kind itself failed to decode, the way
|
|
373
|
+
// rejectForeignTypeScriptReference is: naming an artifact the author did not
|
|
374
|
+
// successfully spell would send them to the wrong line.
|
|
375
|
+
//
|
|
376
|
+
// The two cardinality refusals are unsatisfiability, not preference. A
|
|
377
|
+
// checklist makes every selected host cite every unit, so uniqueEvidence's
|
|
378
|
+
// one-host-per-unit ceiling breaks the moment a claim has two hosts, and
|
|
379
|
+
// singleEvidencePerSymbol's exactly-one-unit-per-host breaks the moment the
|
|
380
|
+
// population has two units. Both are reported at decode rather than as
|
|
381
|
+
// coverage failures, because a population of one unit and one host satisfies
|
|
382
|
+
// them by accident and would let a contradictory configuration ship until the
|
|
383
|
+
// day a second file arrives.
|
|
384
|
+
func rejectChecklistConflicts(
|
|
385
|
+
policy referencePolicy,
|
|
386
|
+
kind artifactKind,
|
|
387
|
+
path string,
|
|
388
|
+
) []string {
|
|
389
|
+
if !policy.Checklist {
|
|
390
|
+
return nil
|
|
391
|
+
}
|
|
392
|
+
if kind != artifactMarkdown && kind != "" {
|
|
393
|
+
return []string{configurationProblem(
|
|
394
|
+
graphRuleName,
|
|
395
|
+
path+".checklist",
|
|
396
|
+
"only a Markdown reference can be a checklist; a "+string(kind)+
|
|
397
|
+
" population has no reading order in which a host answers one item at a time. Drop the option, or move the items into a Markdown document this reference selects.",
|
|
398
|
+
)}
|
|
399
|
+
}
|
|
400
|
+
problems := []string{}
|
|
401
|
+
if policy.UniqueEvidence {
|
|
402
|
+
problems = append(problems, configurationProblem(
|
|
403
|
+
graphRuleName,
|
|
404
|
+
path+".checklist",
|
|
405
|
+
"checklist and uniqueEvidence cannot both hold: a checklist requires every selected host to cite every unit, while uniqueEvidence allows each unit at most one host, so any claim with two hosts fails both ways. Keep the one that states this obligation.",
|
|
406
|
+
))
|
|
407
|
+
}
|
|
408
|
+
if policy.SingleEvidencePerSymbol {
|
|
409
|
+
problems = append(problems, configurationProblem(
|
|
410
|
+
graphRuleName,
|
|
411
|
+
path+".checklist",
|
|
412
|
+
"checklist and singleEvidencePerSymbol cannot both hold: a checklist requires every selected host to cite every unit, while singleEvidencePerSymbol allows each host exactly one, so any population with two units fails both ways. Keep the one that states this obligation.",
|
|
413
|
+
))
|
|
414
|
+
}
|
|
415
|
+
return problems
|
|
416
|
+
}
|
|
417
|
+
|
|
314
418
|
// rejectForeignTypeScriptReference refuses a code population to a claim that
|
|
315
419
|
// cannot address one.
|
|
316
420
|
//
|
|
@@ -563,7 +667,7 @@ func normalizeSwaggerSource(value string) (string, string) {
|
|
|
563
667
|
}
|
|
564
668
|
parsed, err := url.Parse(value)
|
|
565
669
|
if err != nil {
|
|
566
|
-
return "", "invalid Swagger source '" + value + "': " + err
|
|
670
|
+
return "", "invalid Swagger source '" + value + "': " + causeText(err) + "."
|
|
567
671
|
}
|
|
568
672
|
if !drive && parsed.Scheme != "" {
|
|
569
673
|
if parsed.Scheme != "http" && parsed.Scheme != "https" {
|
|
@@ -617,7 +721,7 @@ func decodeFiles(raw json.RawMessage, path string) (globSet, []string) {
|
|
|
617
721
|
}
|
|
618
722
|
globs, err := newGlobSet(patterns)
|
|
619
723
|
if err != nil {
|
|
620
|
-
return globSet{}, []string{"Invalid evidence/graph configuration at " + path + ": " + err.
|
|
724
|
+
return globSet{}, []string{"Invalid evidence/graph configuration at " + path + ": " + causeText(err) + "."}
|
|
621
725
|
}
|
|
622
726
|
return globs, nil
|
|
623
727
|
}
|
|
@@ -779,12 +883,17 @@ func describePatterns(globs globSet) string {
|
|
|
779
883
|
}
|
|
780
884
|
|
|
781
885
|
// describePopulation names the patterns a population selects with, and the base
|
|
782
|
-
// they
|
|
886
|
+
// they resolve against when that base is not the project root.
|
|
783
887
|
//
|
|
784
888
|
// The base is stated rather than assumed, because a citation that resolves
|
|
785
889
|
// outside the project has to be repairable from the diagnostic alone: patterns
|
|
786
890
|
// that look correct against a root the reader is imagining are the failure this
|
|
787
|
-
// property introduces, and naming the
|
|
891
|
+
// property introduces, and naming the base is what removes it.
|
|
892
|
+
//
|
|
893
|
+
// It is named by its declared spelling rather than its resolved one, because
|
|
894
|
+
// the repair is an edit to a configuration property and the reader has to find
|
|
895
|
+
// that property first. `populationRootLabel` owns that choice and the reasoning
|
|
896
|
+
// behind it.
|
|
788
897
|
func describePopulation(base populationBase, globs globSet) string {
|
|
789
898
|
if base.Default {
|
|
790
899
|
return describePatterns(globs)
|