@thebassclef/lite 0.1.0 → 0.1.2
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/dist/cli.cjs +2 -0
- package/dist/cli.js +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/substrate/.bassclef/lite-manifest.json +999 -92
- package/substrate/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
- package/substrate/.claude/hooks/longrun-prep-compounding-sequence-check.sh +492 -0
- package/substrate/.claude/hooks/pre-commit-gate.sh +1 -2
- package/substrate/.claude/hooks/turn-prose-kiss-check.sh +30 -1
- package/substrate/.claude/luminaries/glenford-myers.md +230 -0
- package/substrate/.claude/luminaries/hunt-thomas.md +115 -0
- package/substrate/.claude/luminaries/hyrum-wright.md +94 -0
- package/substrate/.claude/luminaries/michael-feathers.md +2 -2
- package/substrate/.claude/luminaries/tony-hoare.md +170 -0
- package/substrate/.claude/luminaries/vaughn-vernon.md +50 -0
- package/substrate/.claude/luminaries/w-edwards-deming.md +158 -0
- package/substrate/.claude/rules/accessor-library-discipline.md +138 -0
- package/substrate/.claude/rules/adr-discipline.md +120 -0
- package/substrate/.claude/rules/api-conventions.md +125 -0
- package/substrate/.claude/rules/bootstrap-pair-discipline.md +141 -0
- package/substrate/.claude/rules/cold-adopter-harness-discipline.md +129 -0
- package/substrate/.claude/rules/compounding-axis-fresh-analysis.md +188 -0
- package/substrate/.claude/rules/compounding-sequence-fresh-analysis.md +188 -0
- package/substrate/.claude/rules/defensive-bash.md +68 -0
- package/substrate/.claude/rules/deferred-actions.md +233 -0
- package/substrate/.claude/rules/github-issue-flash-tweet.md +156 -0
- package/substrate/.claude/rules/hook-wire-on-author.md +103 -0
- package/substrate/.claude/rules/iteration-bet-brief-completeness.md +54 -0
- package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +3 -3
- package/substrate/.claude/rules/longrun-prep-plan-doc-compression.md +89 -0
- package/substrate/.claude/rules/loop-discipline.md +81 -0
- package/substrate/.claude/rules/manual-prod-approval.md +100 -0
- package/substrate/.claude/rules/marker-enrichment-discipline.md +99 -0
- package/substrate/.claude/rules/mobile-ephemeral-session.md +109 -0
- package/substrate/.claude/rules/new-dependency-check.md +51 -0
- package/substrate/.claude/rules/option-label-discipline.md +108 -0
- package/substrate/.claude/rules/pattern-annotation.md +100 -0
- package/substrate/.claude/rules/plain-english-discipline.md +11 -9
- package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +211 -0
- package/substrate/.claude/rules/pr-title-shape.md +161 -0
- package/substrate/.claude/rules/prototype-workflow.md +65 -0
- package/substrate/.claude/rules/reserved-skill-names.md +123 -0
- package/substrate/.claude/rules/schema-management.md +49 -0
- package/substrate/.claude/rules/security.md +37 -0
- package/substrate/.claude/rules/skill-composition-declarations.md +124 -0
- package/substrate/.claude/rules/skill-description-clarity.md +247 -0
- package/substrate/.claude/rules/skill-procedure-step-list.md +137 -0
- package/substrate/.claude/rules/stuck-signal-diagnostic.md +140 -0
- package/substrate/.claude/rules/substrate-config-schema.md +98 -0
- package/substrate/.claude/rules/test-list-discipline.md +175 -0
- package/substrate/.claude/rules/test-sufficiency.md +210 -0
- package/substrate/.claude/rules/testing-tier-config.md +145 -0
- package/substrate/.claude/rules/testing.md +38 -0
- package/substrate/.claude/rules/turn-estimate-grounding.md +134 -0
- package/substrate/.claude/rules/visual-hierarchy.md +437 -0
- package/substrate/.claude/rules/we-dont-break-adopters.md +126 -0
- package/substrate/.claude/rules/wu-sequencing-compounds.md +145 -0
- package/substrate/.claude/skills/build/SKILL.md +1 -1
- package/substrate/.claude/skills/chronicle/SKILL.md +55 -0
- package/substrate/.claude/skills/clean-artifacts/SKILL.md +249 -0
- package/substrate/.claude/skills/decompose/SKILL.md +1 -1
- package/substrate/.claude/skills/diagnose/SKILL.md +1 -1
- package/substrate/.claude/skills/feynman/SKILL.md +90 -0
- package/substrate/.claude/skills/howdoi/SKILL.md +1 -1
- package/substrate/.claude/skills/ia-model/SKILL.md +1 -1
- package/substrate/.claude/skills/interaction-design/SKILL.md +1 -1
- package/substrate/.claude/skills/interpret-input/SKILL.md +8 -8
- package/substrate/.claude/skills/journal/SKILL.md +209 -0
- package/substrate/.claude/skills/kiss/SKILL.md +1 -1
- package/substrate/.claude/skills/launch/SKILL.md +14 -23
- package/substrate/.claude/skills/lean-canvas/SKILL.md +1 -1
- package/substrate/.claude/skills/longrun/SKILL.md +45 -8
- package/substrate/.claude/skills/luminary/SKILL.md +1 -1
- package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +1 -1
- package/substrate/.claude/skills/onboard-repo/SKILL.md +143 -709
- package/substrate/.claude/skills/pattern-review/SKILL.md +1 -1
- package/substrate/.claude/skills/personas/SKILL.md +5 -5
- package/substrate/.claude/skills/promote/SKILL.md +1 -1
- package/substrate/.claude/skills/requirement/SKILL.md +1 -1
- package/substrate/.claude/skills/retro/SKILL.md +1 -1
- package/substrate/.claude/skills/riff/SKILL.md +1 -1
- package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +1 -1
- package/substrate/.claude/skills/session-end/SKILL.md +1 -1
- package/substrate/.claude/skills/session-log/SKILL.md +3 -3
- package/substrate/.claude/skills/skills/SKILL.md +1 -1
- package/substrate/.claude/skills/spec/SKILL.md +1 -1
- package/substrate/.claude/skills/sprint/SKILL.md +1 -1
- package/substrate/.claude/skills/stage/SKILL.md +1 -1
- package/substrate/.claude/skills/state-a-problem/SKILL.md +1 -1
- package/substrate/.claude/skills/temperance/SKILL.md +1 -1
- package/substrate/.claude/skills/use-case/SKILL.md +1 -1
- package/substrate/.claude/skills/user-stories/SKILL.md +1 -1
- package/substrate/.claude/skills/value-prop/SKILL.md +1 -1
- package/substrate/.claude/skills/verify/SKILL.md +1 -1
- package/substrate/.claude/skills/visual-review/SKILL.md +503 -0
- package/substrate/.claude/skills/whats-the-plan/SKILL.md +202 -0
- package/substrate/.claude/skills/whereami/SKILL.md +2 -2
- package/substrate/CONTRIBUTING.md +1 -1
- package/substrate/README.md +5 -5
- package/substrate/lib/prose-scan-boundary.sh +171 -0
- package/substrate/lib/tier-check.sh +50 -1
- package/substrate/lib/tier-dependency-audit.sh +159 -4
- package/substrate/presence/install/bassclef-sync.template.sh +1 -1
- package/substrate/scripts/generate-lite-manifest.sh +21 -5
- package/substrate/standards/adr-template.md +86 -0
- package/substrate/standards/api-conventions/nextjs.md +84 -0
- package/substrate/standards/artifact-composition.md +209 -0
- package/substrate/standards/bash-hook-safety.md +246 -0
- package/substrate/standards/branch-stacking.md +408 -0
- package/substrate/standards/code-safety-principles.md +176 -0
- package/substrate/standards/composer-prerequisites.md +155 -0
- package/substrate/standards/dependency-discipline/cargo.md +39 -0
- package/substrate/standards/dependency-discipline/gem.md +43 -0
- package/substrate/standards/dependency-discipline/go-mod.md +41 -0
- package/substrate/standards/dependency-discipline/npm.md +42 -0
- package/substrate/standards/dependency-discipline/pip.md +42 -0
- package/substrate/standards/deployment-topology/ec2-tailscale.md +225 -0
- package/substrate/standards/deployment-topology.md +69 -0
- package/substrate/standards/docs-sync-allowlist.md +4 -4
- package/substrate/standards/domain-and-dns.md +145 -0
- package/substrate/standards/frontend-stack.md +67 -0
- package/substrate/standards/frontmatter-schema.md +154 -0
- package/substrate/standards/hook-injection-discipline.md +202 -0
- package/substrate/standards/hook-install-class.md +215 -0
- package/substrate/standards/input-handler-interface.md +152 -0
- package/substrate/standards/lite-manifest-schema-changes.md +60 -0
- package/substrate/standards/luminary-matching.md +105 -0
- package/substrate/standards/migration-discipline/active-record.md +50 -0
- package/substrate/standards/migration-discipline/alembic.md +43 -0
- package/substrate/standards/migration-discipline/gorm.md +50 -0
- package/substrate/standards/migration-discipline/prisma.md +53 -0
- package/substrate/standards/migration-discipline/sqlalchemy.md +51 -0
- package/substrate/standards/mobile-ephemeral-session.md +167 -0
- package/substrate/standards/model-routing-discipline.md +160 -0
- package/substrate/standards/persona-schema.md +229 -0
- package/substrate/standards/pluggable-luminaries.md +323 -0
- package/substrate/standards/pr-body-discipline.md +115 -0
- package/substrate/standards/preview-state-schema.md +189 -0
- package/substrate/standards/reserved-skill-names.md +120 -0
- package/substrate/standards/scannable-multi-option-output.md +261 -0
- package/substrate/standards/sdlc-gates/typescript.md +57 -0
- package/substrate/standards/session-board.md +256 -0
- package/substrate/standards/state-spine-contract.md +255 -0
- package/substrate/standards/steering-hints/kiss-words.md +11 -0
- package/substrate/standards/substrate-config-schema.md +267 -0
- package/substrate/standards/tier-dependency-analysis.md +1 -1
- package/substrate/standards/tier-tag-schema.md +1 -1
- package/substrate/standards/two-layer-config.md +99 -0
- package/substrate/standards/use-case-format.md +292 -0
- package/substrate/standards/user-story-invest.md +268 -0
- package/substrate/standards/velocity-and-appetite.md +229 -0
- package/substrate/standards/voice-input-pattern.md +119 -0
- package/substrate/standards/worktree-management.md +211 -0
- package/substrate/templates/chronicle-template.md +75 -0
- package/substrate/templates/memory-proposal-template.md +77 -0
- package/substrate/templates/persona-template.md +200 -0
- package/substrate/templates/pr-faq.md +45 -0
- package/substrate/templates/secret-rotation-template.md +162 -0
- package/substrate/templates/spec-template.md +131 -0
- package/substrate/templates/use-case-template.md +194 -0
- package/substrate/templates/user-story-template.md +107 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Glenford J. Myers
|
|
4
|
+
slug: glenford-myers
|
|
5
|
+
claimed_by: [reviewer, builder]
|
|
6
|
+
referenced_by_skills: [verify, pattern-review]
|
|
7
|
+
primary_domain: testing
|
|
8
|
+
depth: full
|
|
9
|
+
sources:
|
|
10
|
+
- type: book
|
|
11
|
+
title: "The Art of Software Testing"
|
|
12
|
+
authors: ["Glenford J. Myers"]
|
|
13
|
+
year: 1979
|
|
14
|
+
edition: "1st (3rd ed 2011 with Sandler & Badgett)"
|
|
15
|
+
isbn: "9780471043287"
|
|
16
|
+
methodology_covered:
|
|
17
|
+
- "Decision coverage — every branch (if/else) is exercised by at least one test"
|
|
18
|
+
- "Condition coverage — every boolean sub-expression is independently exercised true and false"
|
|
19
|
+
- "Boundary value analysis — tests target the edges of input domains (min, max, off-by-one)"
|
|
20
|
+
- "Equivalence partitioning — divide input space into classes where one representative tests the whole class"
|
|
21
|
+
- "Error guessing — heuristic enumeration of likely failure modes"
|
|
22
|
+
- type: book
|
|
23
|
+
title: "Reliable Software through Composite Design"
|
|
24
|
+
authors: ["Glenford J. Myers"]
|
|
25
|
+
year: 1975
|
|
26
|
+
methodology_covered:
|
|
27
|
+
- "Cohesion / coupling — module-design quality metrics that pre-date Constantine + Yourdon's structured-design framing"
|
|
28
|
+
verification_status: verified
|
|
29
|
+
description: "\"The purpose of testing is to find errors, not to demonstrate the absence of errors.\""
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# Glenford J. Myers
|
|
33
|
+
|
|
34
|
+
## Signature
|
|
35
|
+
|
|
36
|
+
*"The purpose of testing is to find errors, not to demonstrate the absence of errors."*
|
|
37
|
+
|
|
38
|
+
IBM systems researcher (1960s-80s). Author of **The Art of Software Testing** (1979) — the foundational text that named decision coverage, condition coverage, boundary value analysis, and equivalence partitioning as systematic disciplines. Pairs with Beck (TDD cycle), Hoare (contract testing), and Ousterhout (design judgment): Beck owns the rhythm, Hoare owns the contract semantics, Ousterhout owns the shape, Myers owns the taxonomy of what-to-cover.
|
|
39
|
+
|
|
40
|
+
## Core methods
|
|
41
|
+
|
|
42
|
+
- **Decision coverage** — Every branch in the source has at least one test that exercises it. A function with three if/else paths needs at least three tests. The discipline maps directly to grep-count: count branches in source; count test cases; the second number is at least the first.
|
|
43
|
+
|
|
44
|
+
INSTEAD of one test that "covers the happy path": one test per branch. The cost is small at write-time and compounds as the source grows.
|
|
45
|
+
|
|
46
|
+
- **Condition coverage** — Every boolean sub-expression in a compound condition is independently exercised true AND false. A condition `(a && b) || c` has three sub-expressions; sufficient coverage exercises each one in both states. Decision coverage alone misses this: `(a && b)` can be false because `a` is false OR because `b` is false; the two cases hit different bugs.
|
|
47
|
+
|
|
48
|
+
INSTEAD of one true/false pair per compound condition: one true/false pair per sub-expression. Especially important for hook tool-matchers that combine path-globs with environment checks.
|
|
49
|
+
|
|
50
|
+
- **Boundary value analysis** — Tests target the edges of input domains, not the middles. A function accepting integers `1..100` is tested at 1, 100, 0, 101, and one mid-range value. The bugs that ship are almost always at edges: off-by-one, empty input, max input, just-past-max input.
|
|
51
|
+
|
|
52
|
+
INSTEAD of one test at a representative middle value: at least four tests at min, max, just-below-min, just-above-max. Middle values catch zero bugs that boundary values miss; boundary values catch many bugs that middle values miss.
|
|
53
|
+
|
|
54
|
+
- **Equivalence partitioning** — Divide input space into classes where one representative tests the whole class. Inputs `2, 5, 17, 42` are in the same "positive small integer" class; one test of them tests the class. Inputs `-1, 0, 1.5, "abc"` represent different classes (negative, zero, non-integer, non-numeric); each class owes a test.
|
|
55
|
+
|
|
56
|
+
INSTEAD of testing one input per literal value: identify the classes; test one representative per class plus the boundaries between classes. Reduces redundant tests; surfaces unconsidered classes.
|
|
57
|
+
|
|
58
|
+
- **Error guessing** — Heuristic enumeration of likely failure modes based on the function's shape and history. Not algorithmic; expert-judgment-driven. Augments the systematic categories with experience-based pattern recognition.
|
|
59
|
+
|
|
60
|
+
INSTEAD of treating error guessing as inferior to systematic categories: use it as the additive layer that catches what taxonomy misses. The systematic categories are the floor; error guessing is the ceiling.
|
|
61
|
+
|
|
62
|
+
## When to channel this luminary
|
|
63
|
+
|
|
64
|
+
When the primary risk is sufficiency rather than rhythm. Myers dominates at test-authoring moments where the question is "I have a test that passes — is the test enough?" Specifically: per-hook test suites, state-spine accessor tests, API route validation tests, anywhere the function takes structured input and produces structured output with branches.
|
|
65
|
+
|
|
66
|
+
Pair with Beck (TDD rhythm — Myers tells you what to write tests for; Beck tells you when to write them), Hoare (contract semantics — Myers categories operationalize Hoare's `(P, Q)` pair enumeration), Ousterhout (deep modules earn easier Myers coverage; shallow modules decay it).
|
|
67
|
+
|
|
68
|
+
Skip Myers when: the test is a smoke test (bassclef/'smoke-test' skill scope), the work is a one-off script with no caller, or the relevant risk is design-quality rather than test-completeness (route to Ousterhout). Myers's discipline costs ~3x the write-time of a single happy-path test; apply where the function's correctness has compounding downstream impact.
|
|
69
|
+
|
|
70
|
+
INSTEAD of citing Myers for test rhythm, refactoring tactics, or design quality: route to Beck, Fowler, and Ousterhout respectively.
|
|
71
|
+
|
|
72
|
+
## Stack translation
|
|
73
|
+
|
|
74
|
+
In bassclef's bash hook + state-spine substrate:
|
|
75
|
+
|
|
76
|
+
- **Decision coverage applied to hook source** — Run `grep -cE '^\s*(if|elif|else|case)' <hook>.sh` to count branches. The test file's test-list owes at least that many `[x]` lines. For `auto-save-idle.sh` with 4 branches (no-changes / lock-present / defer-present / proceed), the test file owes 4 tests minimum.
|
|
77
|
+
- **Condition coverage applied to compound `[ ... ]` tests** — A bash condition `[ -f LOCK -a AGE -lt TTL ]` has two sub-conditions. Tests must exercise: LOCK absent + AGE doesn't matter; LOCK present + AGE within TTL; LOCK present + AGE beyond TTL. Three cases for two sub-conditions; the `[ -a ... -a ... ]` compound earns the multi-case treatment.
|
|
78
|
+
- **Boundary value analysis applied to numeric inputs** — For hooks with TTL / age / count thresholds: test exact threshold, one-below, one-above. For `auto-save-idle.sh` with `IDLE_THRESHOLD=300` (seconds): test AGE=299, AGE=300, AGE=301. Off-by-one bugs surface here.
|
|
79
|
+
- **Equivalence partitioning applied to stdin / env-var shapes** — Hooks discriminate on `tool_name` (Bash | Edit | Write | etc), `file_path` glob matches, env-var presence. Each discriminator's value space partitions into classes; one test per class is the Myers minimum.
|
|
80
|
+
- **Error guessing applied to bassclef-specific failure modes** — Experience accumulated from prior incidents: marker file unwritable (sandbox teardown); jq missing on alpine container; trace-helper.sh permission denied; concurrent hook invocations racing on the same marker. Each becomes one additional test that taxonomy alone would miss.
|
|
81
|
+
|
|
82
|
+
In Next.js + TypeScript + vitest adopter stacks:
|
|
83
|
+
|
|
84
|
+
- **Decision coverage in vitest** — `it.each` table-driven tests; one row per source branch
|
|
85
|
+
- **Condition coverage for compound predicates** — `if (user.isAdmin && tenant.active)` owes both true/false variants for each sub-predicate
|
|
86
|
+
- **Boundary value for pagination / limits** — page=0, page=1, page=MAX_PAGE, page=MAX_PAGE+1
|
|
87
|
+
- **Equivalence partitioning for Zod input parsing** — one representative valid input per schema variant; one representative invalid per error class
|
|
88
|
+
- **Error guessing for adopter-stack failures** — token-expired mid-request; rate-limit hit at the wrong tenant boundary; cache stampede on cold start
|
|
89
|
+
|
|
90
|
+
## Anti-patterns it prevents
|
|
91
|
+
|
|
92
|
+
- **"Happy path only"** — A single test that exercises the success case while every error branch is untested. Tier 0 hook (bassclef#1037) passes because a test exists; Myers's discipline fails because decision coverage is 1/N where N > 1.
|
|
93
|
+
|
|
94
|
+
INSTEAD: count branches; write one test per branch in the same commit. The marginal cost per test is small; the marginal cost of a shipped error-branch bug is large.
|
|
95
|
+
|
|
96
|
+
- **"All branches but no boundary"** — Decision coverage achieved (each branch has a test) but every test uses mid-range input. Off-by-one bugs at branch boundaries ship to production.
|
|
97
|
+
|
|
98
|
+
INSTEAD: for any test with a numeric / string-length / count input, add the off-by-one neighbors as additional test cases. Three cases (mid, edge, just-past-edge) per branch is the floor.
|
|
99
|
+
|
|
100
|
+
- **"Boundary but no equivalence"** — Tests at edges but redundant testing of mid-range values from the same class (e.g., 50 different positive-integer tests; zero negative-integer tests).
|
|
101
|
+
|
|
102
|
+
INSTEAD: partition the input space into classes before writing tests; pick one representative per class; the redundancy savings fund the edge-case coverage.
|
|
103
|
+
|
|
104
|
+
- **"Equivalence but no error guessing"** — Formal Myers categories covered but experience-based failure modes ignored. The test suite is taxonomy-complete but production-incomplete.
|
|
105
|
+
|
|
106
|
+
INSTEAD: after applying the four systematic categories, ask "what could go wrong that taxonomy missed?" and add tests for each. The answer comes from incident history (chronicles), monitoring (alerts), and operator pattern recognition.
|
|
107
|
+
|
|
108
|
+
- **"Tautological tests"** — Assertions that mirror the implementation rather than the intent. `assert(x === f(x))` where f is the function under test asserts implementation, not behavior. The test passes regardless of whether `f` is correct.
|
|
109
|
+
|
|
110
|
+
INSTEAD: assert the behavior the caller depends on, expressed in terms the caller would use. For a sorter, assert "result is sorted ascending" not "result equals sort(input)". The first is a property; the second is implementation-shaped.
|
|
111
|
+
|
|
112
|
+
- **"Coverage-percentage gaming"** — Driving the coverage tool's percentage up by adding tests that exercise lines without exercising decisions. Myers's discipline rejects line coverage as the metric.
|
|
113
|
+
|
|
114
|
+
INSTEAD: decision coverage (every branch taken) + condition coverage (every sub-expression true and false) + boundary value (edges of input domains) are the essential metrics. Line coverage is a lagging indicator at best.
|
|
115
|
+
|
|
116
|
+
## Worked example
|
|
117
|
+
|
|
118
|
+
Tightening bassclef's `pre-commit-gate.sh` test under Myers's discipline:
|
|
119
|
+
|
|
120
|
+
Step 1 — Decision coverage analysis (grep + count):
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
$ grep -cE '^\s*(if|elif|else|case|\|\|)' .claude/hooks/pre-commit-gate.sh
|
|
124
|
+
14
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
14 decision points. Minimum 14 tests for decision coverage. Existing test file (allowlisted-pre-hardening) has 3 tests. Coverage = 3/14 = 21%. Failing.
|
|
128
|
+
|
|
129
|
+
Step 2 — Condition coverage analysis:
|
|
130
|
+
|
|
131
|
+
Find compound conditions:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
$ grep -nE '\[\s+.*-(a|o)\s+.*\]|&&|\|\|' .claude/hooks/pre-commit-gate.sh
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Each compound condition with `-a` / `-o` / `&&` / `||` owes one true/false per sub-expression. If 4 compound conditions average 2 sub-expressions each, that's 8 additional test variants beyond decision coverage.
|
|
138
|
+
|
|
139
|
+
Step 3 — Boundary value analysis:
|
|
140
|
+
|
|
141
|
+
Identify numeric / string-length thresholds in the hook:
|
|
142
|
+
- Marker file age: write age=now, age=24h-1s, age=24h+1s tests
|
|
143
|
+
- Branch-name length: 0 chars, 1 char, max-githook-supports, max+1
|
|
144
|
+
- Diff line count if any: 0, 1, MAX, MAX+1
|
|
145
|
+
|
|
146
|
+
Each threshold = 4 test variants.
|
|
147
|
+
|
|
148
|
+
Step 4 — Equivalence partitioning:
|
|
149
|
+
|
|
150
|
+
Discriminator: `tool_name` matcher
|
|
151
|
+
- Class 1: Edit (matched, fires)
|
|
152
|
+
- Class 2: Write (matched, fires)
|
|
153
|
+
- Class 3: MultiEdit (matched, fires)
|
|
154
|
+
- Class 4: Bash (not matched, pass-through)
|
|
155
|
+
- Class 5: NotebookEdit (not matched, pass-through)
|
|
156
|
+
- Class 6: malformed JSON stdin (error path)
|
|
157
|
+
|
|
158
|
+
6 representatives = 6 test cases for this discriminator alone.
|
|
159
|
+
|
|
160
|
+
Step 5 — Error guessing:
|
|
161
|
+
|
|
162
|
+
From bassclef incident history (chronicles + memory):
|
|
163
|
+
- marker directory missing entirely (fresh-clone scenario)
|
|
164
|
+
- trace-helper.sh exits non-zero (broken log endpoint)
|
|
165
|
+
- git binary version skew (BSD vs GNU date — caught bassclef#1085 yesterday)
|
|
166
|
+
- Concurrent hook invocations (two PreToolUse fires on overlapping Edit calls)
|
|
167
|
+
|
|
168
|
+
4 additional test cases from experience.
|
|
169
|
+
|
|
170
|
+
Step 6 — Test list assembled:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# test-list:
|
|
174
|
+
# Decision coverage (14 tests)
|
|
175
|
+
# [x] Branch 1: no marker file, fix/ branch → BLOCKED
|
|
176
|
+
# [x] Branch 2: temperance marker present, feature/ branch → pass
|
|
177
|
+
# [ ] Branch 3: stacked manifest declares branch → suppress
|
|
178
|
+
# ... (11 more decision-coverage entries)
|
|
179
|
+
# Condition coverage (8 additional)
|
|
180
|
+
# [ ] Compound: marker present AND mtime within 24h
|
|
181
|
+
# [ ] Compound: marker present AND mtime older than 24h
|
|
182
|
+
# ... (6 more)
|
|
183
|
+
# Boundary value (12 additional)
|
|
184
|
+
# [ ] Marker mtime = now
|
|
185
|
+
# [ ] Marker mtime = exactly 24h ago
|
|
186
|
+
# [ ] Marker mtime = 24h - 1s ago
|
|
187
|
+
# [ ] Marker mtime = 24h + 1s ago
|
|
188
|
+
# ... (8 more)
|
|
189
|
+
# Equivalence partitioning (6)
|
|
190
|
+
# [ ] tool_name = Edit
|
|
191
|
+
# [ ] tool_name = Write
|
|
192
|
+
# [ ] tool_name = MultiEdit
|
|
193
|
+
# [ ] tool_name = Bash (pass-through)
|
|
194
|
+
# [ ] tool_name = NotebookEdit (pass-through)
|
|
195
|
+
# [ ] stdin malformed JSON
|
|
196
|
+
# Error guessing (4)
|
|
197
|
+
# [ ] marker directory missing entirely
|
|
198
|
+
# [ ] trace-helper.sh exits non-zero
|
|
199
|
+
# [ ] git binary BSD vs GNU date skew
|
|
200
|
+
# [ ] concurrent PreToolUse fires
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
44 test cases for one hook. That sounds like a lot — until you remember pre-commit-gate.sh is essential for every commit in every consumer repo. The marginal cost of one hidden bug at this layer is multiplied by every adopter session.
|
|
204
|
+
|
|
205
|
+
What this discipline catches that lazy testing misses: the BSD-vs-GNU date skew that bit bassclef#1085 yesterday morning. Decision coverage alone would miss it because both code paths use the same date-formatting function. Error-guessing from prior incidents (the "what's bit us before" lens) IS the category that catches it.
|
|
206
|
+
|
|
207
|
+
## Sources
|
|
208
|
+
|
|
209
|
+
- *The Art of Software Testing* — Myers, Wiley (1979); 3rd ed 2011 with Sandler & Badgett, ISBN 9780471043287
|
|
210
|
+
- *Reliable Software through Composite Design* — Myers (1975)
|
|
211
|
+
- ACM Digital Library entry for 1979 first edition
|
|
212
|
+
- Cross-citation in Kaner, C. — *Testing Computer Software* (Wiley, 1993) crediting Myers as the systematic-testing forebear
|
|
213
|
+
|
|
214
|
+
## Related luminaries
|
|
215
|
+
|
|
216
|
+
- **Kent Beck** — TDD rhythm produces tests; Myers categories tell you whether the tests are enough. Tier 0 mtime enforcement (bassclef#1037) plus test-list discipline (bassclef#1090) plus Myers coverage taxonomy = the full TDD discipline bassclef operationalizes.
|
|
217
|
+
- **Tony Hoare / Bertrand Meyer** — Contract-driven testing (precondition/postcondition/invariant) is a sub-shape of Myers's taxonomy applied at the API boundary. Hoare asks WHAT the contract is; Myers asks WHICH categories of input exercise the contract.
|
|
218
|
+
- **John Ousterhout** — Deep modules with small interfaces are easier to fully cover under Myers categories; shallow modules expose so much surface that coverage decays. Myers's discipline implicitly rewards Ousterhout's design quality.
|
|
219
|
+
- **Edsger Dijkstra** — Famously argued "testing shows the presence, not the absence, of bugs" — the counterweight that says even Myers-complete suites do not prove correctness in the formal sense. Read together: Myers operationalizes test-as-bug-discovery; Dijkstra reminds us proof is a different discipline.
|
|
220
|
+
- **James Bach / Cem Kaner** (exploratory testing successors) — Modern testing heuristics built on Myers's foundation. Bassclef may add their luminaries in a future wave if exploratory testing earns a skill citation.
|
|
221
|
+
|
|
222
|
+
## Verification
|
|
223
|
+
|
|
224
|
+
Myers's authorship of *The Art of Software Testing* (1979) and his coining of the coverage taxonomy is verified via:
|
|
225
|
+
|
|
226
|
+
1. ACM Digital Library entry for the 1979 first edition (ISBN 9780471043287)
|
|
227
|
+
2. Wiley's listing of the 3rd edition (2011) with Sandler & Badgett
|
|
228
|
+
3. Cross-citation in Kaner's *Testing Computer Software* (1993) crediting Myers as the systematic-testing forebear
|
|
229
|
+
|
|
230
|
+
Per bassclef#867 anchor-luminary verification: name + dates + text title + taxonomy attribution confirmed from authoritative sources.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Hunt & Thomas (Pragmatic Programmers)
|
|
4
|
+
slug: hunt-thomas
|
|
5
|
+
claimed_by: [builder, reviewer]
|
|
6
|
+
referenced_by_skills: []
|
|
7
|
+
primary_domain: engineering
|
|
8
|
+
depth: full
|
|
9
|
+
solves_problems_brownfield:
|
|
10
|
+
- "Same logic duplicated in three places; any fix requires finding all three"
|
|
11
|
+
- "A change in one module causes unexpected breakage in an unrelated module — tight coupling masked as shared code"
|
|
12
|
+
- "Code written by trial-and-error with no clear intent; passing tests but nobody knows why"
|
|
13
|
+
- "Developers fear changing old code because they can't tell what will break"
|
|
14
|
+
solves_problems_greenfield:
|
|
15
|
+
- "Building a system where every piece of knowledge lives in exactly one place"
|
|
16
|
+
- "Designing modules that can be changed independently without ripple effects"
|
|
17
|
+
- "Starting a new codebase where developer discipline must prevent rot from day one"
|
|
18
|
+
- "Choosing which parts of a feature to prototype as throwaway vs which to keep as tracer bullets"
|
|
19
|
+
anti_patterns:
|
|
20
|
+
- "Large deployed monoliths where DRY and orthogonality would require full rewrites — Feathers seam-first applies before this"
|
|
21
|
+
- "Spec-driven contexts requiring precise fidelity to a fixed requirement"
|
|
22
|
+
- "Teams in regulatory environments where prototype-vs-production distinction must be documented formally"
|
|
23
|
+
sources:
|
|
24
|
+
- type: book
|
|
25
|
+
title: "The Pragmatic Programmer: From Journeyman to Master"
|
|
26
|
+
authors: ["Andrew Hunt", "David Thomas"]
|
|
27
|
+
year: 1999
|
|
28
|
+
url: "https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/"
|
|
29
|
+
isbn: "9780135957059"
|
|
30
|
+
methodology_covered:
|
|
31
|
+
- "DRY (single knowledge source) — Every piece of knowledge must have one, unambiguous, authoritative representation"
|
|
32
|
+
- "Orthogonality — Two components are orthogonal if changing one requires no change in the other"
|
|
33
|
+
- "Tracer bullets — build a thin, working end-to-end path first"
|
|
34
|
+
- "Broken windows — small decay normalizes fast"
|
|
35
|
+
- type: book
|
|
36
|
+
title: "The Pragmatic Programmer: 20th Anniversary Edition"
|
|
37
|
+
authors: ["Andrew Hunt", "David Thomas"]
|
|
38
|
+
year: 2019
|
|
39
|
+
url: "https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/"
|
|
40
|
+
isbn: "9780135957059"
|
|
41
|
+
methodology_covered:
|
|
42
|
+
- "DRY (single knowledge source)"
|
|
43
|
+
- "Orthogonality"
|
|
44
|
+
- "Tracer bullets"
|
|
45
|
+
- "Broken windows"
|
|
46
|
+
- type: blog_post
|
|
47
|
+
title: "Pragmatic Bookshelf publisher site"
|
|
48
|
+
authors: ["David Thomas"]
|
|
49
|
+
year: 1999
|
|
50
|
+
url: "https://pragprog.com/"
|
|
51
|
+
methodology_covered:
|
|
52
|
+
- "Primary publisher site for all Pragmatic Programmer editions; co-founded by Thomas"
|
|
53
|
+
verification_status: verified
|
|
54
|
+
description: "\"Every piece of knowledge must have a single, unambiguous, authoritative representation in a system."
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
# Hunt & Thomas (Pragmatic Programmers)
|
|
58
|
+
|
|
59
|
+
## Signature
|
|
60
|
+
|
|
61
|
+
*"Every piece of knowledge must have a single, unambiguous, authoritative representation in a system. Duplication is the root of all software evil."* [ref:1]
|
|
62
|
+
|
|
63
|
+
Andrew Hunt and David Thomas; authors of **The Pragmatic Programmer** (1999 [ref:1], 20th anniversary edition 2019 [ref:2]). The bassclef voice on day-to-day development discipline — the habits, heuristics, and mental models that separate journeymen from craftspeople. Where Uncle Bob covers SOLID principles and Clean Code covers naming, Hunt & Thomas cover the practical engineering ethos that holds it all together.
|
|
64
|
+
|
|
65
|
+
## Core methods
|
|
66
|
+
|
|
67
|
+
- **DRY (single knowledge source)** — Every piece of knowledge must have one, unambiguous, authoritative representation [ref:1]. Not just code duplication — DRY applies to data schemas, documentation, tests, configuration. When knowledge is duplicated, changes require parallel updates; one update will eventually be missed.
|
|
68
|
+
- **Orthogonality** — Two components are orthogonal if changing one requires no change in the other [ref:1]. Build systems where responsibilities are independent. Orthogonality enables testing in isolation, deployment of parts independently, and fearless refactoring. Ask: "If I change this component, how many other things must change?" More than one means non-orthogonal design.
|
|
69
|
+
- **Tracer bullets** — When starting a new feature or system, build a thin, working end-to-end path first [ref:1]. Unlike a prototype (thrown away after learning), a tracer bullet is production code; it proves the architectural path works with real infrastructure. Flesh out the path once the tracer lands.
|
|
70
|
+
- **Broken windows** — A single unaddressed TODO, a failing test ignored, a function that clearly misrepresents what it does — these signal that quality is not a priority [ref:1]. Teams that tolerate one broken window soon tolerate ten. Small decay normalizes fast.
|
|
71
|
+
|
|
72
|
+
## When to channel this luminary
|
|
73
|
+
|
|
74
|
+
When the primary risk is accumulated developer slop: duplication creeping in across a growing codebase, modules coupling accidentally because it was easier, or a team building by coincidence rather than by intent. Hunt & Thomas dominate code review and initial architecture sessions where discipline habits are being established. Channel them when the team is growing and shared engineering standards need grounding.
|
|
75
|
+
|
|
76
|
+
INSTEAD of channeling Hunt & Thomas for systems under acute failure: use Nygard for production stability, Newman or Hohpe for large-scale distributed architecture. Hunt & Thomas are everyday discipline, not the crisis response.
|
|
77
|
+
|
|
78
|
+
## Stack translation
|
|
79
|
+
|
|
80
|
+
In Next.js + Prisma + TypeScript:
|
|
81
|
+
|
|
82
|
+
- **DRY** — schema types derived from Prisma output (single source of truth); API response shapes defined once as Zod schemas, reused for both server-side validation and client-side type inference; environment variables loaded and typed in a single `env.ts`, imported everywhere else.
|
|
83
|
+
- **Orthogonality** — service layer functions that do not import from UI components; Prisma models that contain no business rules; server actions that contain no formatting logic. If a test for deal enrichment requires importing a React component, the design is non-orthogonal.
|
|
84
|
+
- **Tracer bullets** — first commit on a new feature: end-to-end slice touching DB → server action → component → route — with minimal data but fully wired. Real code that runs, not a mock. The tracer confirms the path works. Then add fields, edge cases, and polish.
|
|
85
|
+
- **Broken windows** — failing tests in CI block the pipeline (no exceptions); TypeScript strict mode enforced from day one; no `any` types in production code without a comment explaining why.
|
|
86
|
+
|
|
87
|
+
## Anti-patterns it prevents
|
|
88
|
+
|
|
89
|
+
- **Knowledge duplication** — the same business rule encoded in the Prisma schema, a Zod schema, a TypeScript type, AND inline validation. When the rule changes, three of four are updated; one is not. DRY discipline collapses these to one source.
|
|
90
|
+
- **Programming by coincidence** — code that "happens to work" without the developer understanding why. Characterized by careful arrangement of boilerplate without testing the assumptions. If you cannot explain why it works, it will stop working in a condition you have not tested.
|
|
91
|
+
- **Accidental coupling** — two modules share a utility or helper that grows to carry business logic for both. Changing the helper to serve one module breaks the other. Orthogonality discipline prevents this: ask whether the helper carries knowledge that belongs to only one module. If yes, extract.
|
|
92
|
+
- **Prototype rot** — throwaway prototypes that become production because "it mostly works." Prototypes are discarded after learning; tracer bullets are production code from the start. Calling something a prototype does not justify shipping it.
|
|
93
|
+
|
|
94
|
+
## Worked example
|
|
95
|
+
|
|
96
|
+
For POA's deal enrichment pipeline, Hunt & Thomas's approach:
|
|
97
|
+
|
|
98
|
+
**DRY check**: the definition of "enrichment fields" (company name, headcount, industry) appears in the Prisma schema, an enrichment TypeScript type, an API response shape, AND a table column list in the UI. Four representations of one piece of knowledge. DRY says: Prisma is the single source; derive the TypeScript type from Prisma's generated types; derive the API response from the same type; derive the table columns from a central field registry. Adding a new field changes one file.
|
|
99
|
+
|
|
100
|
+
**Orthogonality check**: the enrichment worker imports from the email module because a previous developer wanted to send a notification when enrichment completes. Extract the notification logic: enrichment worker emits an event or calls a notification interface; the email module listens. The enrichment worker no longer depends on email infrastructure.
|
|
101
|
+
|
|
102
|
+
**Tracer bullet**: first day on "bulk enrichment" — wire a single deal through the new batch endpoint, job queue, and enrichment function. No retry logic, no bulk UI, no progress tracking. But it runs end-to-end with real data. The tracer confirms the queue can dispatch enrichment jobs. Then add batch size, retries, and UI.
|
|
103
|
+
|
|
104
|
+
## Sources
|
|
105
|
+
|
|
106
|
+
- *The Pragmatic Programmer: From Journeyman to Master* — Hunt, Thomas, Addison-Wesley (1999) [ref:1]
|
|
107
|
+
- *The Pragmatic Programmer: 20th Anniversary Edition* — Hunt, Thomas, Addison-Wesley (2019) — substantially revised [ref:2]
|
|
108
|
+
- pragprog.com — Pragmatic Bookshelf (co-founded by Thomas) [ref:3]
|
|
109
|
+
|
|
110
|
+
## Related luminaries
|
|
111
|
+
|
|
112
|
+
- **Robert C. Martin** — SOLID principles and Clean Code operate at the same altitude. Uncle Bob's Single Responsibility complements Hunt & Thomas's orthogonality; both reject coupling from different starting points.
|
|
113
|
+
- **Martin Fowler** — Refactoring is where you fix the broken windows and eliminate DRY violations that accumulated. Fowler's catalog operationalizes what Hunt & Thomas prescribe.
|
|
114
|
+
- **Kent Beck** — TDD is how you prove the tracer bullet works and keep the broken windows visible as failing tests.
|
|
115
|
+
- **Michael Feathers** — When the codebase is already non-orthogonal with high duplication, Feathers's seam-based approach is the path back before Hunt & Thomas's discipline can hold.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Hyrum Wright
|
|
4
|
+
slug: hyrum-wright
|
|
5
|
+
claimed_by: [architect]
|
|
6
|
+
referenced_by_skills: [release, decompose, architect-review]
|
|
7
|
+
primary_domain: api-stability
|
|
8
|
+
depth: stub
|
|
9
|
+
description: "\"With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.\""
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Hyrum Wright
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
*"With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody."*
|
|
17
|
+
|
|
18
|
+
This is **Hyrum's Law**. Wright is a Google software engineer who codified what kernel hackers, library maintainers, and protocol designers had been learning for decades. The law is the theoretical foundation for why "we don't break adopters" is a Tier 1 discipline.
|
|
19
|
+
|
|
20
|
+
## Core principle
|
|
21
|
+
|
|
22
|
+
**Observability creates dependency.** Hyrum's Law extends API stability beyond declared contracts to every observable behavior. The signature, the return type, the timing, the side effects, the order of error messages, the filename of an internal file — every observable surface accumulates dependencies once enough users exist.
|
|
23
|
+
|
|
24
|
+
The law has three implications:
|
|
25
|
+
|
|
26
|
+
1. **You cannot fully specify behavior.** Whatever you document as "the contract," some adopter will be depending on something you didn't document.
|
|
27
|
+
2. **Refactor risk grows with adoption.** A change "safe under the contract" can break adopters who depend on observable side effects.
|
|
28
|
+
3. **The cost of cleanup is asymmetric.** Producers want to clean up. Adopters want stability. Once N adopters depend on observed behavior, the producer's cleanup cost is N × (each adopter's migration effort).
|
|
29
|
+
|
|
30
|
+
## How this applies to bassclef
|
|
31
|
+
|
|
32
|
+
Tonight's example: bassclef never declared `~/src/sunj-labs/canonical/` as a stable filesystem path. The directory name was an internal convention, not a contract. But every adopter on the operator's machine had observed that path — through their symlinks, through their `settings.json`, through their `additionalDirectories` references. The rename `mv canonical bassclef` broke an undeclared but heavily-observed surface.
|
|
33
|
+
|
|
34
|
+
Hyrum's Law says: that path was a contract whether bassclef declared it or not. With enough adopters (10+ siblings on this one machine), every observable surface becomes load-bearing.
|
|
35
|
+
|
|
36
|
+
The discipline answer:
|
|
37
|
+
|
|
38
|
+
- Treat **every** adopter-observable surface as part of the contract, not just declared ones.
|
|
39
|
+
- When unsure if a surface is observable, **assume it is** and ship the compat shim.
|
|
40
|
+
- Use Hyrum's Law as the budget against premature refactoring — "would I want to maintain this surface forever?" If no, don't ship it as observable.
|
|
41
|
+
|
|
42
|
+
## Key insight: the contract is what users observe, not what you wrote
|
|
43
|
+
|
|
44
|
+
This reframes substrate evolution:
|
|
45
|
+
|
|
46
|
+
| You wrote | Adopters observe | What's actually the contract |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| "Sync from `bassclef-source.json`" | `~/src/sunj-labs/canonical/` path | The path |
|
|
49
|
+
| "Hook X fires on PreToolUse" | Hook X's filename and location | The filename + location |
|
|
50
|
+
| "Skills load from `.claude/skills/`" | Symlink targets, agent names, directory structure | All three |
|
|
51
|
+
| "State spine entities follow schema S" | Every field name, every default value, every error message | All of it |
|
|
52
|
+
|
|
53
|
+
The substrate's "contract" is much bigger than what's written down. Every change must respect the observable surface.
|
|
54
|
+
|
|
55
|
+
## How to apply
|
|
56
|
+
|
|
57
|
+
1. **Enumerate observable surfaces before changing them.** Run `grep -rn` across known adopter repos for any reference to the surface you're about to change.
|
|
58
|
+
2. **When in doubt, assume it's observed.** The cost of an unnecessary compat shim is small. The cost of a broken adopter is large.
|
|
59
|
+
3. **Test against real adopter consumption.** Not unit tests on the substrate side; integration tests that clone a representative adopter and exercise their consumption paths.
|
|
60
|
+
4. **Account for the multiplier.** A surface used by 10 adopters has 10× the migration cost. The math: "is the rename benefit > 10 × (migration cost per adopter)?" usually says no.
|
|
61
|
+
|
|
62
|
+
## Anti-patterns
|
|
63
|
+
|
|
64
|
+
- **"It's not in the public API"** — Hyrum's Law doesn't care. Adopters depend on whatever they can observe.
|
|
65
|
+
- **"We never documented that"** — same response. Documentation isn't the contract; observability is.
|
|
66
|
+
- **"Only one adopter uses it"** — that's still one broken adopter. And tomorrow there will be more.
|
|
67
|
+
- **"We can deprecate and migrate"** — Hyrum's Law warns that deprecation periods are always shorter than the actual migration tail. Plan for permanent shims, not eventual cleanup.
|
|
68
|
+
|
|
69
|
+
## How bassclef channels Hyrum
|
|
70
|
+
|
|
71
|
+
The discipline lives in:
|
|
72
|
+
|
|
73
|
+
- `.claude/rules/we-dont-break-adopters.md` — methodology layer; cites Hyrum's Law as the why
|
|
74
|
+
- `architecture/dual-repo-flow.md` "Non-breaking changes to adopters" section — enumerates adopter-observable surfaces
|
|
75
|
+
- Phase 2 mechanical layer (bassclef#1360) — pre-rename CI test surfaces every observable adopter dependency before a substrate change ships
|
|
76
|
+
|
|
77
|
+
## Sources
|
|
78
|
+
|
|
79
|
+
- Hyrum Wright, "Hyrum's Law" — https://www.hyrumslaw.com/
|
|
80
|
+
- *Software Engineering at Google* — Wright, Winters, Manshreck; O'Reilly (2020)
|
|
81
|
+
- Titus Winters talks on long-term codebase maintenance (Google C++ committee chair); CppCon
|
|
82
|
+
- XKCD 1172 ("Workflow") — the cultural reference Wright codified into a law
|
|
83
|
+
|
|
84
|
+
## Distinct from
|
|
85
|
+
|
|
86
|
+
- @luminary linus-torvalds — applies Hyrum's Law to operating system kernels; provides the discipline answer (we just don't break userspace, ever)
|
|
87
|
+
- @luminary michael-nygard — stability patterns at runtime; complements but doesn't anchor the design-time discipline
|
|
88
|
+
- @luminary frederick-brooks — provides the cost framing (cumulative cleanup cost vs single-rename benefit); Hyrum provides the why (observability multiplies the cost across adopters)
|
|
89
|
+
|
|
90
|
+
## Refs
|
|
91
|
+
|
|
92
|
+
- bassclef#1360 — Phase 2 mechanical layer
|
|
93
|
+
- 2026-06-21 chronicle — first documented Hyrum's-Law cascade in bassclef's history
|
|
94
|
+
- ADR-031 — non-breaking-change adopter discipline (decision layer)
|
|
@@ -113,11 +113,11 @@ The scraper function is 300 lines; it fetches, parses, writes to the database, a
|
|
|
113
113
|
Feathers's "code without characterization tests is legacy code by definition" became the anchor citation for the bassclef substrate-as-system tenet (ADR-035). The bet 24c architect-review (2026-06-24) anchored on comprehension-side lenses (Brooks + Linus + Ishikawa + Deming) and missed the mechanism-fidelity class — "rule names mechanical enforcement that does not actually fire." The recursive Act phase (`architecture/audits/2026-06-27-audit-method-blind-spot.md`) named the lens-gap; Feathers's verification-side framing supplied the cure.
|
|
114
114
|
|
|
115
115
|
The bet 27c foundation ships:
|
|
116
|
-
- `standards/mechanism-fidelity.md` — audit method spec; Feathers-style characterization tests pin every rule's mechanism claim
|
|
116
|
+
- `standards/mechanism-fidelity.md` (standard tier) — audit method spec; Feathers-style characterization tests pin every rule's mechanism claim
|
|
117
117
|
- `lib/mechanism-fidelity.sh` — shared scanner that runs the 5-step verification chain
|
|
118
118
|
- `.claude/skills/audit-rule-mechanism-fidelity/SKILL.md` — operator-invocable audit (Feathers + Beck primary luminaries)
|
|
119
119
|
- `scripts/cold-adopter-harness-sync.sh` Shape d — per-PR gate (4 check classes; Feathers + Saltzer-Schroeder + Ousterhout primary)
|
|
120
|
-
- `.claude/rules/substrate-as-system.md` — auto-loaded tenet rule (cites Feathers as primary)
|
|
120
|
+
- `.claude/rules/substrate-as-system.md` (standard tier) — auto-loaded tenet rule (cites Feathers as primary)
|
|
121
121
|
- `.claude/skills/architect-review/SKILL.md` — amendment makes Feathers + Beck + Saltzer-Schroeder verification-side primaries alongside Brooks + Linus comprehension-side primaries
|
|
122
122
|
|
|
123
123
|
Feathers's brownfield-rescue framing applies recursively at the substrate level: bassclef's own substrate had legacy mechanism-fidelity claims (108 claims classified by WU-6 first audit; 76 non-CLEAN). The cure bet (Bet C-pre-2) drives them to zero via the same Feathers discipline — characterization tests, seam identification, sprout/wrap patterns — applied to substrate hooks rather than application code.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Tony Hoare
|
|
4
|
+
slug: tony-hoare
|
|
5
|
+
claimed_by: [builder, reviewer, architect]
|
|
6
|
+
referenced_by_skills: [verify, pattern-review, decompose]
|
|
7
|
+
primary_domain: engineering
|
|
8
|
+
depth: full
|
|
9
|
+
sources:
|
|
10
|
+
- type: paper
|
|
11
|
+
title: "An Axiomatic Basis for Computer Programming"
|
|
12
|
+
authors: ["C. A. R. Hoare"]
|
|
13
|
+
year: 1969
|
|
14
|
+
venue: "Communications of the ACM, 12(10), 576-580"
|
|
15
|
+
url: "https://dl.acm.org/doi/10.1145/363235.363259"
|
|
16
|
+
methodology_covered:
|
|
17
|
+
- "Hoare logic — the triple {P} S {Q} relating precondition P, statement S, postcondition Q"
|
|
18
|
+
- "Formal reasoning about program correctness through assertion calculus"
|
|
19
|
+
- "Axiomatic semantics — meaning of a program is what can be proved about it"
|
|
20
|
+
- type: paper
|
|
21
|
+
title: "Hints on Programming Language Design"
|
|
22
|
+
authors: ["C. A. R. Hoare"]
|
|
23
|
+
year: 1973
|
|
24
|
+
venue: "Stanford Computer Science Department, STAN-CS-73-403"
|
|
25
|
+
url: "https://www.cs.tufts.edu/~nr/cs257/archive/tony-hoare/hints-pl-design.pdf"
|
|
26
|
+
methodology_covered:
|
|
27
|
+
- "Simplicity is the unique selling proposition of a programming language"
|
|
28
|
+
- "Security via construction — design out classes of error rather than detect them"
|
|
29
|
+
- "Readability primacy — a program is read more often than it is written"
|
|
30
|
+
- type: paper
|
|
31
|
+
title: "Communicating Sequential Processes"
|
|
32
|
+
authors: ["C. A. R. Hoare"]
|
|
33
|
+
year: 1978
|
|
34
|
+
venue: "Communications of the ACM, 21(8), 666-677"
|
|
35
|
+
url: "https://dl.acm.org/doi/10.1145/359576.359585"
|
|
36
|
+
methodology_covered:
|
|
37
|
+
- "CSP — concurrency as composition of independent processes communicating via synchronous channels"
|
|
38
|
+
- "Influenced Go's goroutines + channels, Erlang's actor model, occam"
|
|
39
|
+
- type: talk
|
|
40
|
+
title: "Null References: The Billion Dollar Mistake"
|
|
41
|
+
authors: ["C. A. R. Hoare"]
|
|
42
|
+
year: 2009
|
|
43
|
+
venue: "QCon London"
|
|
44
|
+
url: "https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/"
|
|
45
|
+
methodology_covered:
|
|
46
|
+
- "Reflection on ALGOL W (1965) decision to allow null references — admits as billion-dollar mistake"
|
|
47
|
+
- "Design errors out of existence via type system — modern relevance to Option / Result / NonNullable types"
|
|
48
|
+
verification_status: verified
|
|
49
|
+
description: "\"There are two ways of constructing a software design: one is to make it so simple that there are obviously no deficiencies; the other is to make it so complicated that there are…"
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
# Tony Hoare
|
|
53
|
+
|
|
54
|
+
## Signature
|
|
55
|
+
|
|
56
|
+
*"There are two ways of constructing a software design: one is to make it so simple that there are obviously no deficiencies; the other is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult."*
|
|
57
|
+
|
|
58
|
+
Sir Charles Antony Richard Hoare. Turing Award winner (1980) for "fundamental contributions to the definition and design of programming languages." Author of **Quicksort** (1959), **Hoare logic** (1969), and **Communicating Sequential Processes** (1978). Oxford professor emeritus and Microsoft Research senior researcher. The bassclef voice on contract-driven reasoning, simplicity-as-discipline, and designing errors out of existence.
|
|
59
|
+
|
|
60
|
+
## Core methods
|
|
61
|
+
|
|
62
|
+
- **Hoare logic — the `{P} S {Q}` triple** — A program statement `S` is correct with respect to precondition `P` and postcondition `Q` if: when `P` holds before `S` executes, then `Q` holds after `S` terminates. The triple is the formal contract between caller and callee. Test sufficiency for a function is: cover every meaningful `(P, Q)` pair the function commits to.
|
|
63
|
+
- **Precondition discipline** — A function's precondition is what the caller must guarantee. Violations are programmer errors, not runtime errors. Pre-validate at the boundary; trust internally.
|
|
64
|
+
- **Postcondition discipline** — A function's postcondition is what it guarantees on return. The test asserts the postcondition; the implementation establishes it.
|
|
65
|
+
- **Loop invariant** — A condition true before the loop, after every iteration, and on exit. The invariant IS the proof that the loop establishes its postcondition.
|
|
66
|
+
- **Class invariant** (operationalized by Bertrand Meyer in Eiffel's Design by Contract, 1986) — A condition that holds at every observable state of an instance. Constructors must establish it; methods must preserve it.
|
|
67
|
+
- **Communicating Sequential Processes (CSP)** — Concurrency as composition of independent processes that synchronize only through explicit channels. Shared mutable state replaced by message-passing. Direct ancestor of Go's goroutines + channels, Erlang's actor model.
|
|
68
|
+
- **Simplicity as design discipline** — Hoare's most-cited prescription: choose the design where deficiencies are obvious, not the design where there are no obvious deficiencies. The two are not equivalent; the second hides bugs the first surfaces.
|
|
69
|
+
- **Design errors out of existence** — Null references were a 1965 design choice Hoare publicly regrets. The lens: if a class of error CAN be made impossible by construction (type system, API shape, invariant enforcement), make it so. Detection is strictly weaker than prevention.
|
|
70
|
+
|
|
71
|
+
## When to channel this luminary
|
|
72
|
+
|
|
73
|
+
When the primary risk is correctness under interaction — multiple callers, multiple states, contracts implicit but unenforced. Hoare dominates for state-spine accessors, hook input/output contracts, concurrent code (locks, queues, event ordering), and API boundaries where the contract has to survive every caller.
|
|
74
|
+
|
|
75
|
+
Pair with Beck (TDD rhythm), Myers (coverage taxonomy of what to assert), Ousterhout (design judgment for where to draw the boundary). Beck owns the cycle; Myers owns the categories; Ousterhout owns the shape; Hoare owns the contract itself.
|
|
76
|
+
|
|
77
|
+
Skip Hoare when: the work is exploratory spike code with no caller, the interface is genuinely throwaway, or the relevant risk is design-quality rather than contract-correctness (route to Ousterhout). Hoare's discipline carries overhead; apply where the overhead earns its keep.
|
|
78
|
+
|
|
79
|
+
INSTEAD of citing Hoare for refactoring tactics, design-pattern selection, or test rhythm: route to Fowler, GoF, and Beck respectively.
|
|
80
|
+
|
|
81
|
+
## Stack translation
|
|
82
|
+
|
|
83
|
+
In bassclef's bash hook + state-spine substrate:
|
|
84
|
+
|
|
85
|
+
- **Hook tests as contract assertions** — Every hook test case is a Hoare triple in disguise. Test name = `(P, Q)` pair; arrange-act-assert is `establish P → run S → check Q`. Example: for `auto-save-idle.sh`, `test('SESSION_LOCK present suppresses auto-save', ...)` is `{LOCK file exists} run hook {no commit happens}`. The test sufficiency rubric's "stdin contract" criterion IS Hoare's precondition discipline.
|
|
86
|
+
- **State-spine accessors as contracts** — `state_whereami_set "key" "value"` has precondition (`key` is a valid Whereami field path; `value` is JSON-serializable + schema-conformant) and postcondition (state stored + queryable via `state_whereami_get "key"`). The `state-validate.sh` PreToolUse hook IS the mechanical enforcement of the precondition; the schema IS the contract.
|
|
87
|
+
- **Pre-build-gate hook as precondition enforcement** — Every gate the hook fires (temperance marker present? diagnose evidence on fix/ branches? state markers in place?) is a precondition the substrate refuses to relax. The hook BLOCKs to prevent the agent from violating a contract that downstream consumers depend on.
|
|
88
|
+
- **Bash strict mode as invariant** — `set -euo pipefail` establishes an invariant: any unhandled error terminates the script. The invariant must hold across every function; `trap EXIT` cleanup respects the invariant by running regardless of exit path.
|
|
89
|
+
- **CSP-style channels in bassclef** — Inter-session coordination via roadmap event_history (bassclef#337) follows CSP shape: each session is a process; the roadmap is the synchronization channel; atomic claim/release primitives are the synchronous message-pass. Direct application of Hoare's 1978 paper to multi-agent SDLC.
|
|
90
|
+
|
|
91
|
+
In Next.js + TypeScript adopter stacks:
|
|
92
|
+
|
|
93
|
+
- **Type system as precondition encoder** — `Option<T>` / `Result<T, E>` / branded types make Hoare's "design errors out of existence" mechanical. `NonNullable<T>` is null-as-billion-dollar-mistake corrected at compile time.
|
|
94
|
+
- **Zod schemas as boundary contracts** — Validate at the system boundary (API route handler, message consumer); trust internally. Zod parse failure IS the precondition violation Hoare's framing makes explicit.
|
|
95
|
+
- **Class invariants in domain models** — A `Deal` instance with `status: 'closed' && closingPrice: undefined` violates an invariant. Constructors + factories enforce it; methods preserve it.
|
|
96
|
+
|
|
97
|
+
## Anti-patterns it prevents
|
|
98
|
+
|
|
99
|
+
- **Implicit contracts that drift** — A function with no documented precondition has every caller guessing. When one caller's assumption diverges from another's, bugs appear at the seam. Hoare's discipline forces the contract to be explicit (test, type, assertion, or comment).
|
|
100
|
+
- **Defensive coding scattered across callers** — Every caller checking the same precondition is a contract that should have been centralized at the callee's boundary. Pre-validate once at the entry; trust thereafter.
|
|
101
|
+
- **Postcondition-by-vibe** — "It seems to work" is not a contract. Hoare's framing requires the postcondition be statable and testable. If it is not statable, the function's purpose is unclear.
|
|
102
|
+
- **Loop-by-mutation-tracking** — A loop where correctness depends on tracking which variables mutated in which order is harder to reason about than a loop with an explicit invariant. Hoare's invariant discipline asks: what is true at the top of every iteration?
|
|
103
|
+
- **Null-as-default** — Returning `null` (or `undefined`) for "not found" forces every caller to handle the missing case. Returning `Option<T>` (or `NotFound<T>`) encodes the precondition into the type system. Hoare's billion-dollar-mistake talk is the bassclef case against null-as-default.
|
|
104
|
+
- **Shared mutable state for coordination** — Two processes synchronizing through a shared variable hold an implicit lock the language has no visibility into. CSP-style channels make the synchronization explicit; the channel IS the synchronization.
|
|
105
|
+
|
|
106
|
+
## Worked example
|
|
107
|
+
|
|
108
|
+
Tightening bassclef's `auto-save-idle.sh` hook under Hoare's discipline:
|
|
109
|
+
|
|
110
|
+
**Before — implicit contract:**
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Pseudocode of pre-#1085 state
|
|
114
|
+
if [ -z "$(git status --porcelain)" ]; then exit 0; fi
|
|
115
|
+
git add -A
|
|
116
|
+
git commit -m "auto-save: $(date -u)"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
What is the precondition? Caller assumes: working tree dirty, no SESSION_LOCK, no commit-sequence in flight. None of these are stated. Three different sessions can produce three different definitions of "should this commit?"
|
|
120
|
+
|
|
121
|
+
**After — Hoare-explicit contract:**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# {P}: working tree dirty AND no SESSION_LOCK AND no defer marker for commit-sequence
|
|
125
|
+
[ -n "$(git status --porcelain)" ] || { exit 0; } # P-1: dirty
|
|
126
|
+
[ ! -f .claude/SESSION_LOCK ] || { exit 0; } # P-2: no lock
|
|
127
|
+
[ ! -f state/markers/auto-save-defer/commit-sequence.marker ] || { exit 0; } # P-3: no defer
|
|
128
|
+
|
|
129
|
+
# S: stage + commit
|
|
130
|
+
git add -A
|
|
131
|
+
git commit -m "auto-save: $(date -u)"
|
|
132
|
+
|
|
133
|
+
# {Q}: HEAD advanced by exactly one commit AND working tree clean
|
|
134
|
+
[ "$(git status --porcelain)" = "" ] # Q-1: clean
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
What the test owes (Hoare-derived test list):
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# test-list:
|
|
141
|
+
# [x] {dirty AND no LOCK AND no defer} → commit happens AND tree clean (P all true, Q holds)
|
|
142
|
+
# [x] {LOCK present} → no commit (P-2 false; hook returns early before S)
|
|
143
|
+
# [x] {defer marker present} → no commit (P-3 false; hook returns early before S)
|
|
144
|
+
# [x] {clean tree} → no commit (P-1 false; nothing to commit)
|
|
145
|
+
# [x] {LOCK AND defer present} → no commit, LOCK takes precedence in early-exit order
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The test list IS the Hoare triple decomposed. Each line names one `(P, Q)` pair. The hook is the implementation that establishes Q when P holds.
|
|
149
|
+
|
|
150
|
+
What this discipline catches: PR #1058 (the auto-save-scope-hole that bassclef#1059 closed) shipped without P-2 enforced. A Hoare-explicit contract from day one would have surfaced the missing precondition at write time, not after the failure ran in production substrate.
|
|
151
|
+
|
|
152
|
+
## Sources
|
|
153
|
+
|
|
154
|
+
- "An Axiomatic Basis for Computer Programming" — Hoare, *Communications of the ACM* 12(10), 1969
|
|
155
|
+
- "Hints on Programming Language Design" — Hoare, Stanford CS, 1973
|
|
156
|
+
- "Communicating Sequential Processes" — Hoare, *Communications of the ACM* 21(8), 1978; book Prentice Hall, 1985
|
|
157
|
+
- "Null References: The Billion Dollar Mistake" — Hoare, QCon London 2009
|
|
158
|
+
- "Quicksort" — Hoare, *Computer Journal* 5(1), 1962
|
|
159
|
+
- ACM Turing Award citation (1980)
|
|
160
|
+
- Oxford Department of Computer Science emeritus page
|
|
161
|
+
- Microsoft Research Cambridge senior researcher page
|
|
162
|
+
|
|
163
|
+
## Related luminaries
|
|
164
|
+
|
|
165
|
+
- **Bertrand Meyer** — Design by Contract operationalized Hoare's logic for Eiffel (1986); same lens with practitioner-grade tooling. Modern type systems (TypeScript, Rust, Scala) carry DBC patterns Meyer named.
|
|
166
|
+
- **Edsger Dijkstra** — Structured programming + weakest-precondition calculus extended Hoare's axiomatic basis. Famously argued "testing shows the presence, not the absence, of bugs" — the counterweight that says even Hoare-explicit contracts do not prove correctness in the formal sense.
|
|
167
|
+
- **Glenford Myers** — Coverage taxonomy supplies the WHICH categories of input exercise a contract; Hoare supplies WHAT the contract is. Both are required for a complete test suite.
|
|
168
|
+
- **Kent Beck** — TDD rhythm produces tests; Hoare contracts decide what those tests must assert. Beck's "make it work" needs Hoare's "what does it commit to" to be testable.
|
|
169
|
+
- **John Ousterhout** — Deep modules with small interfaces are easier to contract-test (small surface area for `(P, Q)` pairs). Ousterhout's design quality lens implicitly rewards Hoare-explicit interfaces.
|
|
170
|
+
- **Tony Hoare's own work on CSP** — direct ancestor of Go (channels + goroutines), Erlang (actor model), occam. Bassclef's event_history + atomic claim/release pattern (bassclef#337) is CSP applied to multi-session SDLC.
|