@erclx/canon 4.93.0 → 4.95.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/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/SKILL.md +1 -1
- package/claude/skills/review-pr/REQUIREMENT.md +1 -0
- package/claude/skills/review-pr/SKILL.md +2 -0
- package/claude/skills/test-craft/REQUIREMENT.md +54 -0
- package/claude/skills/test-craft/SKILL.md +77 -0
- package/claude/skills/test-craft/references/adopted.md +44 -0
- package/claude/skills/test-craft/references/component.md +42 -0
- package/claude/skills/test-craft/references/e2e.md +44 -0
- package/claude/skills/test-craft/references/unit.md +49 -0
- package/claude/skills/test-first/REQUIREMENT.md +2 -0
- package/claude/skills/test-first/SKILL.md +4 -2
- package/claude/skills/ui-test/REQUIREMENT.md +7 -2
- package/claude/skills/ui-test/SKILL.md +26 -16
- package/docs/workflow/ai-workflow.md +11 -10
- package/docs/workflow/visual-design-workflow.md +2 -2
- package/governance/rules/core/010-testing.md +4 -2
- package/governance/rules/lib/300-testing-ts.md +4 -0
- package/governance/rules/lib/330-testing-py.md +4 -0
- package/package.json +1 -1
- package/src/claude/cases/misc.ts +5 -0
- package/src/design/components.ts +40 -26
- package/src/teach/fonts.ts +9 -19
|
@@ -4,6 +4,10 @@ description: Enforce universal testing standards and best practices
|
|
|
4
4
|
|
|
5
5
|
# Testing standards
|
|
6
6
|
|
|
7
|
+
## Before writing a test
|
|
8
|
+
|
|
9
|
+
- Load the `canon:test-craft` skill before choosing the layer for a new test, and report it rather than proceeding silently when the skill does not resolve.
|
|
10
|
+
|
|
7
11
|
## Test structure
|
|
8
12
|
|
|
9
13
|
- Structure tests using the Arrange, Act, Assert (AAA) pattern.
|
|
@@ -12,9 +16,7 @@ description: Enforce universal testing standards and best practices
|
|
|
12
16
|
|
|
13
17
|
## Test focus
|
|
14
18
|
|
|
15
|
-
- Test user-visible behavior rather than implementation details.
|
|
16
19
|
- Do not test private functions or internal state directly.
|
|
17
|
-
- Cover critical paths and edge cases.
|
|
18
20
|
- Do not target arbitrary coverage percentages.
|
|
19
21
|
|
|
20
22
|
## Organization and isolation
|
|
@@ -9,6 +9,10 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
# TypeScript/JavaScript testing tooling
|
|
11
11
|
|
|
12
|
+
## Layer
|
|
13
|
+
|
|
14
|
+
- Load the `canon:test-craft` skill to pick the layer a test belongs at before choosing the tooling below, and report it rather than proceeding silently when the skill does not resolve.
|
|
15
|
+
|
|
12
16
|
## Unit and integration
|
|
13
17
|
|
|
14
18
|
- Use Vitest for unit and integration tests.
|
|
@@ -8,6 +8,10 @@ paths:
|
|
|
8
8
|
|
|
9
9
|
# Python testing tooling
|
|
10
10
|
|
|
11
|
+
## Layer
|
|
12
|
+
|
|
13
|
+
- Load the `canon:test-craft` skill to pick the layer a test belongs at before choosing the tooling below, and report it rather than proceeding silently when the skill does not resolve.
|
|
14
|
+
|
|
11
15
|
## Framework
|
|
12
16
|
|
|
13
17
|
- Use `pytest` for all tests. Do not use `unittest.TestCase`.
|
package/package.json
CHANGED
package/src/claude/cases/misc.ts
CHANGED
|
@@ -54,6 +54,11 @@ export const MISC_CASES: readonly SkillCase[] = [
|
|
|
54
54
|
"I'm about to write the retry helper we settled on and nothing covers it yet, so get the failing case in first.",
|
|
55
55
|
expect: 'test-first',
|
|
56
56
|
},
|
|
57
|
+
{
|
|
58
|
+
prompt:
|
|
59
|
+
'The loading state already shipped. Should its test be an e2e test or a component one, and is the one I wrote any good?',
|
|
60
|
+
expect: 'test-craft',
|
|
61
|
+
},
|
|
57
62
|
{
|
|
58
63
|
prompt: 'Does our github about text still match what the readme says?',
|
|
59
64
|
expect: 'repo-metadata',
|
package/src/design/components.ts
CHANGED
|
@@ -225,11 +225,16 @@ const TEACH_CHROME: Component = {
|
|
|
225
225
|
'--teach-chrome',
|
|
226
226
|
'--teach-shadow',
|
|
227
227
|
'--color-teach-accent-bg',
|
|
228
|
+
'--type-body-family',
|
|
229
|
+
'--type-code-family',
|
|
230
|
+
'--t3',
|
|
231
|
+
'--t4',
|
|
232
|
+
'--t5',
|
|
228
233
|
],
|
|
229
234
|
rules: `:root {
|
|
230
|
-
--teach-sans:
|
|
231
|
-
--teach-hand: 'Virgil', '
|
|
232
|
-
--teach-mono:
|
|
235
|
+
--teach-sans: var(--type-body-family);
|
|
236
|
+
--teach-hand: 'Virgil', 'Excalifont', cursive;
|
|
237
|
+
--teach-mono: var(--type-code-family);
|
|
233
238
|
--teach-measure: 52rem;
|
|
234
239
|
--teach-chrome: 52rem;
|
|
235
240
|
--teach-mast-h: 4.4rem;
|
|
@@ -268,7 +273,7 @@ body {
|
|
|
268
273
|
background: var(--color-background);
|
|
269
274
|
color: var(--color-text-body);
|
|
270
275
|
font-family: var(--teach-sans);
|
|
271
|
-
font-size:
|
|
276
|
+
font-size: var(--t3);
|
|
272
277
|
line-height: 1.62;
|
|
273
278
|
-webkit-font-smoothing: antialiased;
|
|
274
279
|
}
|
|
@@ -297,7 +302,7 @@ main { max-width: calc(var(--teach-measure) + 3rem); margin: 0 auto; padding: 2.
|
|
|
297
302
|
justify-content: space-between;
|
|
298
303
|
align-items: center;
|
|
299
304
|
gap: 1rem;
|
|
300
|
-
font-size:
|
|
305
|
+
font-size: var(--t5);
|
|
301
306
|
color: var(--color-muted);
|
|
302
307
|
}
|
|
303
308
|
|
|
@@ -332,7 +337,7 @@ main { max-width: calc(var(--teach-measure) + 3rem); margin: 0 auto; padding: 2.
|
|
|
332
337
|
border-radius: 8px;
|
|
333
338
|
text-decoration: none;
|
|
334
339
|
color: var(--color-text-body);
|
|
335
|
-
font-size:
|
|
340
|
+
font-size: var(--t4);
|
|
336
341
|
font-weight: 600;
|
|
337
342
|
line-height: 1.3;
|
|
338
343
|
box-shadow: var(--teach-shadow);
|
|
@@ -370,14 +375,14 @@ main { max-width: calc(var(--teach-measure) + 3rem); margin: 0 auto; padding: 2.
|
|
|
370
375
|
value for a character even a decorative one. */
|
|
371
376
|
.crumb-sep {
|
|
372
377
|
color: var(--color-muted);
|
|
373
|
-
font-size:
|
|
378
|
+
font-size: var(--t4);
|
|
374
379
|
user-select: none;
|
|
375
380
|
}
|
|
376
381
|
|
|
377
382
|
/* One arrow, on the first segment, since that is the only one that goes up. */
|
|
378
383
|
.crumb-back {
|
|
379
384
|
margin-right: 0.3rem;
|
|
380
|
-
font-size:
|
|
385
|
+
font-size: var(--t4);
|
|
381
386
|
line-height: 1;
|
|
382
387
|
}
|
|
383
388
|
|
|
@@ -612,6 +617,9 @@ const TEACH_ARTICLE: Component = {
|
|
|
612
617
|
'--color-accent',
|
|
613
618
|
'--teach-hand',
|
|
614
619
|
'--teach-mono',
|
|
620
|
+
'--t4',
|
|
621
|
+
'--t5',
|
|
622
|
+
'--t6',
|
|
615
623
|
],
|
|
616
624
|
rules: `/* ---- Type ---- */
|
|
617
625
|
|
|
@@ -664,7 +672,7 @@ em { font-style: italic; }
|
|
|
664
672
|
font-weight: 700;
|
|
665
673
|
letter-spacing: 0.06em;
|
|
666
674
|
text-transform: uppercase;
|
|
667
|
-
font-size:
|
|
675
|
+
font-size: var(--t6);
|
|
668
676
|
margin-bottom: 0.2rem;
|
|
669
677
|
}
|
|
670
678
|
|
|
@@ -680,7 +688,7 @@ code {
|
|
|
680
688
|
|
|
681
689
|
pre {
|
|
682
690
|
font-family: var(--teach-mono);
|
|
683
|
-
font-size:
|
|
691
|
+
font-size: var(--t5);
|
|
684
692
|
line-height: 1.7;
|
|
685
693
|
background: var(--color-surface);
|
|
686
694
|
padding: 1.15rem 1.3rem;
|
|
@@ -745,12 +753,12 @@ tbody tr.mark td { background: var(--color-teach-accent-bg); }
|
|
|
745
753
|
}
|
|
746
754
|
|
|
747
755
|
.toc a:hover { background: var(--color-surface); }
|
|
748
|
-
.toc .num { font-family: var(--teach-mono); font-size:
|
|
756
|
+
.toc .num { font-family: var(--teach-mono); font-size: var(--t5); color: var(--color-accent); }
|
|
749
757
|
.toc b { font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.012em; }
|
|
750
758
|
|
|
751
759
|
.toc .blurb {
|
|
752
760
|
grid-column: 2;
|
|
753
|
-
font-size:
|
|
761
|
+
font-size: var(--t4);
|
|
754
762
|
line-height: 1.5;
|
|
755
763
|
color: var(--color-text-secondary);
|
|
756
764
|
margin-top: 0.1rem;
|
|
@@ -799,7 +807,7 @@ tbody tr.mark td { background: var(--color-teach-accent-bg); }
|
|
|
799
807
|
ol.succ {
|
|
800
808
|
margin: 0 0 2.5rem;
|
|
801
809
|
padding-left: 1.35rem;
|
|
802
|
-
font-size:
|
|
810
|
+
font-size: var(--t4);
|
|
803
811
|
line-height: 1.6;
|
|
804
812
|
color: var(--color-text-secondary);
|
|
805
813
|
}
|
|
@@ -846,13 +854,13 @@ ol.succ li { margin-bottom: 0.4rem; }
|
|
|
846
854
|
|
|
847
855
|
.road-n {
|
|
848
856
|
font-family: var(--teach-mono);
|
|
849
|
-
font-size:
|
|
857
|
+
font-size: var(--t5);
|
|
850
858
|
color: var(--color-accent);
|
|
851
859
|
}
|
|
852
860
|
|
|
853
861
|
.road-b { display: block; }
|
|
854
862
|
.road-b b { display: block; margin-bottom: 0.2rem; }
|
|
855
|
-
.road-b span { color: var(--color-text-secondary); font-size:
|
|
863
|
+
.road-b span { color: var(--color-text-secondary); font-size: var(--t4); line-height: 1.55; }
|
|
856
864
|
|
|
857
865
|
.road-t {
|
|
858
866
|
font-family: var(--teach-mono);
|
|
@@ -889,6 +897,8 @@ const TEACH_QUIZ: Component = {
|
|
|
889
897
|
'--teach-mono',
|
|
890
898
|
'--teach-shadow',
|
|
891
899
|
'--color-teach-accent-bg',
|
|
900
|
+
'--t4',
|
|
901
|
+
'--t5',
|
|
892
902
|
],
|
|
893
903
|
rules: `/* ---- Quiz ---- */
|
|
894
904
|
|
|
@@ -907,7 +917,7 @@ const TEACH_QUIZ: Component = {
|
|
|
907
917
|
margin-bottom: 0.45rem;
|
|
908
918
|
cursor: pointer;
|
|
909
919
|
font-family: var(--teach-sans);
|
|
910
|
-
font-size:
|
|
920
|
+
font-size: var(--t4);
|
|
911
921
|
background: transparent;
|
|
912
922
|
width: 100%;
|
|
913
923
|
text-align: left;
|
|
@@ -967,7 +977,7 @@ const TEACH_QUIZ: Component = {
|
|
|
967
977
|
|
|
968
978
|
.fb {
|
|
969
979
|
display: none;
|
|
970
|
-
font-size:
|
|
980
|
+
font-size: var(--t4);
|
|
971
981
|
line-height: 1.55;
|
|
972
982
|
color: var(--color-text-secondary);
|
|
973
983
|
background: var(--color-surface);
|
|
@@ -983,7 +993,7 @@ footer {
|
|
|
983
993
|
margin-top: 4rem;
|
|
984
994
|
padding-top: 1.4rem;
|
|
985
995
|
border-top: 1px solid var(--color-border);
|
|
986
|
-
font-size:
|
|
996
|
+
font-size: var(--t5);
|
|
987
997
|
line-height: 1.6;
|
|
988
998
|
color: var(--color-muted);
|
|
989
999
|
}`,
|
|
@@ -1004,6 +1014,8 @@ const TEACH_GLOSSARY: Component = {
|
|
|
1004
1014
|
'--color-accent',
|
|
1005
1015
|
'--teach-sans',
|
|
1006
1016
|
'--teach-mono',
|
|
1017
|
+
'--t4',
|
|
1018
|
+
'--t5',
|
|
1007
1019
|
],
|
|
1008
1020
|
rules: `/* ---- Glossary view, generated from the markdown source ---- */
|
|
1009
1021
|
|
|
@@ -1022,7 +1034,7 @@ h2 .count {
|
|
|
1022
1034
|
.filter {
|
|
1023
1035
|
width: 100%;
|
|
1024
1036
|
font-family: var(--teach-sans);
|
|
1025
|
-
font-size:
|
|
1037
|
+
font-size: var(--t4);
|
|
1026
1038
|
color: var(--color-text-body);
|
|
1027
1039
|
background: var(--color-background);
|
|
1028
1040
|
border: 1px solid var(--color-border);
|
|
@@ -1064,7 +1076,7 @@ h2 .count {
|
|
|
1064
1076
|
display: none;
|
|
1065
1077
|
padding: 1.2rem 0;
|
|
1066
1078
|
color: var(--color-muted);
|
|
1067
|
-
font-size:
|
|
1079
|
+
font-size: var(--t4);
|
|
1068
1080
|
}
|
|
1069
1081
|
|
|
1070
1082
|
.gloss.none .empty { display: block; }
|
|
@@ -1072,14 +1084,14 @@ h2 .count {
|
|
|
1072
1084
|
.gterm {
|
|
1073
1085
|
padding: 0.7rem 0;
|
|
1074
1086
|
border-bottom: 1px solid var(--color-border);
|
|
1075
|
-
font-size:
|
|
1087
|
+
font-size: var(--t4);
|
|
1076
1088
|
line-height: 1.55;
|
|
1077
1089
|
}
|
|
1078
1090
|
|
|
1079
1091
|
.gloss-group {
|
|
1080
1092
|
margin: 1.1rem 0 0.4rem;
|
|
1081
1093
|
font-family: var(--teach-sans);
|
|
1082
|
-
font-size:
|
|
1094
|
+
font-size: var(--t5);
|
|
1083
1095
|
font-weight: 600;
|
|
1084
1096
|
color: var(--color-muted);
|
|
1085
1097
|
text-transform: uppercase;
|
|
@@ -1101,7 +1113,7 @@ h2 .count {
|
|
|
1101
1113
|
ol.succ {
|
|
1102
1114
|
margin: 0 0 2.5rem;
|
|
1103
1115
|
padding-left: 1.35rem;
|
|
1104
|
-
font-size:
|
|
1116
|
+
font-size: var(--t4);
|
|
1105
1117
|
line-height: 1.6;
|
|
1106
1118
|
color: var(--color-text-secondary);
|
|
1107
1119
|
}
|
|
@@ -1137,6 +1149,7 @@ const TEACH_OUTLINE: Component = {
|
|
|
1137
1149
|
'--teach-sans',
|
|
1138
1150
|
'--teach-measure',
|
|
1139
1151
|
'--teach-mast-h',
|
|
1152
|
+
'--t5',
|
|
1140
1153
|
],
|
|
1141
1154
|
rules: `/* ---- In-lesson outline, in the gutter the measure leaves over ---- */
|
|
1142
1155
|
|
|
@@ -1151,7 +1164,7 @@ const TEACH_OUTLINE: Component = {
|
|
|
1151
1164
|
width: calc(13rem + 8px);
|
|
1152
1165
|
max-height: calc(100vh - var(--teach-mast-h) - 4rem);
|
|
1153
1166
|
overflow-y: auto;
|
|
1154
|
-
font-size:
|
|
1167
|
+
font-size: var(--t5);
|
|
1155
1168
|
line-height: 1.45;
|
|
1156
1169
|
}
|
|
1157
1170
|
|
|
@@ -1218,12 +1231,13 @@ const TEACH_REFERENCES: Component = {
|
|
|
1218
1231
|
'--color-accent',
|
|
1219
1232
|
'--teach-mono',
|
|
1220
1233
|
'--color-teach-accent-bg',
|
|
1234
|
+
'--t5',
|
|
1221
1235
|
],
|
|
1222
1236
|
rules: `footer {
|
|
1223
1237
|
margin-top: 4rem;
|
|
1224
1238
|
padding-top: 1.4rem;
|
|
1225
1239
|
border-top: 1px solid var(--color-border);
|
|
1226
|
-
font-size:
|
|
1240
|
+
font-size: var(--t5);
|
|
1227
1241
|
line-height: 1.6;
|
|
1228
1242
|
color: var(--color-muted);
|
|
1229
1243
|
}
|
|
@@ -1252,7 +1266,7 @@ ol.refs {
|
|
|
1252
1266
|
counter-reset: r;
|
|
1253
1267
|
padding: 0;
|
|
1254
1268
|
margin: 0.9rem 0 1.1rem;
|
|
1255
|
-
font-size:
|
|
1269
|
+
font-size: var(--t5);
|
|
1256
1270
|
line-height: 1.55;
|
|
1257
1271
|
}
|
|
1258
1272
|
|