-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcodecov.yml
More file actions
663 lines (649 loc) · 33.9 KB
/
Copy pathcodecov.yml
File metadata and controls
663 lines (649 loc) · 33.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
# Codecov configuration.
#
# Coverage is produced by the `clang-coverage` CI job via scripts/coverage.sh:
# always include/morph (the library), plus examples/common (the ladder's
# hand-written GUI/testkit code — real coverage of morph's own client stack,
# not app-specific logic; see examples/TESTING.md's "round-7 T4 reframe") and
# every built rung's own models/app/presenter code, whenever that leg's
# configure also builds the ladder. Tests, a rung's `main()` shells
# (`gui/`, `gui_wasm/`), demo src/, fetched dependencies, and
# AUTOMOC-generated files (which live under the build tree, never under a
# source-tree path this config names) are excluded.
coverage:
status:
# Default (include/morph, i.e. everything not claimed by a component
# below): informational only, unchanged from before this file started
# tracking the ladder. This project's own IMPLEMENTATION.md rule 5 has
# never claimed the whole library is 100% covered — only "models" (and
# now the ladder's hand-written GUI/testkit code, see the component
# below) carry that promise. Note that no status in this file blocks
# today -- see the components below for why the ladder's gates are
# informational while rungs 5-8 are still being built (morph#133).
project:
default:
informational: true
patch:
default:
informational: true
# The ladder's hand-written GUI/testkit code is held to the same 100% bar
# examples/IMPLEMENTATION.md rule 5 sets for models (there are no rung
# models yet — rung 0 ships no app — so this component is the whole of that
# promise today; src/models/ and include/<rung>/models/ join it as rungs
# land). Scoped to examples/common specifically, not project-wide: a
# gate over the *entire* codebase is a much bigger, unverified claim this
# repo has never made and this change does not attempt.
#
# The target sat at 98% (not a literal 100%) for a measurement-tooling reason
# rather than an intentional gap, and the reasoning still explains why a
# ladder component can never honestly read 100%: llvm-cov's source-based coverage places a
# "control reached past this block" counter on the closing brace of certain
# blocks (a switch-case's `}` after `break;`, a scope's `}` after its one
# statement calls a `std::function<void()>`), and that counter can read 0
# even though the statement immediately above it — proven by its own hit
# count — ran. There is no llvm-cov equivalent of gcov's inline
# `LCOV_EXCL_LINE` to suppress just those lines. Confirmed present-day
# instances, all in hand-written (non-test) files, each already directly
# exercised by an existing test per llvm-cov's own count on the preceding
# line: backend_rig.hpp's three switch-case closing braces (BackendRig's
# constructor, one per Mode), strand_interleaver.hpp's two post-`task()`
# closing braces (`step()`, `runSchedule()`), and fault_proxy.cpp's one
# integration-unreachable line pair (onClientConnection's null-guard —
# Qt's own newConnection contract guarantees a valid pointer in practice;
# the underlying decision, isValidIncomingConnection, is unit-tested
# directly). Together these put today's real ceiling at 478/485 = 98.56%
# lines — re-measured at rung 1's close, when `examples/common` gained
# `db_busy_fixture.hpp` and `backend_rig.hpp`'s executor-liveness guard. The
# artifact *list* above is unchanged (the same seven lines); only the
# denominator moved. 98% leaves a small margin below that measured ceiling
# rather than sitting exactly on it, while still failing the gate long before
# a real, newly-introduced gap could hide behind this handful of known
# artifacts.
#
# Per-rung components, one per rung, rather than one component spanning the
# whole ladder: each rung's real ceiling is set by its own handful of known
# artifacts, and folding them together would mean re-deriving a single number
# every time a rung lands. A rung's component simply appears when its
# directory does.
component_management:
individual_components:
# ── The framework itself ────────────────────────────────────────────────
#
# Every other component below is under examples/. Until this one existed,
# include/morph -- the product, and the largest single thing in the report
# -- was scored only by the `default` status above, which carries no target
# at all. The library was the one part of this repository with no stated
# number to hold to, while eight example applications each had one
# (morph#402).
#
# Where 93% comes from, and what has to happen to it. Measured over the
# LCOV this repository actually uploads (build/clang-coverage/coverage.lcov,
# after scripts/aggregate_lcov_branches.py), by Codecov's own arithmetic: a
# DA line with zero hits is a miss, a hit line carrying an untaken BRDA
# branch is a partial, and coverage is hits / (hits + misses + partials).
# That gave 7,977 hits of 8,488 lines = 93.98%, with 332 misses and 179
# partials, so 93% leaves the same small margin below a measured ceiling
# that every target in this file leaves.
#
# Where the number lives, so a regression is legible rather than averaged
# away:
# net 77.61% 1,157 lines 193 misses, 66 partials
# forms 94.68% 1,560 lines 58 misses, 25 partials
# offline 91.94% 633 lines 36 misses, 15 partials
# core 97.35% 3,249 lines 35 misses, 51 partials
# util 97.83% 1,012 lines 4 misses, 18 partials
# session 97.19% 249 lines 4 misses, 3 partials
# qt 97.44% 39 lines 1 miss, 0 partials
# journal 99.44% 357 lines 1 miss, 1 partial
# detail 100.00% 155 lines
# render 100.00% 77 lines
# One subsystem carries the whole gap: net is 26% of the library's misses
# in 14% of its lines. That is not a surprise -- morph#403 is the reason
# anyone can see it, since include/morph/net contributed *zero files* to
# every report before it.
#
# **This target is provisional and must be re-derived from the first
# Codecov report produced after morph#403 lands.** Two reasons, and the
# second is the one that matters. First, the method reproduces Codecov
# to about a third of a point (examples/common: 90.72% computed here
# against 90.39% from the Codecov API on master) rather than exactly --
# the compiler is not a source of the discrepancy: it was measured on
# clang 22.1.8 and CI pins clang 22.
# Second, and unavoidably: morph#403 moved the *denominator*. Handing
# llvm-cov the binaries whose profile data it used to drop brought whole
# files into the report that had never been in it, so include/morph's line
# count is not the 5,716 the API reported for master and the two numbers
# cannot be reconciled by adjusting anything. The measurement has to be
# retaken, not corrected -- which is what morph#403 said would happen.
#
# Re-measured after the 2026-09 framework-coverage-and-mutation plan
# (docs/superpowers/plans/2026-09-03-framework-coverage-and-mutation.md)
# closed the gap the paragraphs above describe. Same file this
# repository actually uploads (build/clang-coverage/coverage.lcov,
# post-aggregate_lcov_branches.py) and the same Codecov-style arithmetic
# (a DA line with zero hits is a miss, a hit line with an untaken BRDA
# branch is a partial, coverage is hits / (hits + misses + partials)) --
# but NOT the same configure as the 93.98% figure above or as CI's
# coverage leg: this run used MORPH_BUILD_NET/OFFLINE_SQLITE/QT=ON
# without MORPH_BUILD_LADDER=ON (Mull/mutation infrastructure being
# unavailable on this machine made the full CI-matching build worth
# skipping rather than fighting for a bookkeeping-only re-measurement).
# LADDER cannot change which include/morph files appear in the
# denominator (it only builds examples/'s own testkit/GUI
# infrastructure and rungs), but its test binaries do exercise
# include/morph and would add hits CI's own report will have that this
# number doesn't -- so 98.10% below is a lower bound on what CI's own
# coverage leg will show for this same tree, not an exact reproduction
# of it. Against a full net + forms + core + offline audit-close-
# remeasure pass, not just the net addition that made the 93% figure
# provisional: 8,502 hits of 8,667 lines = 98.10%, 80 misses, 85
# partials:
#
# net 94.69% 1,262 lines 39 misses, 28 partials
# forms 98.43% 1,590 lines 10 misses, 15 partials
# offline 96.56% 639 lines 11 misses, 11 partials
# core 98.88% 3,292 lines 16 misses, 21 partials
# util 98.91% 1,007 lines 2 misses, 9 partials
# session 98.80% 249 lines 2 misses, 1 partial
# qt 100.00% 39 lines
# journal 100.00% 357 lines
# detail 100.00% 155 lines
# render 100.00% 77 lines
#
# net -- the subsystem that carried the whole gap above -- is no longer
# an outlier: every subsystem now sits at or above 94.69%, and the four
# this plan actually touched (net, forms, offline, core) each moved by
# double digits or, for core (already high), by the largest remaining
# absolute miss count. The branch-coverage view
# (scripts/check_branch_coverage.py, the stricter of the two measures
# since a hit line with one untaken arm still counts against it) moved
# from 91.19% to 95.95% over the same work, with every subsystem clear
# of its own floor in scripts/check_branch_coverage.py's FLOORS table.
#
# 97%, a margin below the 98.10% measured ceiling on the same terms
# every other target in this file leaves (roughly a point, not sitting
# on the number). informational: true is unchanged, for the same reason
# as before: the decision to make this blocking is the repo owner's,
# recorded once the ladder is finished, and this component changes what
# the file *says* about the framework, not what it enforces.
- component_id: framework
name: "morph framework (include/morph)"
paths:
- include/morph/**
statuses:
- type: project
target: 97%
informational: true
- type: patch
target: 97%
informational: true
# include/morph/offline and include/morph/forms, each split out of
# `framework` above so the subsystem can produce a status of its own
# (morph#453 item D).
#
# Neither had a `component_id` until now, and the consequence was that
# neither could ever go red. `framework` scores all of include/morph as
# one number, and include/morph/offline is 639 of its 8,667 lines --
# offline sliding from 96% to 60% moves the whole-library figure by
# about two and a half points and names no subsystem while doing it.
# This is the same hole this file already records one level down for the
# rungs ("a gate, since removed, checked that each rung has a
# `component_id`, not that it has these, so the omission was
# unguarded"), and the fix is the same: a component per thing you want
# to be able to see move.
#
# The paths deliberately overlap `framework`'s `include/morph/**`.
# Codecov scores each component independently, so these files are still
# counted there too; this adds a narrower second view rather than
# carving the first one up. `framework`'s own 97% target is unchanged
# and still measured over the whole library.
#
# Both targets come from the same audit-close-remeasure run recorded in
# the `framework` comment above -- same uploaded file
# (build/clang-coverage/coverage.lcov, post-aggregate_lcov_branches.py),
# same Codecov-style arithmetic, and so the same caveat: that run
# configured NET/OFFLINE_SQLITE/QT without LADDER, whose test binaries
# would add hits to include/morph, so each figure is a lower bound on
# what CI's own coverage leg reports for this tree.
#
# offline 96.56% 639 lines 11 misses, 11 partials
# forms 98.43% 1,590 lines 10 misses, 15 partials
#
# Both were re-derived from an independent local run of CI's own
# clang-coverage configure (NET/OFFLINE_SQLITE/QT/LADDER all ON, rungs
# `all`, 2,706 tests, all passing), which lands on offline 96.56% /
# 639 lines / 11 misses / 11 partials -- the same figures to the digit --
# and forms 98.60% / 1,577 lines / 10 misses / 12 partials, a shade above
# the LADDER-less 98.43% for exactly the reason named above. Both targets
# keep their margin under either measurement.
#
# `offline` also answers morph#453 item C, which asked for the before
# *and* the after for the one header the 85.20% subsystem figure was
# hiding. On the same Codecov arithmetic:
#
# include/morph/offline/sqlite_offline_queue.hpp
# before (morph#409) 57.04% 52 misses, 12 partials
# after 91.53% 189 lines, 8 misses, 8 partials
#
# Most of that move is reporting, not tests: morph#403 is why the header
# had a denominator at all (`morph_offline_sqlite_tests` was never handed
# to llvm-cov, so its hits were dropped). Not all of it, though, which is
# why this branch still closed six genuine gaps in that header and
# documented the two it could not reach -- and why the honest answer to
# #409's "if it barely moves, the suite is thin" is that the suite was
# not thin, only invisible.
#
# Targets sit roughly a point below each measured ceiling, the same
# margin convention every other target in this file uses, so an ordinary
# refactor does not trip them while a real regression does.
# `informational: true` on both, matching `framework` and every ladder
# component: this changes what the file can *see*, not what it enforces.
# Making any of it blocking is the repo owner's decision (morph#133).
- component_id: offline
name: "morph offline queue (include/morph/offline)"
paths:
- include/morph/offline/**
statuses:
- type: project
target: 95%
informational: true
- type: patch
target: 95%
informational: true
- component_id: forms
name: "morph forms (include/morph/forms)"
paths:
- include/morph/forms/**
statuses:
- type: project
target: 97%
informational: true
- type: patch
target: 97%
informational: true
- component_id: ladder
name: "application ladder (examples/common)"
paths:
- examples/common/**
statuses:
- type: project
target: 95%
informational: true
- type: patch
target: 95%
informational: true
# Rung 1, pastebin.
#
# What is actually measured, precisely — the `paths` glob below is
# `examples/pastebin/**`, but a component can only score files the
# uploaded report contains, and that report is whatever
# `scripts/coverage.sh` names in its `SOURCES` array. For this rung that
# is `include/`, `src/` and `gui_lib/`: the DTOs, the model and app
# bootstrap, and the hand-written presenter/QML-adapter layer. It is
# **not** `gui/` or `gui_wasm/` — those are `main()` shells (engine setup,
# argv parsing, `setInitialProperties`) with no unit-testable seam,
# exercised by the offscreen QML engine-load smoke test and by hand, and
# they are named in `ignore:` below so their absence is a decision rather
# than an accident. `tests/` is excluded for the same reason
# examples/common's is: a suite scoring its own test code inflates the
# number it is supposed to police.
#
# Same reasoning as the component above for the target: 96%, not a
# literal 100%, because of a measured ceiling rather than an intentional
# gap. Measured with `llvm-cov report` over that denominator:
# 442/450 lines = 98.22%. Every one of the eight missed lines is
# accounted for:
# * units.hpp (2) — the `default:` arm of `UnitTraits<Unit>::meta`'s
# switch. `Unit` has exactly one enumerator, so that arm is
# unreachable without undefined behavior; it exists because the
# repo's warning policy requires a switch default.
# * src/app/app.cpp (4) — `sweepExpiredOnce()`'s `.onError` branch,
# which logs an `ExpirePaste` that failed to dispatch. Provoking a
# dispatch failure through a `SimulatedRemoteBackend` needs the
# fault-injection proxy that lands at rung 4; until then there is no
# honest way to reach it.
# * src/models/paste_model.cpp (2) — the `rows.empty()` guard in
# `execute(GetPaste)`'s read-back, taken when the row vanishes
# between an `UPDATE` that just matched it and a `SELECT` in the same
# transaction, while that transaction holds the write lock. The
# source documents it as unreachable in practice and treats it as
# "gone" rather than asserting.
# `gui_lib/` itself is fully covered: `paste_presenter.cpp`,
# `paste_qml_bridges.cpp` and both headers' inline bodies are at 100%
# lines, by `tests/test_paste_presenter.cpp` and
# `tests/test_paste_qml_bridges.cpp`.
#
# 96%, not something nearer the 98.22% ceiling, for two reasons: it leaves
# a margin below that ceiling rather than sitting on it, and the ceiling
# is not perfectly stable — `paste_model.cpp` scores 2 or 3 missed lines
# depending on the run, because the two `DbBusyFixture` store-error cases
# race a real SQLite lock and which classifier branch they land in is
# genuinely timing-dependent. A target within a line or two of the ceiling
# would flake on that alone. 96% still fails long before a real,
# newly-introduced gap could hide behind these eight lines.
- component_id: pastebin
name: "application ladder rung 1 (examples/pastebin)"
paths:
- examples/pastebin/**
statuses:
- type: project
target: 95%
informational: true
- type: patch
target: 95%
informational: true
# Rungs 2-4, added with morph#141/#142 -- the change that first put them
# into the coverage report at all. Before it, scripts/coverage.sh named
# only rung 1, so bookmarks, polls and kanban (~15k lines of models,
# presenters and QML adapters) contributed nothing to any number and were
# gated by nothing.
#
# Their measured coverage when they entered the report:
#
# ladder (examples/common) 95.85%
# pastebin (rung 1) 95.99%
# bookmarks (rung 2) 86.79%
# polls (rung 3) 85.99%
# kanban (rung 4) 85.09%
#
# The ~10-point split is not a coincidence: the two components that had a
# gate watching them sit near 96%, and the three that never did sit near
# 85%. That is the clearest evidence in this repo that a visible number
# changes what gets written.
#
# Every status here is `informational: true` deliberately. These rungs are
# below where they should be, and a blocking gate today would stop work on
# rungs 5-8 to pay down debt from rungs 2-4 -- the wrong order. The
# decision is: finish building the ladder, then raise these. Informational
# statuses still post the number on every PR, so the gap stays visible
# while it is being carried rather than quietly forgotten, and flipping
# `informational` to `false` later is a one-line change per component once
# the numbers support it.
#
# Targets are set at each rung's measured floor rather than an aspiration:
# an informational status is a *reference line*, and a line drawn where
# coverage actually is makes a regression legible immediately. An
# aspirational target would show every PR as failing-but-ignored, which
# reads as noise and gets tuned out.
- component_id: bookmarks
name: "application ladder rung 2 (examples/bookmarks)"
paths:
- examples/bookmarks/**
statuses:
- type: project
target: 86%
informational: true
- type: patch
target: 86%
informational: true
- component_id: polls
name: "application ladder rung 3 (examples/polls)"
paths:
- examples/polls/**
statuses:
- type: project
target: 85%
informational: true
- type: patch
target: 85%
informational: true
- component_id: kanban
name: "application ladder rung 4 (examples/kanban)"
paths:
- examples/kanban/**
statuses:
- type: project
target: 85%
informational: true
- type: patch
target: 85%
informational: true
# Rung 5, ledger. Scoped to the rung's models -- what
# examples/IMPLEMENTATION.md rule 5's bar actually names -- rather than the
# whole rung directory, so the number describes domain logic rather than
# being diluted by presenters and QML adapters that have their own tests.
#
# Measured ceiling, from `llvm-cov export`'s JSON (covered/total, not the
# rounded report percentage) over the full ledger suite:
#
# src/models/ledger_model.cpp 611/688 88.81%
# src/models/budget_model.cpp 187/211 88.63%
# src/models/rule_model.cpp 69/79 87.34%
# include/ledger/models/ledger_model.hpp 15/21 71.43%
# include/ledger/models/budget_model.hpp 12/12 100.00%
# include/ledger/models/rule_model.hpp 1/1 100.00%
# ------------------------------------------------------
# total 895/1012 88.44%
#
# Target 87%, a small margin below that ceiling so an ordinary refactor
# does not trip it while a real regression does.
#
# `informational: true`, deviating from this rung's own plan (Task 25 says
# `false`). That plan predates the decision recorded in morph#133: every
# ladder gate is informational until the ladder is built, then raised
# together. Making rung 5 the single blocking component -- while rungs 2-4
# sit informational near 85% -- would invert that policy and gate the
# newest code most strictly precisely because it is newest.
#
# Measuring this honestly was worth doing rather than rounding past: the
# first measurement put rule_model.cpp at 60.76%, which turned out to be
# two documented obligations nothing verified -- Task 11's empty-principal
# refusal and Task 11a's self-journaling, both claimed by the rung and
# neither executed. Covering them moved the file to 87.34% and the
# component from 86.36% to 88.44%.
- component_id: ledger
name: "application ladder rung 5 (examples/ledger models)"
paths:
- examples/ledger/src/models/**
- examples/ledger/include/ledger/models/**
statuses:
- type: project
target: 87%
informational: true
- type: patch
target: 87%
informational: true
# Rung 6, lims. Scoped to the rung's models, like ledger's above and for
# the same reason: the number then describes domain logic rather than
# being diluted by presenters and QML adapters that have their own suites.
#
# NOTE: neither this component nor ledger's could score anything until
# rung 6 also fixed scripts/coverage.sh, whose hand-copied rung list had
# drifted from CMake's and named only rungs 1-4. ledger's component was
# matching a set of files no uploaded report contained -- silently
# reporting nothing rather than failing. Fixed by rung 6, and structurally
# closed by morph#179: coverage.sh now reads examples/rungs.txt (the single
# authoritative rung list) instead of restating it.
#
# The components in this file are the other half of that pair, and are the
# one thing here that still has to be written by hand -- Codecov reads this
# file on its own service, so nothing in the repository can generate it.
# A gate used to fail the build if any rung in examples/rungs.txt had no
# `component_id` here. It was removed with the meta-gates, so the two are
# kept in step by hand now.
#
# Measured ceiling, from `llvm-cov export`'s JSON (covered/total, not the
# rounded report percentage) over the full lims suite:
#
# src/models/sample_model.cpp 666/671 99.25%
# src/models/analysis_catalog_model.cpp 182/186 97.85%
# include/lims/models/sample_model.hpp 7/7 100.00%
# -------------------------------------------------------
# total 855/864 98.96%
#
# The remaining misses are three defensive guards, each unreachable
# through the model's own API rather than merely untested:
# * sample_model.cpp, `alreadyDecided`'s empty-key guard --
# `QueuedCapture::validate()` refuses an empty `operationKey` before
# any dispatch path reaches the lookup, so the guard only fires for a
# caller that bypassed validation entirely.
# * analysis_catalog_model.cpp, `renderSchemaFor`'s "not JSON we can
# patch" arm -- the input is `morph::forms::schemaJson<A>()`, which
# either produces valid JSON or an empty string; there is no input a
# caller can supply.
# * analysis_catalog_model.cpp, `GetAnalysisVersion`'s "version's
# analysis is missing" arm -- `lims_analysis_versions.analysis_id` is
# a declared foreign key, so a version row with no analysis row cannot
# exist while the constraint is enforced.
# Each is kept rather than deleted because each turns an impossible state
# into a typed error instead of a dereference; none is reachable by a test
# that does not first disable the very thing making it impossible.
#
# Target 97%, a margin below the 98.96% ceiling so an ordinary refactor
# does not trip it while a real regression does. `informational: true`,
# consistent with every other ladder component (morph#133): the ladder's
# gates are raised together once it is built, not one rung at a time with
# the newest code gated most strictly.
#
# Measuring this honestly was worth doing rather than rounding past, twice
# over. The first measurement came in at 93.27%, and the gap was not
# padding: it included `AnalysisCatalogModel::attachActionLog`, never
# called by any test, so the catalogue's whole journaling path was
# unverified -- and the audit trail's own classifier, whose
# `VerifyResult` branch was dead because verifications were being
# journaled under an *empty* entity key. That second one was a real
# defect, not a coverage artifact: a sample's audit trail silently omitted
# the second pair of eyes. Fixed by rekeying the journal to the result's
# own sample, and pinned by a test.
- component_id: lims
name: "application ladder rung 6 (examples/lims models)"
paths:
- examples/lims/src/models/**
- examples/lims/include/lims/models/**
statuses:
- type: project
target: 97%
informational: true
- type: patch
target: 97%
informational: true
# Rung 7, crm. Scoped to the rung's models, like ledger's and lims's above
# and for the same reason.
#
# Measured, from `llvm-cov export`'s JSON (covered/total, not the rounded
# report percentage) over the full crm suite (176 tests):
#
# src/models/account_model.cpp 355/377 94.16%
# src/models/authz.cpp 28/28 100.00%
# src/models/contact_model.cpp 130/150 86.67%
# src/models/custom_field_model.cpp 94/102 92.16%
# src/models/lead_model.cpp 156/170 91.76%
# src/models/opportunity_model.cpp 397/435 91.26%
# src/models/quote_model.cpp 209/238 87.82%
# src/models/saved_view_model.cpp 84/88 95.45%
# include/crm/models/*.hpp 15/28 53.57%
# ---------------------------------------------------------
# total 1468/1616 90.84%
#
# Target 89%, a margin below the 90.84% measurement on the same terms as
# ledger's and lims's above, and `informational: true` like every other
# ladder component (morph#133).
#
# Re-measured after morph#403 and morph#426, on a profile with zero foreign
# roots: 1488/1616 = 92.08% lines, of which quote_model.cpp is now
# 222/238 93.28% (GetQuote, previously driven by nothing). By Codecov's own
# arithmetic -- which is what this target is checked against, and which
# counts a line with a one-sided branch as a partial rather than a hit --
# the component reads 87.15%: 1390 hits, 128 misses, 77 partials.
#
# The per-miss audit this entry used to lack is now written, in
# examples/crm/README.md's "What the uncovered lines in crm's models are".
# Its result is that crm is unlike ledger and lims: 92 of the 141 lines it
# classified are the rung's own ValidationError/NotFound rejection paths on
# 25 actions, reachable from the wire and simply untested, and only 4 are
# unreachable-by-design. That is not a ceiling and must not be recorded as
# one (morph#412).
#
# `ContactModel::attachActionLog` and `SavedViewModel::attachActionLog` are
# no longer called by no test: both models gained the "journals its edits
# against the attached identity" case their four siblings had, and no
# defect was found on either -- both journal both mutations, under the
# attached key, with the caller's principal. Recorded as a negative result
# against the lims precedent, rather than left implying an open finding.
- component_id: crm
name: "application ladder rung 7 (examples/crm models)"
paths:
- examples/crm/src/models/**
- examples/crm/include/crm/models/**
statuses:
- type: project
target: 89%
informational: true
- type: patch
target: 89%
informational: true
# Always post the coverage-comparison comment on a PR, even on the first upload
# after activation and even when the base report is still processing.
#
# `layout` is a closed vocabulary, and Codecov rejects an unknown entry as a
# validation error for the *whole file* -- a file that fails validation is
# discarded wholesale, so every `status`, `component_management` and `ignore`
# rule below stops applying and Codecov's own defaults (a blocking
# `codecov/patch` at `target: auto`) silently take their place. `reach` is the
# reachability graph; there is no `reference` section, and naming one is what
# had quietly turned this entire config into a no-op (morph#133).
#
# The failure mode is worth naming because it is invisible: nothing errors,
# the checks still run, and the file reads as though it is in force.
comment:
layout: "reach, diff, flags, files, components"
behavior: default
require_base: false
require_head: true
require_changes: false
# Nothing in examples/ other than examples/common and the built rungs ever
# gets compiled by the coverage job's configure (MORPH_BUILD_LADDER builds
# examples/common's targets plus each rung named by MORPH_LADDER_RUNGS and,
# under Emscripten only, wasm_spike — which this job never reaches), so
# bank/forms/concepts/etc. never produce coverage data here in the first
# place; excluding them explicitly documents the intent rather than relying
# on that as an accident of what happens to be built. A rung's own test
# sources are excluded for the same reason examples/common's are: a suite
# scoring its own test code inflates the number it is supposed to police.
ignore:
- "tests/**"
- "src/**"
- "examples/bank/**"
- "examples/forms/**"
- "examples/concepts/**"
- "examples/vetted_hmac/**"
- "examples/qt_tls_client/**"
- "examples/common/testkit/test_*.cpp"
- "examples/common/testkit/testkit_main.cpp"
- "examples/common/wasm_spike/**"
- "examples/pastebin/tests/**"
- "examples/pastebin/gui/**"
- "examples/pastebin/gui_wasm/**"
# Rungs 2-4, on exactly the same terms as rung 1 above: a rung's own test
# sources are excluded so the suite does not score itself, and `gui/` +
# `gui_wasm/` are `main()` shells with no unit-testable seam. These entries
# arrive with morph#141, which is what first put these rungs into the
# coverage report at all -- scripts/coverage.sh had only ever named rung 1.
- "examples/bookmarks/tests/**"
- "examples/bookmarks/gui/**"
- "examples/bookmarks/gui_wasm/**"
- "examples/polls/tests/**"
- "examples/polls/gui/**"
- "examples/polls/gui_wasm/**"
- "examples/kanban/tests/**"
- "examples/kanban/gui/**"
- "examples/kanban/gui_wasm/**"
# Rungs 5-6, on the same terms. Both entered the coverage report for the
# first time with rung 6's fix to scripts/coverage.sh.
- "examples/ledger/tests/**"
- "examples/ledger/gui/**"
- "examples/ledger/gui_wasm/**"
- "examples/lims/tests/**"
- "examples/lims/gui/**"
- "examples/lims/gui_wasm/**"
# Rung 7, crm, on the same terms. Missing until now: every rung from
# bookmarks onwards got its three entries as it landed, and crm's were not
# added. Nothing failed, because scripts/coverage.sh's SOURCES array names
# only examples/crm/{include,src,gui_lib} and so never put crm's tests or
# main() shells into a report for these lines to exclude -- which is exactly
# the point of writing them down: the entries state the intent rather than
# leaving the exclusion to be an accident of what the other script happens to
# name. A gate (since removed) checked that each rung has a `component_id`,
# not that it has these, so the omission was unguarded then and is now.
- "examples/crm/tests/**"
- "examples/crm/gui/**"
- "examples/crm/gui_wasm/**"