@thebassclef/lite 0.0.1 → 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/LICENSE +202 -0
- package/README.md +85 -4
- package/dist/cli.cjs +1612 -0
- package/dist/cli.js +1589 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/package.json +51 -3
- package/substrate/.bassclef/lite-manifest.json +2701 -0
- package/substrate/.claude/agents/architect.md +70 -0
- package/substrate/.claude/agents/builder.md +114 -0
- package/substrate/.claude/agents/designer.md +156 -0
- package/substrate/.claude/agents/reviewer.md +88 -0
- package/substrate/.claude/hooks/artifact-ingestion-gate.sh +357 -0
- package/substrate/.claude/hooks/assert-verify-steering.sh +77 -0
- package/substrate/.claude/hooks/bassclef-source-config-validate.sh +215 -0
- package/substrate/.claude/hooks/bassclef-sync.sh +634 -0
- package/substrate/.claude/hooks/compound-noun-scrub.sh +292 -0
- package/substrate/.claude/hooks/kiss-expansion-inject.sh +69 -0
- 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/plain-english-steering.sh +156 -0
- package/substrate/.claude/hooks/post-skill-friction-check.sh +177 -0
- package/substrate/.claude/hooks/post-skill-telemetry.sh +62 -0
- package/substrate/.claude/hooks/pre-build-gate.sh +511 -0
- package/substrate/.claude/hooks/pre-commit-gate.sh +451 -0
- package/substrate/.claude/hooks/session-end.sh +433 -0
- package/substrate/.claude/hooks/session-reflection.sh +303 -0
- package/substrate/.claude/hooks/skill-body-grade-gate.sh +219 -0
- package/substrate/.claude/hooks/skill-body-intent-drift.sh +107 -0
- package/substrate/.claude/hooks/skill-step-list-check.sh +171 -0
- package/substrate/.claude/hooks/state-validate.sh +271 -0
- package/substrate/.claude/hooks/substrate-clarity-gate.sh +1110 -0
- package/substrate/.claude/hooks/temperance-gate.sh +147 -0
- package/substrate/.claude/hooks/testing-tier-enforce.sh +233 -0
- package/substrate/.claude/hooks/turn-prose-grade-measure.sh +219 -0
- package/substrate/.claude/hooks/turn-prose-kiss-check.sh +463 -0
- package/substrate/.claude/hooks/vocabulary-migration-check.sh +171 -0
- package/substrate/.claude/hooks/whereami-utc-gate.sh +142 -0
- package/substrate/.claude/luminaries/alan-cooper.md +170 -0
- package/substrate/.claude/luminaries/alistair-cockburn.md +140 -0
- package/substrate/.claude/luminaries/amazon-pr-faq.md +34 -0
- package/substrate/.claude/luminaries/ash-maurya.md +121 -0
- package/substrate/.claude/luminaries/bill-buxton.md +210 -0
- package/substrate/.claude/luminaries/charles-sanders-peirce.md +150 -0
- package/substrate/.claude/luminaries/david-ogilvy.md +192 -0
- package/substrate/.claude/luminaries/don-norman.md +173 -0
- package/substrate/.claude/luminaries/edward-tufte.md +179 -0
- package/substrate/.claude/luminaries/eric-evans.md +160 -0
- package/substrate/.claude/luminaries/frederick-brooks.md +50 -0
- package/substrate/.claude/luminaries/gang-of-four.md +157 -0
- 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/jason-fried-dhh.md +46 -0
- package/substrate/.claude/luminaries/jesse-james-garrett.md +154 -0
- package/substrate/.claude/luminaries/john-ousterhout.md +94 -0
- package/substrate/.claude/luminaries/karl-popper.md +132 -0
- package/substrate/.claude/luminaries/kent-beck.md +168 -0
- package/substrate/.claude/luminaries/linus-torvalds.md +218 -0
- package/substrate/.claude/luminaries/martin-fowler.md +164 -0
- package/substrate/.claude/luminaries/michael-feathers.md +125 -0
- package/substrate/.claude/luminaries/michael-nygard.md +118 -0
- package/substrate/.claude/luminaries/robert-c-martin.md +164 -0
- package/substrate/.claude/luminaries/saltzer-schroeder.md +194 -0
- package/substrate/.claude/luminaries/sophia-prater.md +193 -0
- package/substrate/.claude/luminaries/stephen-toulmin.md +131 -0
- 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/artifact-ingestion.md +179 -0
- package/substrate/.claude/rules/assert-only-after-verify.md +137 -0
- package/substrate/.claude/rules/blocked-items.md +146 -0
- package/substrate/.claude/rules/bootstrap-pair-discipline.md +141 -0
- package/substrate/.claude/rules/branching.md +28 -0
- package/substrate/.claude/rules/cold-adopter-harness-discipline.md +129 -0
- package/substrate/.claude/rules/commit-conventions.md +22 -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/context-engineering.md +202 -0
- package/substrate/.claude/rules/context-management.md +85 -0
- package/substrate/.claude/rules/defensive-bash.md +68 -0
- package/substrate/.claude/rules/deferred-actions.md +233 -0
- package/substrate/.claude/rules/destructive-operations.md +69 -0
- package/substrate/.claude/rules/diagnosis.md +38 -0
- package/substrate/.claude/rules/github-issue-flash-tweet.md +156 -0
- package/substrate/.claude/rules/guardrails.md +73 -0
- package/substrate/.claude/rules/hook-wire-on-author.md +103 -0
- package/substrate/.claude/rules/identifier-leak-prevention.md +104 -0
- package/substrate/.claude/rules/iteration-bet-brief-completeness.md +54 -0
- package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +98 -0
- 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/oo-ad-entry-point.md +117 -0
- package/substrate/.claude/rules/operator-facing-prose.md +196 -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 +156 -0
- package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +211 -0
- package/substrate/.claude/rules/pr-body-shape.md +317 -0
- package/substrate/.claude/rules/pr-strategy.md +167 -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/sdlc-gates.md +149 -0
- package/substrate/.claude/rules/security.md +37 -0
- package/substrate/.claude/rules/session-artifacts.md +236 -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/state-schema-validation.md +162 -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/whereami-load-bearing.md +202 -0
- package/substrate/.claude/rules/writing-craft-discipline.md +92 -0
- package/substrate/.claude/rules/wu-sequencing-compounds.md +145 -0
- package/substrate/.claude/skills/build/SKILL.md +640 -0
- 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 +280 -0
- package/substrate/.claude/skills/diagnose/SKILL.md +297 -0
- package/substrate/.claude/skills/feynman/SKILL.md +90 -0
- package/substrate/.claude/skills/howdoi/SKILL.md +105 -0
- package/substrate/.claude/skills/ia-model/SKILL.md +108 -0
- package/substrate/.claude/skills/interaction-design/SKILL.md +112 -0
- package/substrate/.claude/skills/interpret-input/SKILL.md +180 -0
- package/substrate/.claude/skills/journal/SKILL.md +209 -0
- package/substrate/.claude/skills/kiss/SKILL.md +449 -0
- package/substrate/.claude/skills/launch/SKILL.md +915 -0
- package/substrate/.claude/skills/lean-canvas/SKILL.md +332 -0
- package/substrate/.claude/skills/longrun/SKILL.md +463 -0
- package/substrate/.claude/skills/luminary/SKILL.md +481 -0
- package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
- package/substrate/.claude/skills/onboard-repo/SKILL.md +1624 -0
- package/substrate/.claude/skills/pattern-review/SKILL.md +99 -0
- package/substrate/.claude/skills/personas/SKILL.md +207 -0
- package/substrate/.claude/skills/promote/SKILL.md +283 -0
- package/substrate/.claude/skills/requirement/SKILL.md +98 -0
- package/substrate/.claude/skills/retro/SKILL.md +117 -0
- package/substrate/.claude/skills/riff/SKILL.md +114 -0
- package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
- package/substrate/.claude/skills/session-end/SKILL.md +309 -0
- package/substrate/.claude/skills/session-log/SKILL.md +299 -0
- package/substrate/.claude/skills/skills/SKILL.md +228 -0
- package/substrate/.claude/skills/spec/SKILL.md +105 -0
- package/substrate/.claude/skills/sprint/SKILL.md +392 -0
- package/substrate/.claude/skills/stage/SKILL.md +384 -0
- package/substrate/.claude/skills/state-a-problem/SKILL.md +185 -0
- package/substrate/.claude/skills/temperance/SKILL.md +108 -0
- package/substrate/.claude/skills/use-case/SKILL.md +417 -0
- package/substrate/.claude/skills/user-stories/SKILL.md +268 -0
- package/substrate/.claude/skills/value-prop/SKILL.md +251 -0
- package/substrate/.claude/skills/verify/SKILL.md +160 -0
- 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 +307 -0
- package/substrate/AGENTS.md +79 -0
- package/substrate/CLAUDE-lite.md +85 -0
- package/substrate/CODE_OF_CONDUCT.md +28 -0
- package/substrate/CONTRIBUTING.md +177 -0
- package/substrate/README.md +173 -0
- package/substrate/SECURITY.md +19 -0
- package/substrate/architecture/decisions/ADR-029-release-pipeline.md +79 -0
- package/substrate/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
- package/substrate/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
- package/substrate/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
- package/substrate/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
- package/substrate/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
- package/substrate/lib/clean-artifacts-sweep.sh +112 -0
- package/substrate/lib/code-comment-discipline.sh +144 -0
- package/substrate/lib/composer-preflight.sh +459 -0
- package/substrate/lib/hook-inject.sh +255 -0
- package/substrate/lib/luminary-pick.sh +96 -0
- package/substrate/lib/output-discipline.sh +143 -0
- package/substrate/lib/prose-scan-boundary.sh +171 -0
- package/substrate/lib/rewrite-check.sh +214 -0
- package/substrate/lib/state.sh +1372 -0
- package/substrate/lib/telemetry.sh +205 -0
- package/substrate/lib/tier-check.sh +187 -0
- package/substrate/lib/tier-dependency-audit.sh +1088 -0
- package/substrate/presence/install/bassclef-hook-connect.sh +178 -0
- package/substrate/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
- package/substrate/presence/install/bassclef-sync.template.sh +2076 -0
- package/substrate/presence/install/schedule-auto-save.cron.sh +88 -0
- package/substrate/presence/install/schedule-auto-save.taskscheduler.md +122 -0
- package/substrate/scripts/aggregate-telemetry.sh +217 -0
- package/substrate/scripts/analyze-tier-dependencies.sh +239 -0
- package/substrate/scripts/generate-lite-manifest.sh +505 -0
- package/substrate/scripts/generate-tier-manifest.sh +28 -0
- package/substrate/scripts/intent-drift-check.sh +456 -0
- package/substrate/scripts/lite-manifest-drift-check.sh +146 -0
- package/substrate/scripts/render-lite-manifest-doc.sh +150 -0
- 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/bassclef-configs-schema.md +232 -0
- package/substrate/standards/bassclef-evolution.md +143 -0
- package/substrate/standards/bassclef-internal-jargon.md +244 -0
- package/substrate/standards/bassclef-managed-sentinel.md +96 -0
- package/substrate/standards/bassclef-source-config.md +228 -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/deferred-actions-schema.md +204 -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 +76 -0
- 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/graceful-exit.md +227 -0
- package/substrate/standards/hook-idempotency.md +102 -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 +135 -0
- package/substrate/standards/luminary-matching.md +105 -0
- package/substrate/standards/luminary-problem-patterns.md +481 -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/ogilvy-writing-rules.md +225 -0
- package/substrate/standards/opener-discipline.md +96 -0
- package/substrate/standards/operator-facing-prose-discipline.md +201 -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/project-directory-layout.md +276 -0
- package/substrate/standards/release-tagging.md +137 -0
- package/substrate/standards/reserved-skill-names.md +120 -0
- package/substrate/standards/scannable-multi-option-output.md +261 -0
- package/substrate/standards/sdlc-compliance.md +286 -0
- package/substrate/standards/sdlc-gates/typescript.md +57 -0
- package/substrate/standards/secrets-lifecycle.md +210 -0
- package/substrate/standards/security-scanner-adapter.md +145 -0
- package/substrate/standards/session-board.md +256 -0
- package/substrate/standards/skill-output-discipline.md +90 -0
- package/substrate/standards/state-spine-contract.md +255 -0
- package/substrate/standards/state-spine.md +511 -0
- package/substrate/standards/steering-hints/kiss-words.md +11 -0
- package/substrate/standards/substrate-config-schema.md +267 -0
- package/substrate/standards/tech-stack-config.md +109 -0
- package/substrate/standards/tier-dependency-analysis.md +167 -0
- package/substrate/standards/tier-runtime-deps/lite.md +57 -0
- package/substrate/standards/tier-tag-schema.md +155 -0
- 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/whereami-schema.md +301 -0
- package/substrate/standards/worktree-management.md +211 -0
- package/substrate/standards/writing-guide.md +213 -0
- package/substrate/templates/chronicle-template.md +75 -0
- package/substrate/templates/deferred-action-template.md +45 -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
- package/substrate/templates/whereami-template.md +101 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Linus Torvalds
|
|
4
|
+
slug: linus-torvalds
|
|
5
|
+
claimed_by: [architect, reviewer]
|
|
6
|
+
referenced_by_skills: [release, decompose, architect-review]
|
|
7
|
+
primary_domain: distribution-stability
|
|
8
|
+
depth: full
|
|
9
|
+
solves_problems_brownfield:
|
|
10
|
+
- "Substrate rename / refactor / path-change broke adopter sessions silently after merge"
|
|
11
|
+
- "Adopter following a citation in shipped substrate hit a 404 because the referenced path was renamed"
|
|
12
|
+
- "Hook filename change in bassclef caused adopter's session-start hook to fire stale logic"
|
|
13
|
+
- "PR ships a cleaner name for a hook / skill / rule and breaks every adopter inheriting through additionalDirectories"
|
|
14
|
+
- "Sync template version bumped without compat shim — adopter on prior version is in undefined behavior"
|
|
15
|
+
solves_problems_greenfield:
|
|
16
|
+
- "Designing a new adopter-observable surface where future renames must stay non-breaking"
|
|
17
|
+
- "Planning a release pipeline that catches adopter-breaking changes before they ship"
|
|
18
|
+
- "Authoring the first version of an adopter-facing manifest schema where every field becomes load-bearing once used"
|
|
19
|
+
- "Designing a compat-shim layer ahead of a planned rename so the deprecation window drains cleanly"
|
|
20
|
+
- "Building a representative-adopter integration test that runs against every substrate change"
|
|
21
|
+
anti_patterns:
|
|
22
|
+
- "Dev-machine-only test — works for the author, breaks at sync time for adopters"
|
|
23
|
+
- "Clean-break rename motivated by conceptual integrity — costs more than it saves once observers exist"
|
|
24
|
+
- "Announcement-as-shim — written notice that the old name has gone away, with no surviving artifact"
|
|
25
|
+
- "Deprecation window without a real-adopter migration test — the deprecation tail outlasts the window"
|
|
26
|
+
sources:
|
|
27
|
+
- type: archive
|
|
28
|
+
title: "LKML 2012-12-23: 'We do not break userspace'"
|
|
29
|
+
authors: ["Linus Torvalds"]
|
|
30
|
+
year: 2012
|
|
31
|
+
url: "https://lkml.org/lkml/2012/12/23/75"
|
|
32
|
+
methodology_covered:
|
|
33
|
+
- "Userspace stability as non-negotiable kernel discipline"
|
|
34
|
+
- "Regressions are bugs even when prior behavior was buggy"
|
|
35
|
+
- type: book
|
|
36
|
+
title: "Linux Kernel Development (3rd ed.)"
|
|
37
|
+
authors: ["Robert Love"]
|
|
38
|
+
year: 2010
|
|
39
|
+
url: ""
|
|
40
|
+
methodology_covered:
|
|
41
|
+
- "Kernel ABI stability discipline across versions"
|
|
42
|
+
- "Syscall number preservation; new behavior gets new syscall"
|
|
43
|
+
- type: archive
|
|
44
|
+
title: "Stability of the Linux ABI — Linux Foundation TAB"
|
|
45
|
+
authors: ["Linux Foundation Technical Advisory Board"]
|
|
46
|
+
year: 2014
|
|
47
|
+
url: "https://www.linuxfoundation.org/"
|
|
48
|
+
methodology_covered:
|
|
49
|
+
- "Module ABI stability commitments"
|
|
50
|
+
- "Internal API churn vs external ABI freeze"
|
|
51
|
+
- type: talk
|
|
52
|
+
title: "Driver ABI Stability"
|
|
53
|
+
authors: ["Greg Kroah-Hartman"]
|
|
54
|
+
year: 2015
|
|
55
|
+
url: "https://elinux.org/ELC_2015_Presentations"
|
|
56
|
+
methodology_covered:
|
|
57
|
+
- "Why kernel internals stay unstable on purpose; why exported ABI stays frozen"
|
|
58
|
+
- type: archive
|
|
59
|
+
title: "LKML 'regressions are bugs' thread (multiple instances 2008–2021)"
|
|
60
|
+
authors: ["Linus Torvalds", "LKML community"]
|
|
61
|
+
year: 2008
|
|
62
|
+
url: "https://lkml.org/"
|
|
63
|
+
methodology_covered:
|
|
64
|
+
- "Revert-on-regression default"
|
|
65
|
+
- "Producer pays migration cost, adopter pays nothing"
|
|
66
|
+
verification_status: verified
|
|
67
|
+
description: "\"We do not break userspace.\" — INSTEAD: the kernel team pays the migration cost so every program that ran yesterday keeps running today."
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
# Linus Torvalds
|
|
71
|
+
|
|
72
|
+
## Signature
|
|
73
|
+
|
|
74
|
+
*"We do not break userspace."* — INSTEAD: the kernel team pays the migration cost so every program that ran yesterday keeps running today.
|
|
75
|
+
|
|
76
|
+
Principal architect of Linux. The kernel's single most-cited rule across 30+ years of evolution is the userspace stability commitment. The cost of evolution rides with the kernel team. Adopters carry zero migration burden. This is the discipline bassclef applies at the substrate → adopter boundary.
|
|
77
|
+
|
|
78
|
+
## Core principle
|
|
79
|
+
|
|
80
|
+
Userspace stability is the ceiling, not a tradeoff. Linus's framing (LKML 2012, restated dozens of times since): a change that breaks user programs is a kernel bug, regardless of whether the user program was relying on documented or undocumented behavior. The kernel team has rejected technically-better designs because the migration cost to userspace was too high. Shipped compatibility shims have outlived the original feature by a decade. Permanent code complexity is accepted as the price of adopter trust.
|
|
81
|
+
|
|
82
|
+
Three operational consequences flow from this:
|
|
83
|
+
|
|
84
|
+
1. **Regressions are bugs even when prior behavior was buggy.** INSTEAD of fixing forward into a cleaner state: revert, fix the underlying problem from a different angle, ship the fix without changing the observable surface adopters depend on.
|
|
85
|
+
2. **The producer pays the cost.** INSTEAD of telling adopters to migrate: ship the compat shim, keep the old surface alive, document the retirement condition as "when the last known adopter migrates."
|
|
86
|
+
3. **Conceptual integrity has a budget.** INSTEAD of treating rename-for-cleanliness as free: weigh the rename benefit against migration cost × adopter count. When the cost exceeds the benefit, hold the rename.
|
|
87
|
+
|
|
88
|
+
## What this looks like in Linux
|
|
89
|
+
|
|
90
|
+
- **Syscall ABI is permanent.** Once a syscall ships, the signature stays. INSTEAD of changing an existing syscall: a new behavior gets a new syscall number; the old one keeps working forever.
|
|
91
|
+
- **Struct layouts grow but stay backward-compatible.** Removed fields stay as reserved holes. INSTEAD of rearranging fields: a new struct gets introduced; the old one stays usable.
|
|
92
|
+
- **/proc and /sys accumulate compatibility commitments.** Even ad-hoc debug surfaces become quasi-stable once tools parse them.
|
|
93
|
+
- **Compatibility shims live forever.** The kernel still supports 32-bit syscalls on 64-bit kernels for old binaries — INSTEAD of forcing a migration to 64-bit.
|
|
94
|
+
- **Regressions revert by default.** When a feature change breaks any adopter, the change reverts. INSTEAD of asking the adopter to adapt: the kernel team re-engineers from a different angle.
|
|
95
|
+
|
|
96
|
+
## Core methods
|
|
97
|
+
|
|
98
|
+
Five named methods an agent can invoke by name during review or design:
|
|
99
|
+
|
|
100
|
+
- **Adopter-observable surface enumeration** — Before any substrate change, list every surface adopters can observe (filesystem paths, hook filenames, schema field names, skill names referenced by settings.json, symlink targets, sync-template version markers). When the enumeration is missing from the PR body, the change is not yet reviewable. INSTEAD of reviewing on faith: send the PR back with a request for the surface list.
|
|
101
|
+
|
|
102
|
+
- **Compat-shim-first ship discipline** — Build the shim in the same release as the change. Symlink at the old path, alias at the old name, forwarding stub at the old hook filename, schema accommodation that accepts both names during transition. INSTEAD of "ship the rename now, add the shim later": ship both together; the gap between them is the window where adopters break.
|
|
103
|
+
|
|
104
|
+
- **Real-adopter integration test** — Test the change against a clone of a representative adopter. Run the adopter's actual sync hook against proposed substrate HEAD. Confirm zero observable change. INSTEAD of dev-machine validation: the cold-adopter harness IS the real-adopter test surface; the change waits for the harness when it isn't yet built.
|
|
105
|
+
|
|
106
|
+
- **Revert-on-regression default** — When a feature change breaks any adopter, revert by default and fix from a different angle. INSTEAD of trading adopter trust for the partial win: adopter trust is the ceiling; the feature is re-engineered.
|
|
107
|
+
|
|
108
|
+
- **Permanent-shim acceptance** — Accept that some compat shims live forever. The kernel still supports 32-bit syscalls for old binaries. INSTEAD of cycling shims through deprecation: document the retirement condition honestly ("when all known adopters migrate") and expect the answer is "forever."
|
|
109
|
+
|
|
110
|
+
## When to channel this luminary
|
|
111
|
+
|
|
112
|
+
When the primary risk is **adopter-observable surface change**. Linus dominates the review lens any time a PR touches:
|
|
113
|
+
|
|
114
|
+
- Filesystem paths under `~/src/sunj-labs/` that adopter symlinks resolve through
|
|
115
|
+
- Filenames inside `.claude/hooks/`, `.claude/skills/`, `.claude/rules/`, `.claude/agents/` (adopter settings.json + symlinks reference them by name)
|
|
116
|
+
- Schema shapes in `standards/state-spine/schemas/`
|
|
117
|
+
- Sync-template version markers in `presence/install/`
|
|
118
|
+
- `.bassclef-source.json` schema
|
|
119
|
+
- Adopter migration tooling under `scripts/migrate-*`
|
|
120
|
+
- Release pipeline andon decisions (per ADR-029)
|
|
121
|
+
- Rename / move / refactor of any of the above
|
|
122
|
+
|
|
123
|
+
Pair with Hyrum Wright (provides the theoretical why — observability creates dependency), Michael Nygard (ADR lifecycle for the breaking-change decision), and Vaughn Vernon (anticorruption layer is the structural shape Linus's discipline produces).
|
|
124
|
+
|
|
125
|
+
Outside this scope, route elsewhere. INSTEAD of channeling Linus for bassclef-internal refactors that touch zero adopter-observable surface: channel John Ousterhout (deep modules) or Kent Beck (TDD cycle). INSTEAD of channeling Linus for operator-private content under `docs/operator-private/`: that content stays in bassclef-upstream and doesn't ship to adopters; Linus's discipline is silent there. INSTEAD of channeling Linus for chronicles and journal entries: those are operator narrative, not contract; voice luminaries apply.
|
|
126
|
+
|
|
127
|
+
## Stack translation
|
|
128
|
+
|
|
129
|
+
bassclef is a substrate. Adopters are the userspace. Every adopter-observable surface is a syscall: once shipped, the surface keeps working forever unless an explicit multi-cycle deprecation runs.
|
|
130
|
+
|
|
131
|
+
Map:
|
|
132
|
+
|
|
133
|
+
| Linux kernel | bassclef substrate |
|
|
134
|
+
|---|---|
|
|
135
|
+
| Syscall ABI | hook filenames, skill names, agent names referenced by adopter settings.json |
|
|
136
|
+
| `/proc` + `/sys` | filesystem paths under `~/src/sunj-labs/` that adopter symlinks resolve through |
|
|
137
|
+
| Struct layouts | state-spine schema shapes |
|
|
138
|
+
| Module ABI | sync-template version markers in `presence/install/bassclef-sync.template.sh` |
|
|
139
|
+
| Boot interface | `.bassclef-source.json` schema fields |
|
|
140
|
+
| LKML release announcements | `/release` PR body Summary section + adopter changelog entry |
|
|
141
|
+
| Kernel-internal refactors | bassclef-internal refactors touching only `docs/operator-private/`, chronicles, internal scripts unexposed to adopters |
|
|
142
|
+
|
|
143
|
+
When bassclef renames `canonical → bassclef`, that is the equivalent of removing a syscall. The discipline answer: leave a compatibility shim (symlink, alias, forwarding stub) at the old name. Deprecate explicitly. Give adopters a grace period measured in `/release` cycles. INSTEAD of removing the shim once a deadline passes: remove only with an explicit ADR documenting the breaking change and citing the migration test that proves zero adopter remains on the old name.
|
|
144
|
+
|
|
145
|
+
## Anti-patterns it prevents
|
|
146
|
+
|
|
147
|
+
- **Dev-machine-only test.** "It works on my machine." INSTEAD: clone a representative adopter; run their sync hook; confirm zero observable change. The dev machine is one environment among many.
|
|
148
|
+
|
|
149
|
+
- **Clean-break rename motivated by conceptual integrity.** "The new name is clearer." INSTEAD: weigh the rename benefit against migration cost × adopter count. Hold the rename when the math tips against it. Brooks's conceptual-integrity is a budget, not a license.
|
|
150
|
+
|
|
151
|
+
- **Announcement-as-shim.** "We told them in advance." INSTEAD: ship the technical artifact (symlink, alias, forwarding stub) that keeps the old name working. Communication is necessary AND insufficient on its own.
|
|
152
|
+
|
|
153
|
+
- **Single-adopter dismissal.** "Only one adopter uses this surface." INSTEAD: ship the shim anyway. Hyrum's Law applies the moment any adopter observes the surface; declared user count fails as the metric.
|
|
154
|
+
|
|
155
|
+
- **Deprecation window without a real-adopter migration test.** "We gave them three release cycles." INSTEAD: the migration test verifies adopters actually moved; the calendar window verifies only that time passed.
|
|
156
|
+
|
|
157
|
+
## Worked example
|
|
158
|
+
|
|
159
|
+
**Scenario:** Tonight's bet 25e shipped a structural cold-adopter harness. The next bet ships shape b — a sync round-trip harness that runs against a fresh clone. The harness will catch regressions like #336 (bassclef-sync.sh §4 missing PreToolUse template embedding).
|
|
160
|
+
|
|
161
|
+
**The Linus lens applied at PR-review time for #336 fix:**
|
|
162
|
+
|
|
163
|
+
1. **Adopter-observable surface enumeration** — the agent reviewing the #336 PR lists every adopter-observable surface the fix touches: the PreToolUse hook matcher, the settings.json template merged into adopter sessions, the hook firing order, and the stderr contract on BLOCK exits. All four are observable; all four must stay stable across the fix. INSTEAD of accepting a PR body that lists only the bug fix: send back for the surface enumeration.
|
|
164
|
+
|
|
165
|
+
2. **Compat-shim-first** — the fix ships the embedding template AND the test that catches it in the same PR. INSTEAD of "add the embedding now, add the test next bet": same release, or the gap between fix and verification is the window where adopters silently inherit the buggy state.
|
|
166
|
+
|
|
167
|
+
3. **Real-adopter integration test** — the new shape b harness IS the real-adopter test. Once the harness ships (next bet), the #336 fix gets re-run against the cold-adopter clone and the PreToolUse path fires correctly post-sync. INSTEAD of trusting unit tests alone: the harness validates the adopter-observable surface end-to-end.
|
|
168
|
+
|
|
169
|
+
4. **Revert-on-regression default** — if the #336 fix causes any adopter-observable regression (a different hook stops firing, a stderr message changes, the merge logic drops an operator key like #340 did), the fix reverts. INSTEAD of trading adopter trust for the partial win: revert, re-engineer from a different angle, ship without changing the observable surface.
|
|
170
|
+
|
|
171
|
+
5. **Permanent-shim acceptance** — the cp-fallback in additive_merge_settings (the surface #340 patches) is exactly the kind of shim that lives forever. Adopters on older `jq` versions, adopters without `jq` at all, adopters whose settings.json predates the new schema — the cp-fallback covers them all. INSTEAD of removing the fallback once a new merger ships: keep both paths alive; the cost is permanent merge-logic complexity; the benefit is permanent adopter compatibility.
|
|
172
|
+
|
|
173
|
+
The shape-b harness shipping as a methodology-only document with a deferred mechanical layer fails this lens. INSTEAD: the mechanical layer IS the discipline — without the harness running against every PR, the adopter-observable surface stays untested and the next #336-class regression ships silently.
|
|
174
|
+
|
|
175
|
+
## How to apply
|
|
176
|
+
|
|
177
|
+
When designing or reviewing a substrate change:
|
|
178
|
+
|
|
179
|
+
1. **Identify every adopter-observable surface the change touches.** When the surface list is missing from the PR body, the change is not yet ready. INSTEAD of guessing: enumerate explicitly.
|
|
180
|
+
2. **Ask "would an adopter's existing program break?"** INSTEAD of "should it" — would it. Think about every adopter shape: vendored snapshot, thin-pointer, cold-onboarding, partial-sync.
|
|
181
|
+
3. **When the answer is yes, build the shim first.** Symlink, alias, forwarding stub, schema accommodation. Whatever makes the old name keep working.
|
|
182
|
+
4. **Document the shim's retirement condition.** "When all known adopters migrate" or "after N release cycles." INSTEAD of "forever": match Linus's commitment to permanent code when the data demands it.
|
|
183
|
+
5. **Test the shim against a real adopter.** The cold-adopter harness is the substrate's vehicle for this. INSTEAD of dev-machine validation: clone a representative adopter, run their sync hook, confirm zero observable change.
|
|
184
|
+
6. **Ship the shim in the SAME release as the rename.** INSTEAD of "we'll add a shim later": same PR, same release; the gap between rename and shim is the breakage window.
|
|
185
|
+
|
|
186
|
+
## How bassclef channels Linus
|
|
187
|
+
|
|
188
|
+
The discipline lives in:
|
|
189
|
+
|
|
190
|
+
- `.claude/rules/we-dont-break-adopters.md` — methodology layer; cites Hyrum's Law as the theoretical why and Linus's discipline as the operational answer
|
|
191
|
+
- `architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md` — decision layer; adopts the discipline as Tier 1
|
|
192
|
+
- `architecture/dual-repo-flow.md` "Non-breaking changes to adopters" section — architectural layer
|
|
193
|
+
- `scripts/migrate-adopter-references.sh` — adopter self-healing tool for the canonical → bassclef cascade
|
|
194
|
+
- `presence/install/bassclef-sync.template.sh` — the sync surface that adopters depend on; load-bearing per this discipline
|
|
195
|
+
- `scripts/cold-adopter-harness.sh` (bet 25e) + planned shape b sync round-trip (#341) — the real-adopter integration test surface
|
|
196
|
+
- bassclef-upstream#1360 — Phase 2 mechanical layer (pre-rename CI test against representative adopter, redirect registry, versioned sync protocol)
|
|
197
|
+
|
|
198
|
+
## Sources
|
|
199
|
+
|
|
200
|
+
- LKML 2012-12-23 — "We do not break userspace" thread (Linus Torvalds, re: PowerPC syscall change)
|
|
201
|
+
- *Linux Kernel Development* — Robert Love, Addison-Wesley (3rd ed. 2010)
|
|
202
|
+
- *Stability of the Linux ABI* — Linux Foundation Technical Advisory Board (2014)
|
|
203
|
+
- ELC 2015 — Greg Kroah-Hartman, "Driver ABI Stability"
|
|
204
|
+
- LKML "regressions are bugs" thread — multiple instances 2008, 2011, 2014, 2017, 2021
|
|
205
|
+
|
|
206
|
+
## Related luminaries
|
|
207
|
+
|
|
208
|
+
- **Hyrum Wright** — provides the theoretical why (observability creates dependency); Linus provides the operational answer (we just keep userspace working). They pair as why + how.
|
|
209
|
+
- **Michael Nygard** — stability patterns at runtime; ADR lifecycle for the breaking-change decision. Operates at runtime-failure layer where Linus operates at API-surface layer; complementary.
|
|
210
|
+
- **Vaughn Vernon** — anticorruption layer is the structural pattern Linus's discipline produces in practice. When the substrate must do an internal rename, the anticorruption layer between substrate-internal and adopter-observable preserves stability.
|
|
211
|
+
- **Frederick Brooks** — frames the conceptual-integrity-vs-migration-cost tradeoff. Linus picks adopter stability every time; Brooks gives the language to reason about when the tradeoff actually costs more than it saves.
|
|
212
|
+
- **Kent Beck** — adjacent at the test-first layer. Linus's real-adopter integration test IS Beck's red-first discipline applied at the adopter boundary.
|
|
213
|
+
|
|
214
|
+
## Refs
|
|
215
|
+
|
|
216
|
+
- bassclef-upstream#1360 — Phase 2 mechanical layer
|
|
217
|
+
- 2026-06-21 chronicle — the canonical → bassclef cascade + recovery + rule authoring
|
|
218
|
+
- ADR-031 — non-breaking-change adopter discipline (decision layer)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Martin Fowler
|
|
4
|
+
slug: martin-fowler
|
|
5
|
+
claimed_by: [builder, reviewer]
|
|
6
|
+
referenced_by_skills: [pattern-review, decompose, architect-review]
|
|
7
|
+
primary_domain: engineering
|
|
8
|
+
depth: full
|
|
9
|
+
sources:
|
|
10
|
+
- type: book
|
|
11
|
+
title: "Refactoring: Improving the Design of Existing Code (2nd edition)"
|
|
12
|
+
authors: ["Martin Fowler"]
|
|
13
|
+
year: 2018
|
|
14
|
+
url: "https://martinfowler.com/books/refactoring.html"
|
|
15
|
+
isbn: "9780134757599"
|
|
16
|
+
methodology_covered:
|
|
17
|
+
- "Refactoring catalog with named transformations"
|
|
18
|
+
- "When a change is hard, first refactor to make the change easy — then make the easy change"
|
|
19
|
+
- "Code smells: Long Method, Feature Envy, Shotgun Surgery, Primitive Obsession, Data Clumps"
|
|
20
|
+
- type: book
|
|
21
|
+
title: "Patterns of Enterprise Application Architecture"
|
|
22
|
+
authors: ["Martin Fowler"]
|
|
23
|
+
year: 2002
|
|
24
|
+
url: "https://martinfowler.com/books/eaa.html"
|
|
25
|
+
isbn: "9780321127426"
|
|
26
|
+
methodology_covered:
|
|
27
|
+
- "Repository pattern — domain object persistence behind a collection-like interface"
|
|
28
|
+
- "Service Layer — defines an application's boundary and its set of available operations"
|
|
29
|
+
- "Domain Model + Active Record + Data Mapper — three approaches to domain logic and data access"
|
|
30
|
+
- "Unit of Work — maintain a list of objects affected by a business transaction"
|
|
31
|
+
- type: book
|
|
32
|
+
title: "Domain-Specific Languages"
|
|
33
|
+
authors: ["Martin Fowler", "Rebecca Parsons"]
|
|
34
|
+
year: 2010
|
|
35
|
+
url: "https://martinfowler.com/books/dsl.html"
|
|
36
|
+
isbn: "9780321712943"
|
|
37
|
+
methodology_covered:
|
|
38
|
+
- "Internal vs external DSL design choices"
|
|
39
|
+
- "DSL design patterns — when to build, when to embed, when to skip"
|
|
40
|
+
- type: blog_post
|
|
41
|
+
title: "martinfowler.com (primary methodology venue)"
|
|
42
|
+
authors: ["Martin Fowler"]
|
|
43
|
+
year: 2025
|
|
44
|
+
url: "https://martinfowler.com/"
|
|
45
|
+
methodology_covered:
|
|
46
|
+
- "Continuous refactoring as engineering discipline, not a scheduled event"
|
|
47
|
+
- "Microservices framing + architectural design notes"
|
|
48
|
+
- "Patterns evolve through the blog before landing in books"
|
|
49
|
+
verification_status: verified
|
|
50
|
+
description: "\"Any fool can write code that a computer can understand."
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
# Martin Fowler
|
|
54
|
+
|
|
55
|
+
## Signature
|
|
56
|
+
|
|
57
|
+
*"Any fool can write code that a computer can understand. Good programmers write code that humans can understand. Is the code in the right place?"*
|
|
58
|
+
|
|
59
|
+
ThoughtWorks Chief Scientist. Author of **Refactoring**, **Patterns of
|
|
60
|
+
Enterprise Application Architecture**, **Domain-Specific Languages**,
|
|
61
|
+
and countless seminal essays. The bassclef voice on code smells,
|
|
62
|
+
refactoring, and enterprise patterns.
|
|
63
|
+
|
|
64
|
+
## Core methods
|
|
65
|
+
|
|
66
|
+
- **Code smells catalog** — Long Method, Large Class, Feature Envy,
|
|
67
|
+
Shotgun Surgery, Primitive Obsession, Data Clumps, and dozens more.
|
|
68
|
+
Named patterns make smells recognizable on sight.
|
|
69
|
+
- **Refactoring catalog** — Extract Method, Move Method, Replace
|
|
70
|
+
Conditional with Polymorphism, Introduce Parameter Object, and ~70
|
|
71
|
+
others. Each is a mechanical transformation that preserves behavior.
|
|
72
|
+
- **Enterprise patterns (PoEAA)** — Repository, Unit of Work, Service
|
|
73
|
+
Layer, Domain Model, Table Data Gateway, Data Mapper. Vocabulary for
|
|
74
|
+
how business logic meets persistence.
|
|
75
|
+
- **Strangler Fig pattern** — migrate legacy by routing calls through
|
|
76
|
+
a new layer while old shrinks. Reversible at every step.
|
|
77
|
+
- **Expand-and-contract schema migrations** — add new column → backfill
|
|
78
|
+
→ switch reads → remove old column. Zero-downtime migration pattern.
|
|
79
|
+
|
|
80
|
+
## When to channel this luminary
|
|
81
|
+
|
|
82
|
+
When the primary risk is that existing code will become unworkable
|
|
83
|
+
under change. Fowler dominates for refactoring work, legacy migration,
|
|
84
|
+
pattern selection in Construction, and code review. Pair with Uncle Bob
|
|
85
|
+
(SOLID principles), Beck (TDD), and Feathers (legacy code) for the
|
|
86
|
+
engineering quality stack.
|
|
87
|
+
|
|
88
|
+
Do NOT channel Fowler as primary for: greenfield architecture (use
|
|
89
|
+
Simon Brown or Evans), pure language design, or brand-new frameworks
|
|
90
|
+
where patterns haven't settled.
|
|
91
|
+
|
|
92
|
+
## Stack translation
|
|
93
|
+
|
|
94
|
+
In Next.js + Prisma + TypeScript:
|
|
95
|
+
|
|
96
|
+
- **Repository pattern** → `lib/repositories/deal.ts` wraps Prisma
|
|
97
|
+
queries; routes and services call the repository, not Prisma
|
|
98
|
+
directly. Decouples storage from business logic.
|
|
99
|
+
- **Service Layer** → `lib/services/ScoringService.ts` orchestrates
|
|
100
|
+
multiple repositories + policies for a single business operation.
|
|
101
|
+
- **Refactoring before feature** — when a change is hard, first refactor
|
|
102
|
+
to make the change easy, then make the easy change.
|
|
103
|
+
- **Strangler Fig** → route old API calls through a facade that
|
|
104
|
+
progressively delegates to new implementation; remove old route
|
|
105
|
+
only when all traffic has shifted.
|
|
106
|
+
- **Expand-and-contract migrations** → Prisma migrations add nullable
|
|
107
|
+
column first, backfill via job, then add NOT NULL constraint, then
|
|
108
|
+
remove old column in subsequent migration.
|
|
109
|
+
|
|
110
|
+
## Anti-patterns it prevents
|
|
111
|
+
|
|
112
|
+
- **Shotgun Surgery** — one logical change touches many unrelated files.
|
|
113
|
+
Signal that abstraction is missing; responsibility is smeared.
|
|
114
|
+
- **Feature Envy** — a method/component uses more of another's data
|
|
115
|
+
than its own. The logic belongs there, not here.
|
|
116
|
+
- **Primitive Obsession** — using primitive types (string, number) when
|
|
117
|
+
a domain concept (DealId, Money, EmailAddress) would clarify intent.
|
|
118
|
+
- **Long Parameter List** — functions with 6+ params. Extract Parameter
|
|
119
|
+
Object.
|
|
120
|
+
- **Data Clumps** — the same group of fields appearing together across
|
|
121
|
+
many places. Extract a class/type for the clump.
|
|
122
|
+
- **Inappropriate Intimacy** — class A peering into class B's privates.
|
|
123
|
+
Violates encapsulation; signals poor boundary placement.
|
|
124
|
+
|
|
125
|
+
## Worked example
|
|
126
|
+
|
|
127
|
+
For POA's deal-enrichment pipeline:
|
|
128
|
+
|
|
129
|
+
Fowler's approach:
|
|
130
|
+
- Identify **code smells** in current implementation: `enrichmentService.ts`
|
|
131
|
+
has 300 lines (Large Class), nested callbacks (Complex Method), and
|
|
132
|
+
direct Prisma + vendor-API calls (Feature Envy + Inappropriate Intimacy).
|
|
133
|
+
- Apply **Extract Class**: split into `EnrichmentOrchestrator`,
|
|
134
|
+
`EnrichmentRepository`, and `EnrichmentVendorAdapter`.
|
|
135
|
+
- Apply **Replace Conditional with Polymorphism**: if-else over enrichment
|
|
136
|
+
provider types becomes a Strategy with `IEnrichmentProvider` interface.
|
|
137
|
+
- Apply **Repository pattern** to the Prisma access.
|
|
138
|
+
- **Strangler Fig** the migration: new code runs behind feature flag,
|
|
139
|
+
old code runs in parallel with comparison logging, switch cutover
|
|
140
|
+
once comparison shows parity.
|
|
141
|
+
|
|
142
|
+
What Fowler would NOT produce: a rewrite from scratch. Fowler's
|
|
143
|
+
discipline is incremental, behavior-preserving refactoring — not
|
|
144
|
+
greenfield redos.
|
|
145
|
+
|
|
146
|
+
## Sources
|
|
147
|
+
|
|
148
|
+
- *Refactoring: Improving the Design of Existing Code* — Fowler,
|
|
149
|
+
Addison-Wesley (2nd ed 2018)
|
|
150
|
+
- *Patterns of Enterprise Application Architecture* — Fowler (2002)
|
|
151
|
+
- *Domain-Specific Languages* — Fowler (2010)
|
|
152
|
+
- *NoSQL Distilled* — Fowler, Sadalage (2012)
|
|
153
|
+
- martinfowler.com — primary site with decades of essays, bliki entries
|
|
154
|
+
|
|
155
|
+
## Related luminaries
|
|
156
|
+
|
|
157
|
+
- **Robert C. Martin** — SOLID + Clean Code; pair with Fowler's refactoring
|
|
158
|
+
catalog for complete engineering-quality practice.
|
|
159
|
+
- **Kent Beck** — TDD + Extreme Programming; Fowler credits Beck for
|
|
160
|
+
much of the refactoring discipline.
|
|
161
|
+
- **Michael Feathers** — Working with Legacy Code extends Fowler's
|
|
162
|
+
refactoring to the before-state (no tests exist yet).
|
|
163
|
+
- **Eric Evans** — DDD complements Fowler's Service Layer + Repository
|
|
164
|
+
at the strategic domain-modeling level.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Michael Feathers
|
|
4
|
+
slug: michael-feathers
|
|
5
|
+
claimed_by: [builder, reviewer]
|
|
6
|
+
referenced_by_skills: [verify, pattern-review]
|
|
7
|
+
primary_domain: engineering
|
|
8
|
+
depth: full
|
|
9
|
+
solves_problems_brownfield:
|
|
10
|
+
- "Codebase has no tests; any change risks unknown breakage across the system"
|
|
11
|
+
- "A class or function can't be tested without instantiating half the application"
|
|
12
|
+
- "New behavior needs to be added adjacent to legacy code that can't be safely changed"
|
|
13
|
+
- "A module is deeply coupled to its dependencies (database, filesystem, clock); tests require real infrastructure"
|
|
14
|
+
solves_problems_greenfield:
|
|
15
|
+
- "Designing a new module that will be introduced to a legacy system; seams must be planned from the start"
|
|
16
|
+
- "Building a service layer that wraps a third-party system; the wrap method must stay testable as the third-party evolves"
|
|
17
|
+
- "Planning a brownfield rescue effort; need a staged safety-net strategy before any refactoring begins"
|
|
18
|
+
- "Establishing the testing discipline a team will use as a system ages"
|
|
19
|
+
anti_patterns:
|
|
20
|
+
- "Greenfield systems with modern tooling and existing test culture — Feathers is the brownfield specialist"
|
|
21
|
+
- "Systems where a full rewrite is genuinely the right call and incremental safety-net building would slow the work"
|
|
22
|
+
- "Pure architectural redesigns where the code isn't the constraint"
|
|
23
|
+
sources:
|
|
24
|
+
- type: book
|
|
25
|
+
title: "Working Effectively with Legacy Code"
|
|
26
|
+
authors: ["Michael C. Feathers"]
|
|
27
|
+
year: 2004
|
|
28
|
+
url: "https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052"
|
|
29
|
+
isbn: "9780131177055"
|
|
30
|
+
methodology_covered:
|
|
31
|
+
- "Characterization tests — pin current behavior before touching legacy code"
|
|
32
|
+
- "Seam identification — find places where behavior can change without editing in place (preprocessor, link, object seams)"
|
|
33
|
+
- "Sprout method / sprout class — add new testable behavior adjacent to legacy code"
|
|
34
|
+
- "Wrap method / wrap class — change behavior by wrapping; original is untouched"
|
|
35
|
+
- "Legacy code definition — code without tests"
|
|
36
|
+
- type: website
|
|
37
|
+
title: "Michael Feathers blog"
|
|
38
|
+
authors: ["Michael Feathers"]
|
|
39
|
+
year: 2008
|
|
40
|
+
url: "https://michaelfeathers.silvrback.com/"
|
|
41
|
+
methodology_covered:
|
|
42
|
+
- "Ongoing writing on software design, legacy systems, and refactoring discipline"
|
|
43
|
+
verification_status: verified
|
|
44
|
+
description: "\"Legacy code is code without tests. Everything else is detail.\" [ref:1]"
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
# Michael Feathers
|
|
48
|
+
|
|
49
|
+
## Signature
|
|
50
|
+
|
|
51
|
+
*"Legacy code is code without tests. Everything else is detail."* [ref:1]
|
|
52
|
+
|
|
53
|
+
Author of **Working Effectively with Legacy Code** (2004) [ref:1]. The bassclef voice on bringing old, test-less, or tightly-coupled code under control without a rewrite. Where Beck starts with TDD on a clean slate, Feathers starts with the code that actually exists in production today.
|
|
54
|
+
|
|
55
|
+
## Core methods
|
|
56
|
+
|
|
57
|
+
- **Characterization tests** — Write tests that describe what the code currently does, not what it should do. Before touching anything, pin the current behavior. These tests are the safety net that makes refactoring safe. Only after pinning do you change behavior — and changing behavior means writing a failing test first. [ref:1]
|
|
58
|
+
- **Seam identification** — A seam is a place where you can change the program's behavior without editing in place. Seams come in three types: preprocessor seams (build-time), link seams (object-file substitution), and object seams (subclassing or interface injection). Finding seams is finding where you can insert a test double without rewriting the production code. [ref:1]
|
|
59
|
+
- **Sprout method / sprout class** — When you need to add new behavior to a function that is too risky to touch, add the new behavior in a new method or class that you CAN test. Wire the new code into the legacy code with minimal contact. The sprout is independently testable; the legacy code is preserved. [ref:1]
|
|
60
|
+
- **Wrap method / wrap class** — When you need to change a method's behavior, wrap it: create a new method (or class) that calls the original and adds or modifies behavior around it. The wrap is testable; the original is untouched. Like Decorator, but driven by safety rather than design. [ref:1]
|
|
61
|
+
|
|
62
|
+
## When to channel this luminary
|
|
63
|
+
|
|
64
|
+
When the codebase has real production code that lacks tests, or where tests exist but the dependencies are so tangled that changing anything is risky. Feathers dominates legacy system rescue: adding a feature to a 10-year-old module, extracting a service from a monolith, or incrementally stabilizing a system before a modernization effort begins. Pair with Fowler (refactoring catalog) once the safety net is in place.
|
|
65
|
+
|
|
66
|
+
INSTEAD of channeling Feathers when the team is starting fresh: use Beck's TDD from the first line of production code. Feathers handles the before-state that TDD assumes away.
|
|
67
|
+
|
|
68
|
+
## Stack translation
|
|
69
|
+
|
|
70
|
+
In Next.js + Prisma + TypeScript:
|
|
71
|
+
|
|
72
|
+
- **Characterization tests** — for a legacy API route, write integration tests against its actual behavior (inputs, outputs, side effects) before touching it. Use vitest + supertest or a test client. Pin the response shapes that downstream code depends on.
|
|
73
|
+
- **Seam identification** — TypeScript interfaces are the primary seam type. A service function that imports Prisma directly has no seam; extract an interface and inject via constructor or parameter. The seam enables swapping a real DB client for a test double.
|
|
74
|
+
- **Sprout method** — a 200-line server action that handles validation + database + notification: sprout the new validation logic into a standalone function tested in isolation. Wire it into the existing action with a single call. Ship both together.
|
|
75
|
+
- **Wrap class** — a third-party SDK (BizBuySell, an email provider) with no seam: create a thin wrapper class that implements your own interface and delegates to the SDK. Tests use a test double; production uses the wrapper. Swap SDKs later without touching callers.
|
|
76
|
+
|
|
77
|
+
## Anti-patterns it prevents
|
|
78
|
+
|
|
79
|
+
- **Edit and pray** — making a change to legacy code without tests and hoping nothing breaks. Feathers's characterization tests create the safety net before any edit, making each change verifiable rather than hopeful.
|
|
80
|
+
- **The big refactor** — attempting to redesign a legacy system comprehensively before adding tests. Feathers insists: tests come first, then refactoring. The comprehensive redesign without tests is just a different legacy system that happens to be new. [ref:1]
|
|
81
|
+
- **Dependency grabbing** — adding a new dependency to a legacy class because it was "easier." Each new dependency reduces the seam surface and makes future testing harder. Feathers's discipline: find the seam, inject the dependency, preserve optionality.
|
|
82
|
+
- **Sprout regression** — the new behavior works; the old behavior was accidentally changed. Characterization tests catch this: the old behavior is pinned; if any characterization test fails, something changed that was not intended to change.
|
|
83
|
+
|
|
84
|
+
## Worked example
|
|
85
|
+
|
|
86
|
+
For POA's legacy BizBuySell scraper module:
|
|
87
|
+
|
|
88
|
+
The scraper function is 300 lines; it fetches, parses, writes to the database, and sends a Slack notification. No tests. Before any change:
|
|
89
|
+
|
|
90
|
+
1. **Characterization test**: run the scraper against a recorded HTTP fixture; capture the database rows it writes and the Slack payload it sends. These are the characterization tests. Any change that alters these outputs is a signal, not a surprise.
|
|
91
|
+
|
|
92
|
+
2. **Seam identification**: the database write is not injectable — it calls Prisma directly. INSTEAD: extract a `ScrapeResultWriter` interface; pass it as a parameter in tests. The seam now exists.
|
|
93
|
+
|
|
94
|
+
3. **Sprout method**: the new requirement is deduplication before writing. INSTEAD of editing the 300-line function: sprout `deduplicateResults(incoming: ScrapeResult[], existing: ScrapeResult[]): ScrapeResult[]` — pure function, fully testable. Wire it into the legacy function with one line.
|
|
95
|
+
|
|
96
|
+
4. **Verify**: characterization tests still pass (old behavior preserved). New unit tests cover the deduplication logic independently.
|
|
97
|
+
|
|
98
|
+
## Sources
|
|
99
|
+
|
|
100
|
+
- *Working Effectively with Legacy Code* — Feathers, Prentice Hall (2004) [ref:1]
|
|
101
|
+
- michaelfeathers.silvrback.com — primary blog [ref:2]
|
|
102
|
+
- "Getting Empirical About Refactoring" — Feathers, various conference talks
|
|
103
|
+
|
|
104
|
+
## Related luminaries
|
|
105
|
+
|
|
106
|
+
- **Martin Fowler** — Refactoring is the next step after Feathers's safety net is in place; Fowler's catalog assumes tests exist, Feathers builds the before-state.
|
|
107
|
+
- **Kent Beck** — TDD is the end state Feathers helps teams reach incrementally.
|
|
108
|
+
- **Robert C. Martin** — Clean Code principles are the target; Feathers handles the path from legacy reality to that target.
|
|
109
|
+
- **Hunt & Thomas** — DRY and orthogonality are easier to maintain from the start; Feathers is the recovery discipline when they were not.
|
|
110
|
+
|
|
111
|
+
## Substrate-as-system anchor (bassclef bet 27c, 2026-06-27)
|
|
112
|
+
|
|
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
|
+
|
|
115
|
+
The bet 27c foundation ships:
|
|
116
|
+
- `standards/mechanism-fidelity.md` (standard tier) — audit method spec; Feathers-style characterization tests pin every rule's mechanism claim
|
|
117
|
+
- `lib/mechanism-fidelity.sh` — shared scanner that runs the 5-step verification chain
|
|
118
|
+
- `.claude/skills/audit-rule-mechanism-fidelity/SKILL.md` — operator-invocable audit (Feathers + Beck primary luminaries)
|
|
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` (standard tier) — auto-loaded tenet rule (cites Feathers as primary)
|
|
121
|
+
- `.claude/skills/architect-review/SKILL.md` — amendment makes Feathers + Beck + Saltzer-Schroeder verification-side primaries alongside Brooks + Linus comprehension-side primaries
|
|
122
|
+
|
|
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.
|
|
124
|
+
|
|
125
|
+
The substrate as a system needs Feathers as much as application code does. This anchor citation reflects that.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Michael Nygard
|
|
4
|
+
slug: michael-nygard
|
|
5
|
+
claimed_by: [architect]
|
|
6
|
+
referenced_by_skills: [architect-review, decompose]
|
|
7
|
+
primary_domain: architecture
|
|
8
|
+
depth: full
|
|
9
|
+
solves_problems_brownfield:
|
|
10
|
+
- "A single slow external API call hangs the entire application because the thread pool exhausts"
|
|
11
|
+
- "One failing service causes a cascade that takes down services with no direct dependency on it"
|
|
12
|
+
- "The application works fine locally and in staging but fails in production under real load patterns"
|
|
13
|
+
- "There is no defined behavior when an external integration is unavailable"
|
|
14
|
+
solves_problems_greenfield:
|
|
15
|
+
- "Designing a service that will integrate with external systems of unknown reliability"
|
|
16
|
+
- "Planning the failure modes of a distributed system before any code is written"
|
|
17
|
+
- "Building a system that continues operating (in degraded mode) when individual integrations fail"
|
|
18
|
+
- "Establishing the production-readiness criteria a system must meet before going live"
|
|
19
|
+
anti_patterns:
|
|
20
|
+
- "Single-process applications with no external integrations — stability patterns add overhead without value"
|
|
21
|
+
- "Batch systems that run to completion and exit — patterns designed for long-lived services"
|
|
22
|
+
- "Early-stage prototypes where production reliability is deliberately out of scope"
|
|
23
|
+
sources:
|
|
24
|
+
- type: book
|
|
25
|
+
title: "Release It! Design and Deploy Production-Ready Software"
|
|
26
|
+
authors: ["Michael T. Nygard"]
|
|
27
|
+
year: 2018
|
|
28
|
+
url: "https://pragprog.com/titles/mnee2/release-it-second-edition/"
|
|
29
|
+
isbn: "9781680502398"
|
|
30
|
+
methodology_covered:
|
|
31
|
+
- "Circuit breaker — stateful wrapper with Closed/Open/Half-Open states; prevents cascading failure"
|
|
32
|
+
- "Bulkhead — partition resources by concern; failure in one partition cannot exhaust shared resources"
|
|
33
|
+
- "Timeout — every remote call must have connect + read timeout values"
|
|
34
|
+
- "Fail fast — reject requests immediately when a known failure condition exists"
|
|
35
|
+
- "Stability anti-patterns — cascading failure, blocked threads, self-denial, integration point failures"
|
|
36
|
+
- type: book
|
|
37
|
+
title: "Release It! Design and Deploy Production-Ready Software (1st edition)"
|
|
38
|
+
authors: ["Michael T. Nygard"]
|
|
39
|
+
year: 2007
|
|
40
|
+
url: "https://pragprog.com/titles/mnee/release-it/"
|
|
41
|
+
methodology_covered:
|
|
42
|
+
- "Original stability patterns catalog"
|
|
43
|
+
- type: blog_post
|
|
44
|
+
title: "Documenting Architecture Decisions"
|
|
45
|
+
authors: ["Michael Nygard"]
|
|
46
|
+
year: 2011
|
|
47
|
+
url: "https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions"
|
|
48
|
+
methodology_covered:
|
|
49
|
+
- "ADR (Architecture Decision Record) format — Title, Status, Context, Decision, Consequences"
|
|
50
|
+
- "Originated the ADR format; widely adopted across software organizations"
|
|
51
|
+
verification_status: verified
|
|
52
|
+
description: "\"Everything fails. Every remote call can hang. Every integration point is a liability. Design your system to be stable in the presence of failure, not to assume failure away.\"…"
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
# Michael Nygard
|
|
56
|
+
|
|
57
|
+
## Signature
|
|
58
|
+
|
|
59
|
+
*"Everything fails. Every remote call can hang. Every integration point is a liability. Design your system to be stable in the presence of failure, not to assume failure away."* [ref:1]
|
|
60
|
+
|
|
61
|
+
Author of **Release It! Design and Deploy Production-Ready Software** (2nd ed 2018) [ref:1]. Coined the ADR (Architecture Decision Record) format in his 2011 blog post [ref:3]. The bassclef voice on production-grade software: the stability patterns that prevent cascading failures and the anti-patterns that cause them.
|
|
62
|
+
|
|
63
|
+
## Core methods
|
|
64
|
+
|
|
65
|
+
- **Circuit breaker** — A stateful wrapper around an integration point (external API, database, downstream service). Three states: Closed (normal operation), Open (fast-fail all calls without attempting contact), Half-Open (probe with one call to test recovery). When the failure rate exceeds a threshold, the circuit opens. Callers fail fast rather than hanging. After a timeout, one call is allowed through; if it succeeds, the circuit closes. [ref:1]
|
|
66
|
+
- **Bulkhead** — Partition resources by concern so that failure in one partition cannot exhaust resources needed by another. Named after the ship bulkhead that prevents water ingress in one compartment from sinking the ship. In software: separate thread pools for different integrations, separate connection pools for different databases, separate queue workers for different job types. [ref:1]
|
|
67
|
+
- **Timeout** — Every remote call must have a timeout. A call with no timeout can block a thread indefinitely. Two values needed: connect timeout (how long to wait for connection), read timeout (how long to wait for response). Timeouts must be tuned: too short creates unnecessary failures; too long creates unacceptable UX. [ref:1]
|
|
68
|
+
- **Fail fast** — When a system knows it cannot fulfill a request (circuit open, connection pool exhausted, downstream service unavailable), it should fail immediately with a clear error rather than accepting the request and failing slowly. Fail fast enables callers to retry or redirect; slow failure degrades the entire system. [ref:1]
|
|
69
|
+
|
|
70
|
+
## When to channel this luminary
|
|
71
|
+
|
|
72
|
+
When the system will integrate with any external dependency (databases, third-party APIs, downstream services, message queues) and failure modes of those integrations need explicit design. Nygard dominates production readiness reviews, architecture reviews before launch, and any system that must remain partially operational when integrations fail. Pair with Newman (service decomposition that creates the integration boundaries Nygard's patterns protect), Hohpe (integration patterns at the messaging layer), and Brown (ADRs for recording stability-pattern decisions).
|
|
73
|
+
|
|
74
|
+
INSTEAD of channeling Nygard for internal application logic: stability patterns are for integration points and external boundaries. Business logic, UI composition, and domain modeling are governed by Evans, Cockburn, and Cooper. Nygard's scope is the edges where your system meets systems you cannot control.
|
|
75
|
+
|
|
76
|
+
## Stack translation
|
|
77
|
+
|
|
78
|
+
In Next.js + Prisma + external APIs (BizBuySell, Anthropic, email providers):
|
|
79
|
+
|
|
80
|
+
- **Circuit breaker** — wrap each external API client (BizBuySell scraper, Anthropic enrichment, email delivery) in a circuit breaker. When the API is unavailable or slow, the circuit opens; callers receive a fast failure and can queue the work for retry. Libraries: `opossum` (Node.js) or a simple state machine per integration.
|
|
81
|
+
- **Bulkhead** — BullMQ workers for enrichment, for email, and for scraping use separate queues with separate concurrency limits. A spike in enrichment work cannot starve the email workers.
|
|
82
|
+
- **Timeout** — every `fetch()` call to an external API uses `AbortSignal.timeout()`. Anthropic API calls that exceed 30s abort; enrichment jobs that exceed 60s fail and are retried. Prisma connection pool has an explicit pool timeout.
|
|
83
|
+
- **Fail fast** — server actions that depend on an unavailable service return a clear `503` rather than hanging. The UI shows a retry state rather than a spinner.
|
|
84
|
+
- **ADRs** — every stability-pattern decision is recorded in `architecture/decisions/`: "ADR-009: circuit breaker for BizBuySell API — context, decision, consequences." [ref:3]
|
|
85
|
+
|
|
86
|
+
## Anti-patterns it prevents
|
|
87
|
+
|
|
88
|
+
- **Cascading failure** — a slow external API causes thread pool exhaustion, which causes queue buildup, which causes memory pressure, which causes the entire application to fail. Circuit breaker and bulkhead prevent this: failures stay contained within their integration boundary. [ref:1]
|
|
89
|
+
- **Blocked threads** — a database query or HTTP call with no timeout holds a thread indefinitely. Ten such calls block ten threads. The system accepts new requests it cannot service.
|
|
90
|
+
INSTEAD: set connect + read timeouts on every remote call; set a maximum wait in every queue consumer. Threads that time out release and become available for other work.
|
|
91
|
+
- **Self-denial** — the application triggers its own overload: a scheduled job fans out thousands of API calls simultaneously, the API rate-limits, all calls fail, the job retries them immediately, the rate-limit worsens. Circuit breaker + exponential backoff prevent the retry cascade. [ref:1]
|
|
92
|
+
- **Test harness gap** — the system was tested with a fast, reliable test double for every integration; production uses real integrations that are sometimes slow or unavailable. The failure paths were tested with mocks that never fail.
|
|
93
|
+
INSTEAD: include chaos tests (slow responses, connection drops, partial failures) in the integration test suite. The failure behavior must be verified, not assumed.
|
|
94
|
+
|
|
95
|
+
## Worked example
|
|
96
|
+
|
|
97
|
+
For POA's BizBuySell scraper integration:
|
|
98
|
+
|
|
99
|
+
**The failure mode without patterns**: BizBuySell returns 503 for 5-10 minutes. The scraper worker holds ten open HTTP connections waiting for responses that will not arrive; the BullMQ queue backs up; the worker crashes; manual intervention is required.
|
|
100
|
+
|
|
101
|
+
**With stability patterns**:
|
|
102
|
+
1. **Timeout**: every BizBuySell fetch has a 10-second timeout. After 10 seconds, the call fails with a timeout error.
|
|
103
|
+
2. **Circuit breaker**: after five consecutive timeouts within 60 seconds, the circuit opens. All subsequent scrape attempts fail fast. The circuit enters Half-Open after 60 seconds and allows one probe call through.
|
|
104
|
+
3. **Bulkhead**: the scraper uses a separate BullMQ queue (max 5 concurrent workers) from the enrichment queue (max 10 workers). A BizBuySell outage fills the scraper queue but cannot starve enrichment workers.
|
|
105
|
+
4. **ADR**: "ADR-010: BizBuySell API stability patterns — context: BizBuySell has 99.5% SLA (~43 hours downtime/year). We need scraping to be non-blocking during outages. Decision: circuit breaker with 5-failure threshold, 60s recovery. Consequences: scrape jobs may lag 60s during recovery; acceptable given the non-real-time nature of scrape data."
|
|
106
|
+
|
|
107
|
+
## Sources
|
|
108
|
+
|
|
109
|
+
- *Release It! Design and Deploy Production-Ready Software* — Nygard, Pragmatic Bookshelf (1st ed 2007, 2nd ed 2018) [ref:1][ref:2]
|
|
110
|
+
- "Documenting Architecture Decisions" — Nygard, cognitect.com blog (2011) — original ADR proposal [ref:3]
|
|
111
|
+
- thinkrelevance.com / cognitect.com — Nygard's primary writing venues (thinkrelevance.com was the predecessor domain to cognitect.com)
|
|
112
|
+
|
|
113
|
+
## Related luminaries
|
|
114
|
+
|
|
115
|
+
- **Sam Newman** — Microservices create the service boundaries where Nygard's stability patterns apply. Newman decomposes; Nygard hardens the resulting integration points.
|
|
116
|
+
- **Gregor Hohpe** — EIP messaging patterns operate at the same integration boundaries. Hohpe's dead letter channels and Nygard's circuit breakers are complementary: messaging + stability.
|
|
117
|
+
- **Simon Brown** — ADR format (Nygard's invention) is central to Brown's architecture communication approach. C4 documents the structure; ADRs record the stability decisions.
|
|
118
|
+
- **Alistair Cockburn** — Hexagonal architecture creates explicit integration ports; Nygard's stability patterns wrap those ports.
|