@clawhub-yixiao1032-publish-7476c994cb
以《周易》本经原著为底,系统收集并逐一拆解市面上几乎所有可获取的同类 divination agents / skills / 程序, 汲取百家之长,取其精华,去其糟粕,最终打磨成这一套更准确、更完整、更好用的周易系统。它把同类产品里 最成熟的交互、百科式组织、起卦体验和规则呈现方式整合进来,同时去掉卦序错误、原...
---
name: zhouyi-benjing-oracle
clawhub-slug: zhouyi-benjing-oracle
description: |
以《周易》本经原著为底,系统收集并逐一拆解市面上几乎所有可获取的同类 divination agents / skills / 程序,
汲取百家之长,取其精华,去其糟粕,最终打磨成这一套更准确、更完整、更好用的周易系统。它把同类产品里
最成熟的交互、百科式组织、起卦体验和规则呈现方式整合进来,同时去掉卦序错误、原文截断、白话混原文、
未校验命理乱炖和伪精确排盘,让《周易》回到原著,也把产品做到更像市面上值得长期留下来的那一个。
Built on the original Zhouyi text, this skill was forged by systematically collecting and dissecting virtually
every comparable divination agent, skill, and app we could access, absorbing the best ideas across the field
while stripping away the noise. We kept the strongest UX, encyclopedia structure, casting flow, and rule
presentation, and removed the usual flaws: wrong hexagram mappings, truncated canon, paraphrase mixed into
scripture, unverified metaphysics mashups, and fake precision. The result is a cleaner, stronger, and more
enduring I Ching product.
license: MIT-0
compatibility:
platforms:
- claude-code
- claude-ai
- api
metadata:
author: pineapple
version: "1.0.0"
tags: ["zhouyi", "yijing", "iching", "周易", "易经", "六十四卦", "占卜", "卦辞", "爻辞"]
openclaw:
emoji: "☯"
skillKey: "zhouyi-benjing-oracle"
requires:
bins:
- node
---
# 周易本经占筮
这是一个以《周易》本经为底座的技能包。它包含三部分能力:
1. `起卦`:三钱或蓍草起卦,按七种变爻规则取辞。
2. `查卦`:查六十四卦卦辞、爻辞、用九、用六。
3. `路由`:给出术数百科式总览,但只把周易本经模块当作已校验核心。
## 何时使用
当用户出现以下需求时,优先使用本技能:
- “帮我起一卦”
- “用周易看一下这件事”
- “查乾卦/屯卦/某句卦辞”
- “这个卦该看哪条爻辞”
- “周易和六爻/梅花/八字有什么区别”
- “我想看这个系统怎么用”
以下需求不要冒充已实现高精度:
- 八字排盘
- 奇门遁甲排盘
- 紫微斗数排盘
- 六爻纳甲断卦
这些内容目前只在 `术数百科` 中作为资料要求和边界说明存在。
## 默认工作流
### 1. 现场起卦
优先调用:
```bash
node scripts/zhouyi_cli.js cast --question "我是否该推进这次合作" --method coin --json
```
可选方法:
- `coin`:三钱法,6/7/8/9 概率为 1/8、3/8、3/8、1/8
- `yarrow`:蓍草概率模拟,6/7/8/9 概率为 1/16、5/16、7/16、3/16
如果需要复现结果,可带种子:
```bash
node scripts/zhouyi_cli.js cast --question "测试" --method coin --seed demo --json
```
### 2. 查某一卦
```bash
node scripts/zhouyi_cli.js lookup --name 乾 --json
node scripts/zhouyi_cli.js lookup --number 3 --json
```
### 3. 按关键词搜原文
```bash
node scripts/zhouyi_cli.js search --query "十年乃字" --json
node scripts/zhouyi_cli.js search --query "利涉大川" --json
```
### 4. 看术数百科路由
```bash
node scripts/zhouyi_cli.js catalog --json
node scripts/zhouyi_cli.js catalog --grade S --query 周易 --json
```
### 5. 打开内置网页
如果用户想要直接操作本地网页,打开根目录的 `index.html` 即可。网页包含:
- 周易本经占筮界面
- 六十四卦本经库
- 术数百科导航
- 近占记录
## 解读规则
调用 `cast` 后,按下列规则取辞:
1. 六爻不变:用本卦卦辞。
2. 一爻变:用该动爻爻辞。
3. 二爻变:用两个动爻爻辞,以上爻为主。
4. 三爻变:用本卦卦辞与变卦卦辞。
5. 四爻变:用两个静爻爻辞,以下爻为主。
6. 五爻变:用变卦中唯一静爻所对应的爻辞。
7. 六爻皆变:乾用用九,坤用用六,其余用变卦卦辞。
## 输出原则
1. 先交代本次取辞规则。
2. 再引用本经原文。
3. 最后给白话解释。
4. 不把解释说成确定命令。
5. 不用未校验体系污染周易本经结论。
## 参考资源
- 产品与验证说明:`references/README.md`
- 小白使用说明:`references/user-guide-zh.md`
- 本经底本:`references/zhouyi-benjing-source.txt`
## 维护命令
重建本经数据:
```bash
python3 scripts/build_zhouyi_data.py
```
运行校验:
```bash
node tests/verify_zhouyi_system.js
node tests/verify_system_catalog.js
node tests/verify_cli.js
```
FILE:_meta.json
{
"slug": "zhouyi-benjing-oracle",
"version": "1.0.0"
}
FILE:index.html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>周易本经占筮</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main class="shell">
<section class="oracle">
<header class="masthead">
<div>
<p class="eyebrow">周易本经 · 六爻取辞 · 易问</p>
<h1>周易本经占筮</h1>
</div>
<div class="bagua-ring" aria-hidden="true">
<span>☰</span><span>☱</span><span>☲</span><span>☳</span>
<span>☴</span><span>☵</span><span>☶</span><span>☷</span>
</div>
</header>
<section class="casting-panel">
<label class="question-label" for="question">当下之问</label>
<textarea
id="question"
rows="4"
placeholder="例如:我是否应该在这个月推进新的合作?"
></textarea>
<div class="controls">
<div class="mode-switch" role="group" aria-label="起卦方式">
<button class="mode-button active" type="button" data-method="coin">三钱</button>
<button class="mode-button" type="button" data-method="yarrow">蓍草</button>
</div>
<button class="cast-button" id="castButton" type="button">
<span class="button-icon" aria-hidden="true">◎</span>
起卦
</button>
</div>
</section>
</section>
<section class="atlas-section">
<div class="section-heading">
<div>
<p class="eyebrow">全体系导航</p>
<h2>术数百科</h2>
</div>
<div class="atlas-search">
<input id="catalogSearch" type="search" placeholder="搜索体系、用途或资料要求" />
</div>
</div>
<div class="grade-filter" id="catalogFilters" role="group" aria-label="精度筛选">
<button class="filter-button active" type="button" data-grade="all">全部</button>
<button class="filter-button" type="button" data-grade="S">S 级</button>
<button class="filter-button" type="button" data-grade="B">B 级</button>
<button class="filter-button" type="button" data-grade="C">C 级</button>
</div>
<div id="catalogGrid" class="catalog-grid"></div>
</section>
<section class="library-section">
<div class="section-heading">
<div>
<p class="eyebrow">六十四卦</p>
<h2>本经卦库</h2>
</div>
<div class="atlas-search">
<input id="hexagramSearch" type="search" placeholder="搜索卦名、卦辞或爻辞" />
</div>
</div>
<div id="hexagramLibrary" class="hexagram-library"></div>
</section>
<section class="result-layout" id="resultLayout" hidden>
<section class="hexagram-stage" aria-live="polite">
<div class="hexagram-visuals">
<div class="hex-block">
<p class="block-label">本卦</p>
<div class="hexagram" id="primaryHexagram"></div>
<h2 id="primaryTitle">-</h2>
<p id="primaryTrigrams">-</p>
</div>
<div class="change-arrow" id="changeArrow">→</div>
<div class="hex-block secondary" id="changedBlock">
<p class="block-label">变卦</p>
<div class="hexagram" id="changedHexagram"></div>
<h2 id="changedTitle">-</h2>
<p id="changedTrigrams">-</p>
</div>
</div>
</section>
<aside class="reading-panel">
<div class="reading-header">
<p class="eyebrow">本经取辞</p>
<button class="icon-button" id="copyButton" type="button" title="复制解读">
⧉
</button>
</div>
<div id="readingText" class="reading-text"></div>
</aside>
</section>
<section class="detail-grid" id="detailGrid" hidden>
<article class="detail-panel">
<h3>六爻</h3>
<div id="lineList" class="line-list"></div>
</article>
<article class="detail-panel">
<h3>本经线索</h3>
<div id="symbolList" class="symbol-list"></div>
</article>
<article class="detail-panel journal-panel">
<div class="panel-title-row">
<h3>近占</h3>
<button class="icon-button" id="clearJournalButton" type="button" title="清空记录">
×
</button>
</div>
<div id="journalList" class="journal-list"></div>
</article>
</section>
</main>
<script src="./data/zhouyi-benjing.js"></script>
<script src="./data/system-catalog.js"></script>
<script src="./app.js"></script>
</body>
</html>
FILE:styles.css
:root {
color-scheme: light;
--ink: #171614;
--muted: #67605a;
--paper: #f8f5ef;
--paper-deep: #ece2d2;
--line: #d8c8b1;
--jade: #1f6f63;
--jade-soft: #dceae5;
--cinnabar: #b5432f;
--gold: #b88738;
--night: #202428;
--white: #fffdfa;
--shadow: 0 22px 70px rgba(49, 39, 25, 0.14);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
color: var(--ink);
background:
linear-gradient(90deg, rgba(31, 111, 99, 0.08) 1px, transparent 1px),
linear-gradient(0deg, rgba(184, 135, 56, 0.08) 1px, transparent 1px),
var(--paper);
background-size: 42px 42px;
font-family:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
"PingFang SC", "Microsoft YaHei", sans-serif;
}
button,
textarea,
input {
font: inherit;
}
button {
cursor: pointer;
}
.shell {
width: min(1180px, calc(100vw - 32px));
margin: 0 auto;
padding: 28px 0 44px;
}
.oracle {
display: grid;
grid-template-columns: minmax(0, 0.9fr) minmax(320px, 1.1fr);
gap: 28px;
align-items: stretch;
min-height: 42vh;
}
.masthead {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
min-height: 360px;
padding: 32px;
color: var(--white);
background:
linear-gradient(rgba(23, 22, 20, 0.45), rgba(23, 22, 20, 0.3)),
radial-gradient(circle at 74% 30%, rgba(184, 135, 56, 0.62), transparent 34%),
linear-gradient(135deg, #1f6f63 0%, #273136 58%, #612d25 100%);
border-radius: 8px;
box-shadow: var(--shadow);
}
.masthead::before {
content: "";
position: absolute;
inset: 18px;
border: 1px solid rgba(255, 253, 250, 0.24);
pointer-events: none;
}
.eyebrow {
margin: 0 0 10px;
color: inherit;
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0;
opacity: 0.72;
}
h1 {
position: relative;
z-index: 1;
margin: 0;
font-size: clamp(3rem, 8vw, 6.8rem);
line-height: 0.92;
letter-spacing: 0;
}
.bagua-ring {
position: relative;
z-index: 1;
display: grid;
grid-template-columns: repeat(4, minmax(42px, 1fr));
gap: 10px;
width: min(100%, 360px);
color: rgba(255, 253, 250, 0.9);
}
.bagua-ring span {
display: grid;
place-items: center;
aspect-ratio: 1;
border: 1px solid rgba(255, 253, 250, 0.25);
background: rgba(255, 253, 250, 0.08);
font-size: clamp(1.8rem, 4vw, 3rem);
}
.casting-panel {
display: flex;
flex-direction: column;
justify-content: center;
gap: 16px;
padding: 30px;
background: rgba(255, 253, 250, 0.82);
border: 1px solid var(--line);
border-radius: 8px;
box-shadow: var(--shadow);
}
.question-label {
color: var(--muted);
font-weight: 750;
}
textarea {
width: 100%;
min-height: 160px;
resize: vertical;
padding: 18px;
color: var(--ink);
background: var(--white);
border: 1px solid var(--line);
border-radius: 8px;
outline: none;
line-height: 1.7;
}
textarea:focus {
border-color: var(--jade);
box-shadow: 0 0 0 4px rgba(31, 111, 99, 0.12);
}
input[type="search"] {
width: 100%;
min-height: 44px;
padding: 0 14px;
color: var(--ink);
background: var(--white);
border: 1px solid var(--line);
border-radius: 8px;
outline: none;
}
input[type="search"]:focus {
border-color: var(--jade);
box-shadow: 0 0 0 4px rgba(31, 111, 99, 0.12);
}
.controls {
display: flex;
gap: 14px;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
.mode-switch {
display: inline-grid;
grid-template-columns: repeat(2, minmax(78px, 1fr));
padding: 4px;
background: var(--paper-deep);
border: 1px solid var(--line);
border-radius: 8px;
}
.mode-button {
min-height: 42px;
padding: 0 16px;
color: var(--muted);
background: transparent;
border: 0;
border-radius: 6px;
font-weight: 750;
}
.mode-button.active {
color: var(--white);
background: var(--jade);
}
.cast-button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
min-width: 148px;
min-height: 52px;
padding: 0 22px;
color: var(--white);
background: var(--cinnabar);
border: 0;
border-radius: 8px;
font-weight: 850;
box-shadow: 0 12px 24px rgba(181, 67, 47, 0.22);
}
.button-icon {
font-size: 1.35rem;
}
.result-layout {
display: grid;
grid-template-columns: minmax(0, 1.05fr) minmax(340px, 0.95fr);
gap: 24px;
margin-top: 26px;
}
.atlas-section,
.library-section {
margin-top: 26px;
padding: 24px;
background: rgba(255, 253, 250, 0.88);
border: 1px solid var(--line);
border-radius: 8px;
box-shadow: var(--shadow);
}
.section-heading {
display: flex;
align-items: end;
justify-content: space-between;
gap: 18px;
margin-bottom: 16px;
}
.section-heading h2 {
margin: 0;
font-size: clamp(1.6rem, 3vw, 2.4rem);
}
.atlas-search {
width: min(100%, 360px);
}
.grade-filter {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-bottom: 16px;
}
.filter-button {
min-height: 38px;
padding: 0 14px;
color: var(--muted);
background: var(--paper-deep);
border: 1px solid var(--line);
border-radius: 8px;
font-weight: 800;
}
.filter-button.active {
color: var(--white);
background: var(--jade);
border-color: var(--jade);
}
.catalog-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
}
.system-card,
.hex-card {
min-height: 100%;
padding: 16px;
background: rgba(255, 253, 250, 0.82);
border: 1px solid rgba(216, 200, 177, 0.82);
border-radius: 8px;
}
.system-card header,
.hex-card header {
display: flex;
align-items: start;
justify-content: space-between;
gap: 12px;
}
.system-card h3,
.hex-card h3 {
margin: 0;
font-size: 1.05rem;
}
.system-card p,
.hex-card p {
margin: 8px 0 0;
color: var(--muted);
line-height: 1.62;
font-size: 0.94rem;
}
.grade-badge,
.status-badge {
display: inline-flex;
align-items: center;
min-height: 26px;
padding: 0 8px;
color: var(--white);
background: var(--night);
border-radius: 6px;
font-size: 0.76rem;
font-weight: 850;
white-space: nowrap;
}
.grade-s {
background: var(--jade);
}
.grade-b {
background: var(--gold);
}
.grade-c {
background: var(--muted);
}
.status-badge {
margin-top: 10px;
color: var(--ink);
background: var(--paper-deep);
}
.tag-list {
display: flex;
gap: 6px;
flex-wrap: wrap;
margin-top: 12px;
}
.tag-list span {
padding: 4px 7px;
color: var(--jade);
background: var(--jade-soft);
border-radius: 6px;
font-size: 0.78rem;
font-weight: 760;
}
.hexagram-library {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
max-height: 520px;
overflow: auto;
padding-right: 4px;
}
.hex-card {
min-height: 170px;
}
.hex-card .source-line {
color: var(--ink);
font-family: "Songti SC", "STSong", "Noto Serif CJK SC", serif;
}
.hexagram-stage,
.reading-panel,
.detail-panel {
background: rgba(255, 253, 250, 0.88);
border: 1px solid var(--line);
border-radius: 8px;
box-shadow: var(--shadow);
}
.hexagram-stage {
padding: 26px;
}
.hexagram-visuals {
display: grid;
grid-template-columns: minmax(220px, 1fr) 48px minmax(220px, 1fr);
gap: 16px;
align-items: center;
}
.hex-block {
min-height: 430px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 24px;
border: 1px solid rgba(216, 200, 177, 0.72);
background: linear-gradient(180deg, #fffdfa, #f4ecdf);
border-radius: 8px;
}
.hex-block.secondary {
background: linear-gradient(180deg, #fbfaf6, #e9f1ed);
}
.block-label {
margin: 0 0 18px;
color: var(--muted);
font-size: 0.8rem;
font-weight: 800;
}
.hexagram {
display: flex;
flex-direction: column;
justify-content: center;
gap: 12px;
width: min(100%, 240px);
min-height: 248px;
}
.yao {
position: relative;
display: grid;
grid-template-columns: 1fr;
align-items: center;
min-height: 28px;
}
.yao::before,
.yao::after {
content: "";
height: 14px;
background: var(--night);
border-radius: 2px;
}
.yao.yin {
grid-template-columns: 1fr 34px 1fr;
}
.yao.yin::before,
.yao.yin::after {
display: block;
}
.yao.yin::before {
grid-column: 1;
}
.yao.yin::after {
grid-column: 3;
}
.yao.yang::after {
display: none;
}
.yao.moving::before,
.yao.moving::after {
background: var(--cinnabar);
}
.yao.moving::marker {
color: var(--cinnabar);
}
.yao .move-dot {
position: absolute;
right: -24px;
width: 10px;
height: 10px;
border-radius: 999px;
background: var(--gold);
box-shadow: 0 0 0 5px rgba(184, 135, 56, 0.18);
}
.hex-block h2 {
margin: 18px 0 8px;
text-align: center;
font-size: clamp(1.35rem, 3vw, 2rem);
}
.hex-block p:last-child {
margin: 0;
color: var(--muted);
text-align: center;
line-height: 1.6;
}
.change-arrow {
display: grid;
place-items: center;
width: 48px;
aspect-ratio: 1;
color: var(--jade);
border: 1px solid var(--line);
border-radius: 50%;
background: var(--jade-soft);
font-size: 1.7rem;
font-weight: 900;
}
.reading-panel {
padding: 24px;
}
.reading-header,
.panel-title-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.icon-button {
display: inline-grid;
place-items: center;
width: 38px;
height: 38px;
color: var(--ink);
background: var(--white);
border: 1px solid var(--line);
border-radius: 8px;
font-size: 1.2rem;
}
.reading-text {
display: grid;
gap: 16px;
margin-top: 12px;
}
.reading-text section {
padding-top: 14px;
border-top: 1px solid rgba(216, 200, 177, 0.7);
}
.reading-text h3,
.detail-panel h3 {
margin: 0 0 10px;
font-size: 1rem;
}
.reading-text p {
margin: 0;
color: var(--muted);
line-height: 1.8;
}
.reading-text blockquote {
margin: 0;
padding: 12px 14px;
color: var(--ink);
background: #fff8ea;
border-left: 3px solid var(--gold);
line-height: 1.8;
}
.reading-text blockquote strong {
display: block;
margin-bottom: 4px;
color: var(--cinnabar);
}
.reading-text blockquote.primary-source {
background: var(--jade-soft);
border-left-color: var(--jade);
}
.source-stack {
display: grid;
gap: 10px;
margin-top: 10px;
}
.rule-badge {
display: inline-flex;
align-items: center;
min-height: 26px;
margin-right: 8px;
padding: 0 9px;
color: var(--white);
background: var(--jade);
border-radius: 6px;
font-size: 0.82rem;
font-weight: 800;
}
.detail-grid {
display: grid;
grid-template-columns: 1fr 1fr 0.9fr;
gap: 18px;
margin-top: 18px;
}
.detail-panel {
min-height: 220px;
padding: 22px;
}
.line-list,
.symbol-list,
.journal-list {
display: grid;
gap: 10px;
}
.line-item,
.symbol-item,
.journal-item {
padding: 12px 0;
color: inherit;
background: transparent;
border: 0;
border-bottom: 1px solid rgba(216, 200, 177, 0.78);
border-radius: 0;
}
.line-item strong,
.symbol-item strong,
.journal-item strong {
display: block;
margin-bottom: 4px;
}
.line-item p,
.symbol-item p,
.journal-item p {
margin: 0;
color: var(--muted);
line-height: 1.6;
font-size: 0.94rem;
}
.line-item.moving {
padding-left: 12px;
box-shadow: inset 3px 0 0 var(--cinnabar);
}
.line-item.selected {
padding-left: 12px;
background: rgba(31, 111, 99, 0.06);
box-shadow: inset 3px 0 0 var(--jade);
}
.line-item.moving.selected {
box-shadow:
inset 3px 0 0 var(--cinnabar),
inset 7px 0 0 var(--jade);
}
.source-text {
color: var(--ink) !important;
font-family: "Songti SC", "STSong", "Noto Serif CJK SC", serif;
}
.journal-panel {
max-height: 420px;
overflow: auto;
}
.journal-item {
width: 100%;
text-align: left;
cursor: pointer;
}
.journal-item:hover {
color: var(--jade);
}
@media (max-width: 980px) {
.oracle,
.result-layout,
.detail-grid {
grid-template-columns: 1fr;
}
.catalog-grid,
.hexagram-library {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.masthead {
min-height: 300px;
}
.hexagram-visuals {
grid-template-columns: 1fr;
}
.change-arrow {
justify-self: center;
transform: rotate(90deg);
}
}
@media (max-width: 620px) {
.shell {
width: min(100% - 18px, 1180px);
padding-top: 10px;
}
.masthead,
.casting-panel,
.hexagram-stage,
.reading-panel,
.detail-panel {
padding: 18px;
}
.controls {
align-items: stretch;
}
.mode-switch,
.cast-button {
width: 100%;
}
.section-heading {
align-items: stretch;
flex-direction: column;
}
.atlas-search,
.catalog-grid,
.hexagram-library {
width: 100%;
grid-template-columns: 1fr;
}
.hex-block {
min-height: 360px;
padding: 18px;
}
.hexagram {
width: min(100%, 210px);
}
}
FILE:references/zhouyi-benjing-source.txt
周易本经
整理日期:2026-04-19
来源:Project Gutenberg eBook #25501《易經》。
整理范围:六十四卦卦辞、爻辞;不含《彖传》《象传》《文言》《系辞》《说卦》《序卦》《杂卦》。
第 一 卦
乾
乾:元,亨,利,貞。
初九:潛龍,勿用。
九二:見龍在田,利見大人。
九三:君子終日乾乾,夕惕,若厲,無咎。
九四:或躍在淵,無咎。
九五:飛龍在天,利見大人。
上九:亢龍有悔。
用九:見群龍無首,吉。
第 二 卦
坤
坤:元,亨,利牝馬之貞。
君子有攸往,先迷後得主,利西南得朋,東北喪朋。安貞,吉。
初六:履霜,堅冰至。
六二:直,方,大,不習無不利。
六三:含章可貞。或從王事,無成有終。
六四:括囊;無咎,無譽。
六五:黃裳,元吉。
上六:戰龍於野,其血玄黃。
用六:利永貞。
第 三 卦
屯
屯:元,亨,利,貞,勿用,有攸往,利建侯。
初九:磐桓;利居貞,利建侯。
六二:屯如邅如,乘馬班如。匪寇婚媾,女子貞不字,十年乃字。
六三:既鹿無虞,惟入于林中,君子幾不如舍,往吝。
六四:乘馬班如,求婚媾,往吉,無不利。
九五:屯其膏,小貞吉,大貞凶。
上六:乘馬班如,泣血漣如。
第 四 卦
蒙
蒙:亨。匪我求童蒙,童蒙求我。初噬告,再三瀆,瀆則不告。利貞。
初六:發蒙,利用刑人,用說桎梏,以往吝。
九二:包蒙,吉;納婦,吉;子克家。
六三:勿用娶女;見金夫,不有躬,無攸利。
六四:困蒙,吝。
六五:童蒙,吉。
上九:擊蒙;不利為寇,利御寇。
第 五 卦
需
需:有孚,光亨,貞吉。利涉大川。
初九:需于郊。利用恆,無咎。
九二:需于沙。小有言,終吉。
九三:需于泥,致寇至。
六四:需于血,出自穴。
九五:需于酒食,貞吉。
上六:入于穴,有不速之客三人來,敬之終吉。
第 六 卦
訟
訟:有孚,窒。惕中吉。終凶。利見大人,不利涉大川。
初六:不永所事,小有言,終吉。
九二:不克訟,歸而逋,其邑人三百戶,無眚。
六三:食舊德,貞厲,終吉,或從王事,無成。
九四:不克訟,復即命,渝安貞,吉。
九五:訟元吉。
上九:或錫之鞶帶,終朝三褫之。
第 七 卦
師
師:貞,丈人,吉無咎。
初六:師出以律,否臧凶。
九二:在師中,吉無咎,王三錫命。
六三:師或輿尸,凶。
六四:師左次,無咎。
六五:田有禽,利執言,無咎。長子帥師,弟子輿尸,貞凶。
上六:大君有命,開國承家,小人勿用。
第 八 卦
比
比:吉。原筮元永貞,無咎。不寧方來,後夫凶。
初六:有孚比之,無咎。有孚盈缶,終來有他,吉。
六二:比之自內,貞吉。
六三:比之匪人。
六四:外比之,貞吉。
九五:顯比,王用三驅,失前禽。邑人不誡,吉。
上六:比之無首,凶。
第 九 卦
小畜
小畜:亨。密雲不雨,自我西郊。
初九:復自道,何其咎,吉。
九二:牽復,吉。
九三:輿說輻,夫妻反目。
六四:有孚,血去。惕出,無咎。
九五:有孚攣如,富以其鄰。
上九:既雨既處,尚德載婦,貞厲。月幾望,君子征凶。
第 十 卦
履
履:履虎尾,不咥人,亨。
初九:素履,往無咎。
九二:履道坦坦,幽人貞吉。
六三:眇能視,跛能履,履虎尾,咥人,凶。武人為于大君。
九四:履虎尾,愬愬,終吉。
九五:夬履,貞厲。
上九:視履考祥,其旋元吉。
第 十一 卦
泰
泰:小往大來,吉亨。
初九:拔茅茹,以其彙,征吉。
九二:包荒,用馮河,不遐遺,朋亡,得尚于中行。
九三:無平不陂,無往不復,艱貞無咎。勿恤其孚,于食有福。
六四:翩翩不富,以其鄰,不戒以孚。
六五:帝乙歸妹,以祉元吉。
上六:城復于隍,勿用師。自邑告命,貞吝。
第 十二 卦
否
否:否之匪人,不利君子貞,大往小來。
初六:拔茅茹,以其彙,貞吉亨。
六二:包承。小人吉,大人否亨。
六三:包羞。
九四:有命無咎,疇離祉。
九五:休否,大人吉。其亡其亡,繫于苞桑。
上九:傾否,先否後喜。
第 十三 卦
同人
同人:同人于野,亨。利涉大川,利君子貞。
初九:同人于門,無咎。
六二:同人于宗,吝。
九三:伏戎于莽,升其高陵,三歲不興。
九四:乘其墉,弗克攻,吉。
九五:同人,先號咷而後笑。大師克相遇。
上九:同人于郊,無悔。
第 十四 卦
大有
大有:元亨。
初九:無交害,匪咎,艱則無咎。
九二:大車以載,有攸往,無咎。
九三:公用亨于天子,小人弗克。
九四:匪其彭,無咎。
六五:厥孚交如,威如;吉。
上九:自天佑之,吉無不利。
第 十五 卦
謙
謙:亨,君子有終。
初六:謙謙君子,用涉大川,吉。
六二:鳴謙,貞吉。
九三:勞謙君子,有終吉。
六四:無不利,撝謙。
六五:不富,以其鄰,利用侵伐,無不利。
上六:鳴謙,利用行師,征邑國。
第 十六 卦
豫
豫:利建侯行師。
初六:鳴豫,凶。
六二:介于石,不終日,貞吉。
六三:盱豫,悔。遲有悔。
九四:由豫,大有得。勿疑。朋盍簪。
六五:貞疾,恆不死。
上六:冥豫,成有渝,無咎。
第 十七 卦
隨
隨:元亨利貞,無咎。
初九:官有渝,貞吉。出門交有功。
六二:係小子,失丈夫。
六三:係丈夫,失小子。隨有求得,利居貞。
九四:隨有獲,貞凶。有孚在道,以明,何咎。
九五:孚于嘉,吉。
上六:拘系之,乃從維之。王用亨于西山。
第 十八 卦
蠱
蠱:元亨,利涉大川。先甲三日,後甲三日。
初六:幹父之蠱,有子,考無咎,厲終吉。
九二:幹母之蠱,不可貞。
九三:幹父小有晦,無大咎。
六四:裕父之蠱,往見吝。
六五:幹父之蠱,用譽。
上九:不事王侯,高尚其事。
第 十九 卦
臨
臨:元,亨,利,貞。至于八月有凶。
初九:咸臨,貞吉。
九二:咸臨,吉無不利。
六三:甘臨,無攸利。既憂之,無咎。
六四:至臨,無咎。
六五:知臨,大君之宜,吉。
上六:敦臨,吉無咎。
第 二十 卦
觀
觀:盥而不薦,有孚顒若。
初六:童觀,小人無咎,君子吝。
六二:窺觀,利女貞。
六三:觀我生,進退。
六四:觀國之光,利用賓于王。
九五:觀我生,君子無咎。
上九:觀其生,君子無咎。
第二十一卦
噬嗑
噬嗑:亨。利用獄。
初九:履校滅趾,無咎。
六二:噬膚滅鼻,無咎。
六三:噬臘肉,遇毒;小吝,無咎。
九四:噬乾胏,得金矢,利艱貞,吉。
六五:噬乾肉,得黃金,貞厲,無咎。
上九:何校滅耳,凶。
第二十二卦
賁
賁:亨。小利有所往。
初九:賁其趾,舍車而徒。
六二:賁其須。
九三:賁如濡如,永貞吉。
六四:賁如皤如,白馬翰如,匪寇婚媾。
六五:賁于丘園,束帛戔戔,吝,終吉。
上九:白賁,無咎。
第二十三卦
剝
剝:不利有攸往。
初六:剝床以足,蔑貞凶。
六二:剝床以辨,蔑貞凶。
六三:剝之,無咎。
六四:剝床以膚,凶。
六五:貫魚,以宮人寵,無不利。
上九:碩果不食,君子得輿,小人剝廬。
第二十四卦
復
復:亨。出入無疾,朋來無咎。反復其道,七日來復,利有攸往。
初九:不復遠,無祗悔,元吉。
六二:休復,吉。
六三:頻復厲,無咎。
六四:中行獨復。
六五:敦復,無悔。
上六:迷復,凶,有災眚。用行師,終有大敗,以其國君,凶;至于十年,不克征。
第二十五卦
無妄
無妄:元,亨,利,貞。其匪正有眚,不利有攸往。
初九:無妄,往吉。
六二:不耕獲,不菑畬,則利有攸往。
六三:無妄之災,或繫之牛,行人之得,邑人之災。
九四:可貞,無咎。
九五:無妄之疾,勿藥有喜。
上九:無妄,行有眚,無攸利。
第二十六卦
大畜
大畜:利貞,不家食吉,利涉大川。
初九:有厲利已。
九二:輿說輻。
九三:良馬逐,利艱貞。日閑輿衛,利有攸往。
六四:童牛之牿,元吉。
六五:豶豕之牙,吉。
上九:何天之衢,亨。
第二十七卦
頤
頤:貞吉。觀頤,自求口實。
初九:舍爾靈龜,觀我朵頤,凶。
六二:顛頤,拂經于丘頤,征凶。
六三:拂頤,貞凶,十年勿用,無攸利。
六四:顛頤吉,虎視眈眈,其欲逐逐,無咎。
六五:拂經,居貞吉,不可涉大川。
上九:由頤,厲吉,利涉大川。
第二十八卦
大過
大過:棟橈,利有攸往,亨。
初六:藉用白茅,無咎。
九二:枯楊生稊,老夫得其女妻,無不利。
九三:棟橈,凶。
九四:棟隆,吉;有它吝。
九五:枯楊生華,老婦得士夫,無咎無譽。
上六:過涉滅頂,凶,無咎。
第二十九卦
坎
坎:習坎,有孚,維心亨,行有尚。
初六:習坎,入于坎窞,凶。
九二:坎有險,求小得。
六三:來之坎坎,險且枕,入于坎窞,勿用。
六四:樽酒簋貳,用缶,納約自牖,終無咎。
九五:坎不盈,祗既平,無咎。
上六:係用徽纆,寘于叢棘,三歲不得,凶。
第 三十 卦
離
離:利貞,亨。畜牝牛,吉。
初九:履錯然,敬之無咎。
六二:黃離,元吉。
九三:日昃之離,不鼓缶而歌,則大耋之嗟,凶。
九四:突如其來如,焚如,死如,棄如。
六五:出涕沱若,戚嗟若,吉。
上九:王用出征,有嘉折首,獲匪其醜,無咎。
第三十一卦
咸
咸:亨,利貞,取女吉。
初六:咸其拇。
六二:咸其腓,凶,居吉。
九三:咸其股,執其隨,往吝。
九四:貞吉悔亡,憧憧往來,朋從爾思。
九五:咸其脢,無悔。
上六:咸其輔,頰,舌。
第三十二卦
恆:亨,無咎,利貞,利有攸往。
初六:浚恆,貞凶,無攸利。
九二:悔亡。
九三:不恆其德,或承之羞,貞吝。
九四:田無禽。
六五:恆其德,貞,婦人吉,夫子凶。
上六:振恆,凶。
第三十三卦
遯
遯:亨,小利貞。
初六:遯尾,厲,勿用有攸往。
六二:執之用黃牛之革,莫之勝說。
九三:係遯,有疾厲,畜臣妾吉。
九四:好遯君子吉,小人否。
九五:嘉遯,貞吉。
上九:肥遯,無不利。
第三十四卦
大壯
大壯:利貞。
初九:壯于趾,征凶,有孚。
九二:貞吉。
九三:小人用壯,君子用罔,貞厲。羝羊觸藩,羸其角。
九四:貞吉悔亡,藩決不羸,壯于大輿之輹。
六五:喪羊于易,無悔。
上六:羝羊觸藩,不能退,不能遂,無攸利,艱則吉。
第三十五卦
晉
晉:康侯用錫馬蕃庶,晝日三接。
初六:晉如,摧如,貞吉。罔孚,裕無咎。
六二:晉如,愁如,貞吉。受茲介福,于其王母。
六三:眾允,悔亡。
九四:晉如鼫鼠,貞厲。
六五:悔亡,失得勿恤,往吉無不利。
上九:晉其角,維用伐邑,厲吉無咎,貞吝。
第三十六卦
明夷
明夷:利艱貞。
初九:明夷于飛,垂其翼。君子于行,三日不食,有攸往,主人有言。
六二:明夷,夷于左股,用拯馬壯,吉。
九三:明夷于南狩,得其大首,不可疾貞。
六四:入于左腹,獲明夷之心,于出門庭。
六五:箕子之明夷,利貞。
上六:不明晦,初登于天,後入于地。
第三十七卦
家人
家人:利女貞。
初九:閑有家,悔亡。
六二:無攸遂,在中饋,貞吉。
九三:家人嗃嗃,悔厲吉;婦子嘻嘻,終吝。
六四:富家,大吉。
九五:王假有家,勿恤吉。
上九:有孚威如,終吉。
第三十八卦
睽
睽:小事吉。
初九:悔亡,喪馬勿逐,自復;見惡人無咎。
九二:遇主于巷,無咎。
六三:見輿曳,其牛掣,其人天且劓,無初有終。
九四:睽孤,遇元夫,交孚,厲無咎。
六五:悔亡,厥宗噬膚,往何咎。
上九:睽孤,見豕負塗,載鬼一車,先張之弧,後說之弧,匪寇婚媾,往遇雨則吉。
第三十九卦
蹇
蹇:利西南,不利東北;利見大人,貞吉。
初六:往蹇,來譽。
六二:王臣蹇蹇,匪躬之故。
九三:往蹇來反。
六四:往蹇來連。
九五:大蹇朋來。
上六:往蹇來碩,吉;利見大人。
第 四十 卦
解
解:利西南,無所往,其來復吉。有攸往,夙吉。
初六:無咎。
九二:田獲三狐,得黃矢,貞吉。
六三:負且乘,致寇至,貞吝。
九四:解而拇,朋至斯孚。
六五:君子維有解,吉;有孚于小人。
上六:公用射隼,于高墉之上,獲之,無不利。
第四十一卦
損
損:有孚,元吉,無咎,可貞,利有攸往?曷之用,二簋可用享。
初九:已事遄往,無咎,酌損之。
九二:利貞,征凶,弗損益之。
六三:三人行,則損一人;一人行,則得其友。
六四:損其疾,使遄有喜,無咎。
六五:或益之,十朋之龜弗克違,元吉。
上九:弗損益之,無咎,貞吉,利有攸往,得臣無家。
第四十二卦
益
益:利有攸往,利涉大川。
初九:利用為大作,元吉,無咎。
六二:或益之,十朋之龜弗克違,永貞吉。王用享于帝,吉。
六三:益之用凶事,無咎。有孚中行,告公用圭。
六四:中行,告公從。利用為依遷國。
九五:有孚惠心,勿問元吉。有孚惠我德。
上九:莫益之,或擊之,立心勿恆,凶。
第四十三卦
夬
夬:揚于王庭,孚號,有厲,告自邑,不利即戎,利有攸往。
初九:壯于前趾,往不勝為吝。
九二:惕號,莫夜有戎,勿恤。
九三:壯于頄,有凶。君子夬夬,獨行遇雨,若濡有慍,無咎。
九四:臀無膚,其行次且。牽羊悔亡,聞言不信。
九五:莧陸夬夬,中行無咎。
上六:無號,終有凶。
第四十四卦
姤
姤:女壯,勿用取女。
初六:繫于金柅,貞吉,有攸往,見凶,羸豕孚蹢躅。
九二:包有魚,無咎,不利賓。
九三:臀無膚,其行次且,厲,無大咎。
九四:包無魚,起凶。
九五:以杞包瓜,含章,有隕自天。
上九:姤其角,吝,無咎。
第四十五卦
萃
萃:亨。王假有廟,利見大人,亨,利貞。用大牲吉,利有攸往。
初六:有孚不終,乃亂乃萃,若號一握為笑,勿恤,往無咎。
六二:引吉,無咎,孚乃利用禴。
六三:萃如,嗟如,無攸利,往無咎,小吝。
九四:大吉,無咎。
九五:萃有位,無咎。匪孚,元永貞,悔亡。
上六:齎咨涕洟,無咎。
第四十六卦
升
升:元亨,用見大人,勿恤,南征吉。
初六:允升,大吉。
九二:孚乃利用禴,無咎。
九三:升虛邑。
六四:王用亨于岐山,吉無咎。
六五:貞吉,升階。
上六:冥升,利于不息之貞。
第四十七卦
困
困:亨,貞,大人吉,無咎,有言不信。
初六:臀困于株木,入于幽谷,三歲不覿。
九二:困于酒食,朱紱方來,利用亨祀,征凶,無咎。
六三:困于石,據于蒺藜,入于其宮,不見其妻,凶。
九四:來徐徐,困于金車,吝,有終。
九五:劓刖,困于赤紱,乃徐有說,利用祭祀。
上六:困于葛藟,于臲卼,曰動悔。有悔,征吉。
第四十八卦
井
井:改邑不改井,無喪無得,往來井井。汔至,亦未繘井,羸其瓶,凶。
初六:井泥不食,舊井無禽。
九二:井谷射鮒,甕敝漏。
九三:井渫不食,為我民惻,可用汲,王明,並受其福。
六四:井甃,無咎。
九五:井冽,寒泉食。
上六:井收勿幕,有孚無吉。
第四十九卦
革
革:己日乃孚,元亨利貞,悔亡。
初九:鞏用黃牛之革。
六二:己日乃革之,征吉,無咎。
九三:征凶,貞厲,革言三就,有孚。
九四:悔亡,有孚改命,吉。
九五:大人虎變,未占有孚。
上六:君子豹變,小人革面,征凶,居貞吉。
第 五十 卦
鼎
鼎:元吉,亨。
初六:鼎顛趾,利出否,得妾以其子,無咎。
九二:鼎有實,我仇有疾,不我能即,吉。
九三:鼎耳革,其行塞,雉膏不食,方雨虧悔,終吉。
九四:鼎折足,覆公餗,其形渥,凶。
六五:鼎黃耳金鉉,利貞。
上九:鼎玉鉉,大吉,無不利。
第五十一卦
震
震:亨。震來虩虩,笑言啞啞。震驚百里,不喪匕鬯。
初九:震來虩虩,後笑言啞啞,吉。
六二:震來厲,億喪貝,躋于九陵,勿逐,七日得。
六三:震蘇蘇,震行無眚。
九四:震遂泥。
六五:震往來厲,億無喪,有事。
上六:震索索,視矍矍,征凶。震不于其躬,于其鄰,無咎。婚媾有言。
第五十二卦
艮
艮:艮其背,不獲其身,行其庭,不見其人,無咎。
初六:艮其趾,無咎,利永貞。
六二:艮其腓,不拯其隨,其心不快。
九三:艮其限,列其夤,厲薰心。
六四:艮其身,無咎。
六五:艮其輔,言有序,悔亡。
上九:敦艮,吉。
第五十三卦
漸
漸:女歸吉,利貞。
初六:鴻漸于干,小子厲,有言,無咎。
六二:鴻漸于磐,飲食衎衎,吉。
九三:鴻漸于陸,夫征不復,婦孕不育,凶;利御寇。
六四:鴻漸于木,或得其桷,無咎。
九五:鴻漸于陵,婦三歲不孕,終莫之勝,吉。
上九:鴻漸于逵,其羽可用為儀,吉。
第五十四卦
歸妹
歸妹:征凶,無攸利。
初九:歸妹以娣,跛能履,征吉。
九二:眇能視,利幽人之貞。
六三:歸妹以須,反歸以娣。
九四:歸妹愆期,遲歸有時。
六五:帝乙歸妹,其君之袂,不如其娣之袂良,月幾望,吉。
上六:女承筐無實,士刲羊無血,無攸利。
第五十五卦
豐
豐:亨,王假之,勿憂,宜日中。
初九:遇其配主,雖旬無咎,往有尚。
六二:豐其蔀,日中見斗,往得疑疾,有孚發若,吉。
九三:豐其沛,日中見沫,折其右肱,無咎。
九四:豐其蔀,日中見斗,遇其夷主,吉。
六五:來章,有慶譽,吉。
上六:豐其屋,蔀其家,窺其戶,闃其無人,三歲不覿,凶。
第五十六卦
旅
旅:小亨,旅貞吉。
初六:旅瑣瑣,斯其所取災。
六二:旅即次,懷其資,得童僕貞。
九三:旅焚其次,喪其童僕,貞厲。
九四:旅于處,得其資斧,我心不快。
六五:射雉一矢亡,終以譽命。
上九:鳥焚其巢,旅人先笑後號咷。喪牛于易,凶。
第五十七卦
巽
巽:小亨,利攸往,利見大人。
初六:進退,利武人之貞。
九二:巽在床下,用史巫紛若,吉無咎。
九三:頻巽,吝。
六四:悔亡,田獲三品。
九五:貞吉悔亡,無不利。無初有終,先庚三日,後庚三日,吉。
上九:巽在床下,喪其資斧,貞凶。
第五十八卦
兌
兌:亨,利貞。
初九:和兌,吉。
九二:孚兌,吉,悔亡。
六三:來兌,凶。
九四:商兌,未寧,介疾有喜。
九五:孚于剝,有厲。
上六:引兌。
第五十九卦
渙
渙:亨。王假有廟,利涉大川,利貞。
初六:用拯馬壯,吉。
九二:渙奔其機,悔亡。
六三:渙其躬,無悔。
六四:渙其群,元吉。渙有丘,匪夷所思。
九五:渙汗其大號,渙王居,無咎。
上九:渙其血,去逖出,無咎。
第 六十 卦
節
節:亨。苦節不可貞。
初九:不出戶庭,無咎。
九二:不出門庭,凶。
六三:不節若,則嗟若,無咎。
六四:安節,亨。
九五:甘節,吉;往有尚。
上六:苦節,貞凶,悔亡。
第六十一卦
中孚
中孚:豚魚,吉,利涉大川,利貞。
初九:虞吉,有他不燕。
九二:鳴鶴在陰,其子和之,我有好爵,吾與爾靡之。
六三:得敵,或鼓或罷,或泣或歌。
六四:月幾望,馬匹亡,無咎。
九五:有孚攣如,無咎。
上九:翰音登于天,貞凶。
第六十二卦
小過
小過:亨,利貞,可小事,不可大事。飛鳥遺之音,不宜上宜下,大吉。
初六:飛鳥以凶。
六二:過其祖,遇其妣;不及其君,遇其臣;無咎。
九三:弗過防之,從或戕之,凶。
九四:無咎,弗過遇之。往厲必戒,勿用永貞。
六五:密雲不雨,自我西郊,公弋取彼在穴。
上六:弗遇過之,飛鳥離之,凶,是謂災眚。
第六十三卦
既濟
既濟:亨,小利貞,初吉終亂。
初九:曳其輪,濡其尾,無咎。
六二:婦喪其茀,勿逐,七日得。
九三:高宗伐鬼方,三年克之,小人勿用。
六四:繻有衣袽,終日戒。
九五:東鄰殺牛,不如西鄰之禴祭,實受其福。
上六:濡其首,厲。
第六十四卦
未濟
未濟:亨,小狐汔濟,濡其尾,無攸利。
初六:濡其尾,吝。
九二:曳其輪,貞吉。
六三:未濟,征凶,利涉大川。
九四:貞吉,悔亡,震用伐鬼方,三年有賞于大國。
六五:貞吉,無悔,君子之光,有孚,吉。
上九:有孚于飲酒,無咎,濡其首,有孚失是。
FILE:references/user-guide-zh.md
# 周易本经占筮:使用说明
这不是一个只会“给吉凶”的算卦玩具,而是一套基于《周易》本经原著、适合做决策整理和处境判断的系统。
你可以把它当成三种工具来用:
1. `起卦`:问一件事现在该怎么推进。
2. `查卦`:查六十四卦原文、卦辞、爻辞。
3. `导航`:看周易和六爻、梅花、八字、奇门等体系有什么区别。
## 一、最适合拿来问什么
这套系统最适合的问题是:
- 我该不该推进这次合作?
- 这份工作现在该继续,还是先缓一缓?
- 这段关系下一步适合主动沟通,还是先观察?
- 这个项目目前最大的风险点是什么?
- 我现在应该进,还是守?
不适合的问题是:
- 我什么时候一定发财?
- 对方百分百会不会回来?
- 哪只股票一定涨?
- 医疗、法律、投资上的确定指令
一句话:它更适合看`处境`、`节奏`、`取舍`和`提醒`,不适合替你承担现实决策责任。
## 二、在 ClawHub / 对话里怎么用
你可以直接对它说下面这些话。
### 1. 直接起卦
示例:
- 帮我起一卦,问这次合作要不要推进
- 用周易看一下我现在是否适合换工作
- 用三钱起卦,看看这段关系接下来该怎么处理
- 用蓍草法帮我问一下这个项目的时机
推荐说法:
```text
帮我起一卦,问题是:我这个月是否应该主动推进新的合作?
```
### 2. 直接查某一卦
示例:
- 查乾卦
- 第三卦是什么
- 给我看屯卦的卦辞和六二爻辞
- 查一下“利涉大川”出自哪些卦
### 3. 让它解释一个结果
示例:
- 这个卦为什么取这一条爻辞?
- 两爻变应该怎么看?
- 请先给我原文,再给白话解释
- 不要鸡汤,直接说这卦提醒我什么
### 4. 让它做体系导航
示例:
- 周易和六爻有什么区别?
- 小六壬是不是基于周易原文?
- 这个问题更适合用周易、八字还是奇门?
## 三、问得越好,结果越准
最好的提问方式是:`一事一问`。
好问题:
- 我这个月要不要推进新的合作?
- 我现在是否适合离开这份工作?
- 这段关系接下来该不该主动沟通?
不好的问法:
- 我的整个人生怎么样?
- 我什么时候一定暴富?
- 他到底爱不爱我、会不会回来、会不会娶我?
你可以照着这个模板问:
```text
我想问的是:
现在这件事的核心问题是:
我最想判断的是:该推进 / 该等待 / 该止损 / 该沟通?
```
## 四、结果出来后怎么看
结果里最重要的是四部分:
- `本卦`:你现在的处境是什么
- `变卦`:事情接下来可能往哪里转
- `动爻`:变化最关键的位置
- `本经取辞`:真正该看的《周易》原文
最简单的读法:
1. 先看系统说这次用了哪条规则取辞。
2. 再看引用的卦辞或爻辞原文。
3. 最后再看它对现实问题的白话解释。
不要一上来只盯着“吉”还是“凶”。
真正有用的是:它提醒你现在该进、该守、该改,还是该停。
## 五、七种取辞规则
这套系统严格按传统的变爻规则来,不会乱选一句听起来顺耳的话:
1. 六爻不变:看本卦卦辞
2. 一爻变:看该动爻爻辞
3. 二爻变:看两条动爻,以上爻为主
4. 三爻变:看本卦卦辞和变卦卦辞
5. 四爻变:看两条静爻,以下爻为主
6. 五爻变:看变卦中唯一静爻
7. 六爻皆变:乾看用九,坤看用六,其余看变卦卦辞
这也是它和很多“会起卦但不会严格取辞”的同类 agent 最大的不同之一。
## 六、如果你是本地打开网页用
打开:
`index.html`
你会看到三个主要区域:
### 1. 周易本经占筮
- 输入问题
- 选择 `三钱` 或 `蓍草`
- 点击 `起卦`
### 2. 本经卦库
可以搜索:
- 卦名:乾、坤、屯、需……
- 卦辞关键词:利涉大川、元亨利贞……
- 爻辞关键词:十年乃字、无咎……
### 3. 术数百科
这里会告诉你:
- 哪些体系已经校验过
- 哪些体系暂时只做百科导航
- 每个体系适合解决什么问题
## 七、推荐的使用姿势
如果你是第一次用,最推荐这三种方式:
### 方式一:直接问现实问题
```text
帮我起一卦,问这次合作还要不要继续推进。
```
### 方式二:先查卦再理解
```text
查一下谦卦,并告诉我它为什么常被理解成“有利于长期发展”。
```
### 方式三:先问体系差异
```text
我现在的问题到底适合用周易本经、六爻还是八字?
```
## 八、边界说明
这套系统有一个很重要的原则:
`宁可说清边界,也不冒充高精度。`
所以它会坚持这些做法:
- 周易部分只以本经原文为底
- 不把八字、奇门、紫微、小六壬硬混进周易解释
- 不把白话改写伪装成原文
- 不把未校验的命理模块装成“全都能算”
这也是它和很多市面上“什么都想算、但每样都不够扎实”的 agent 不一样的地方。
## 九、一句话总结
最好的使用方法不是把它当神谕机,而是把它当一面镜子:
先用《周易》帮你把问题照清楚,再回到现实里做真正的选择。
FILE:references/README.md
# 周易本经占筮
一个以 `sources/zhouyi/zhouyi_benjing.txt` 为底座的本地《周易》占筮系统,同时提供百科式术数导航。
如果你只是想知道怎么使用,请先看:`使用说明-小白版.md`。
## 核心原则
- 以《周易》本经卦辞、爻辞、用九、用六为第一数据源。
- 起卦只负责生成六爻,不把随机结果包装成确定命令。
- 解读必须先说明取辞规则,再引用本经原文,再给出现代语境建议。
- 其他术数体系只做百科导航和资料要求说明;未通过校验前不冒充高精度排盘。
- 高风险问题只给决策提示,不替代医疗、法律、投资等专业意见。
## 已吸收并修正的点
- 保留 `gua` 包里较好的 64 卦映射、三钱概率和七种取辞规则。
- 修正之前多个包里出现的卦序反置、原文截断、白话混入原文等问题。
- 放弃不可靠的八字、六爻纳甲、奇门、紫微混搭,不让非周易体系污染本经解释。
- 增加数据构建校验,确保 64 卦完整、每卦 6 爻、乾坤特殊用辞存在。
- 新增全体系百科导航,按 S/B/C 级标明可信度、资料要求和边界。
- 新增本经卦库检索,可按卦名、卦辞、爻辞关键词查找。
## 使用
直接用浏览器打开 `index.html`。
如果想接到 Telegram,见:`TELEGRAM部署.md`。
可选起卦方式:
- `三钱`:三枚铜钱法,6/7/8/9 概率为 1/8、3/8、3/8、1/8。
- `蓍草`:按蓍草法常用概率模拟,6/7/8/9 概率为 1/16、5/16、7/16、3/16。
## 取辞规则
- 六爻不变:用本卦卦辞。
- 一爻变:用该动爻爻辞。
- 二爻变:用两个动爻爻辞,以上爻为主。
- 三爻变:用本卦卦辞与变卦卦辞。
- 四爻变:用两个静爻爻辞,以下爻为主。
- 五爻变:用变卦中唯一静爻所对应的爻辞。
- 六爻皆变:乾用用九,坤用用六,其他卦用变卦卦辞。
## 数据构建
```bash
python3 tools/build_zhouyi_data.py
```
这会从 `sources/zhouyi/zhouyi_benjing.txt` 生成 `data/zhouyi-benjing.js`。
## 验证
```bash
node tests/verify_zhouyi_system.js
node tests/verify_system_catalog.js
```
验证内容包括:64 卦数量、每卦 6 爻、乾坤用辞、关键原文、乾坤泰否既济未济等卦象映射。
百科验证内容包括:体系数量、字段完整性、已启用模块范围、待校验体系边界。
FILE:tests/verify_zhouyi_system.js
#!/usr/bin/env node
const assert = require("node:assert/strict");
const zhouyi = require("../data/zhouyi-benjing.js");
const trigrams = {
"111": "乾",
"110": "兑",
"101": "离",
"100": "震",
"011": "巽",
"010": "坎",
"001": "艮",
"000": "坤"
};
const lookup = {
"乾|乾": 1, "乾|兑": 43, "乾|离": 14, "乾|震": 34, "乾|巽": 9, "乾|坎": 5, "乾|艮": 26, "乾|坤": 11,
"兑|乾": 10, "兑|兑": 58, "兑|离": 38, "兑|震": 54, "兑|巽": 61, "兑|坎": 60, "兑|艮": 41, "兑|坤": 19,
"离|乾": 13, "离|兑": 49, "离|离": 30, "离|震": 55, "离|巽": 37, "离|坎": 63, "离|艮": 22, "离|坤": 36,
"震|乾": 25, "震|兑": 17, "震|离": 21, "震|震": 51, "震|巽": 42, "震|坎": 3, "震|艮": 27, "震|坤": 24,
"巽|乾": 44, "巽|兑": 28, "巽|离": 50, "巽|震": 32, "巽|巽": 57, "巽|坎": 48, "巽|艮": 18, "巽|坤": 46,
"坎|乾": 6, "坎|兑": 47, "坎|离": 64, "坎|震": 40, "坎|巽": 59, "坎|坎": 29, "坎|艮": 4, "坎|坤": 7,
"艮|乾": 33, "艮|兑": 31, "艮|离": 56, "艮|震": 62, "艮|巽": 53, "艮|坎": 39, "艮|艮": 52, "艮|坤": 15,
"坤|乾": 12, "坤|兑": 45, "坤|离": 35, "坤|震": 16, "坤|巽": 20, "坤|坎": 8, "坤|艮": 23, "坤|坤": 2
};
function resolve(bits) {
const lower = trigrams[bits.slice(0, 3)];
const upper = trigrams[bits.slice(3, 6)];
return zhouyi[lookup[`lower|upper`] - 1];
}
assert.equal(zhouyi.length, 64);
for (const hex of zhouyi) {
assert.equal(hex.lines.length, 6, `hex.number hex.name should have 6 lines`);
assert.ok(hex.judgment, `hex.number hex.name should have judgment`);
}
assert.equal(zhouyi[0].name, "乾");
assert.equal(zhouyi[0].extras[0].label, "用九");
assert.equal(zhouyi[1].name, "坤");
assert.equal(zhouyi[1].extras[0].label, "用六");
assert.equal(zhouyi[2].lines[1].text, "屯如邅如,乘馬班如。匪寇婚媾,女子貞不字,十年乃字。");
assert.equal(resolve("111111").name, "乾");
assert.equal(resolve("000000").name, "坤");
assert.equal(resolve("111000").name, "泰");
assert.equal(resolve("000111").name, "否");
assert.equal(resolve("101010").name, "既濟");
assert.equal(resolve("010101").name, "未濟");
assert.equal(resolve("011101").name, "鼎");
assert.equal(resolve("001101").name, "旅");
const sourceRules = [
"六爻不变:本卦卦辞",
"一爻变:该动爻爻辞",
"二爻变:两条动爻爻辞,以上爻为主",
"三爻变:本卦卦辞与变卦卦辞",
"四爻变:两条静爻爻辞,以下爻为主",
"五爻变:变卦中唯一静爻所对应的爻辞",
"六爻皆变:乾用用九,坤用用六,其他用变卦卦辞"
];
assert.equal(sourceRules.length, 7);
console.log("zhouyi system verification passed");
FILE:tests/verify_cli.js
const { execFileSync } = require("child_process");
const path = require("path");
const root = path.join(__dirname, "..");
const cli = path.join(root, "scripts", "zhouyi_cli.js");
function run(args) {
return execFileSync("node", [cli, ...args], {
cwd: root,
encoding: "utf-8"
});
}
function assert(condition, message) {
if (!condition) throw new Error(message);
}
const cast = JSON.parse(run(["cast", "--question", "测试", "--method", "coin", "--seed", "demo", "--json"]));
assert(cast.primary && cast.primary.number >= 1 && cast.primary.number <= 64, "cast should resolve primary hexagram");
assert(cast.changed && cast.changed.number >= 1 && cast.changed.number <= 64, "cast should resolve changed hexagram");
assert(Array.isArray(cast.lines) && cast.lines.length === 6, "cast should return 6 lines");
assert(cast.decision && cast.decision.entries.length >= 1, "cast should return decision entries");
const lookup = JSON.parse(run(["lookup", "--name", "乾", "--json"]));
assert(lookup.number === 1, "lookup by name should return 乾卦");
assert(lookup.extras[0].label === "用九", "乾卦 should retain 用九");
const search = JSON.parse(run(["search", "--query", "十年乃字", "--json"]));
assert(search.some((item) => item.number === 3), "search should find 屯卦");
const catalog = JSON.parse(run(["catalog", "--grade", "S", "--json"]));
assert(catalog.length >= 3, "catalog S grade should include enabled core systems");
console.log("cli verification passed");
FILE:tests/verify_system_catalog.js
#!/usr/bin/env node
const assert = require("node:assert/strict");
const systems = require("../data/system-catalog.js");
assert.ok(systems.length >= 10, "catalog should feel encyclopedic");
for (const item of systems) {
assert.ok(item.id, "system id required");
assert.ok(item.name, `item.id name required`);
assert.ok(["S", "B", "C"].includes(item.grade), `item.id invalid grade`);
assert.ok(item.status, `item.id status required`);
assert.ok(item.basis, `item.id basis required`);
assert.ok(item.capability, `item.id capability required`);
assert.ok(item.guardrail, `item.id guardrail required`);
assert.ok(Array.isArray(item.bestFor) && item.bestFor.length > 0, `item.id bestFor required`);
assert.ok(Array.isArray(item.inputs) && item.inputs.length > 0, `item.id inputs required`);
}
const active = systems.filter((item) => item.status === "已启用").map((item) => item.id).sort();
assert.deepEqual(active, ["routing", "yijing-library", "zhouyi-benjing"].sort());
const zhouyi = systems.find((item) => item.id === "zhouyi-benjing");
assert.equal(zhouyi.grade, "S");
assert.match(zhouyi.basis, /周易/);
const qimen = systems.find((item) => item.id === "qimen");
assert.equal(qimen.status, "待校验");
assert.match(qimen.guardrail, /基准盘/);
console.log("system catalog verification passed");
FILE:agents/openai.yaml
interface:
display_name: "周易本经占筮"
short_description: "汲取百家之长,打磨成更完整的《周易》系统 | A more complete I Ching system distilled from the best of the field"
default_prompt: "Use $zhouyi-benjing-oracle to cast a Zhouyi hexagram or look up hexagram source text, cite the original judgment or line text first, and then explain it in plain Chinese."
FILE:package.json
{
"name": "zhouyi-benjing-oracle",
"version": "1.0.0",
"description": "以《周易》本经原著为底,系统收集并拆解市面上几乎所有可获取的同类 divination agents / skills / 程序,汲取百家之长,取其精华、去其糟粕,最终打磨成更准确、更完整、更好用的周易系统。Built on the original Zhouyi text and refined by absorbing the best ideas across virtually every comparable divination agent we could access.",
"main": "SKILL.md",
"keywords": [
"openclaw",
"skill",
"zhouyi",
"yijing",
"iching",
"周易",
"易经",
"六十四卦",
"占卜",
"卦辞",
"爻辞"
],
"author": "pineapple",
"license": "MIT-0",
"engines": {
"node": ">=18"
},
"scripts": {
"cast": "node scripts/zhouyi_cli.js cast",
"lookup": "node scripts/zhouyi_cli.js lookup",
"search": "node scripts/zhouyi_cli.js search",
"catalog": "node scripts/zhouyi_cli.js catalog",
"build:data": "python3 scripts/build_zhouyi_data.py",
"test": "node tests/verify_zhouyi_system.js && node tests/verify_system_catalog.js && node tests/verify_cli.js"
}
}
FILE:scripts/zhouyi_cli.js
#!/usr/bin/env node
const crypto = require("crypto");
const ZHOUYI_BENJING = require("../data/zhouyi-benjing");
const DIVINATION_SYSTEMS = require("../data/system-catalog");
const TRIGRAMS = {
"111": { name: "乾", symbol: "☰", nature: "天", image: "健" },
"110": { name: "兑", symbol: "☱", nature: "泽", image: "悦" },
"101": { name: "离", symbol: "☲", nature: "火", image: "丽" },
"100": { name: "震", symbol: "☳", nature: "雷", image: "动" },
"011": { name: "巽", symbol: "☴", nature: "风", image: "入" },
"010": { name: "坎", symbol: "☵", nature: "水", image: "险" },
"001": { name: "艮", symbol: "☶", nature: "山", image: "止" },
"000": { name: "坤", symbol: "☷", nature: "地", image: "顺" }
};
const HEXAGRAM_LOOKUP = {
"乾|乾": 1, "乾|兑": 43, "乾|离": 14, "乾|震": 34, "乾|巽": 9, "乾|坎": 5, "乾|艮": 26, "乾|坤": 11,
"兑|乾": 10, "兑|兑": 58, "兑|离": 38, "兑|震": 54, "兑|巽": 61, "兑|坎": 60, "兑|艮": 41, "兑|坤": 19,
"离|乾": 13, "离|兑": 49, "离|离": 30, "离|震": 55, "离|巽": 37, "离|坎": 63, "离|艮": 22, "离|坤": 36,
"震|乾": 25, "震|兑": 17, "震|离": 21, "震|震": 51, "震|巽": 42, "震|坎": 3, "震|艮": 27, "震|坤": 24,
"巽|乾": 44, "巽|兑": 28, "巽|离": 50, "巽|震": 32, "巽|巽": 57, "巽|坎": 48, "巽|艮": 18, "巽|坤": 46,
"坎|乾": 6, "坎|兑": 47, "坎|离": 64, "坎|震": 40, "坎|巽": 59, "坎|坎": 29, "坎|艮": 4, "坎|坤": 7,
"艮|乾": 33, "艮|兑": 31, "艮|离": 56, "艮|震": 62, "艮|巽": 53, "艮|坎": 39, "艮|艮": 52, "艮|坤": 15,
"坤|乾": 12, "坤|兑": 45, "坤|离": 35, "坤|震": 16, "坤|巽": 20, "坤|坎": 8, "坤|艮": 23, "坤|坤": 2
};
const POSITION_NAMES = ["初爻", "二爻", "三爻", "四爻", "五爻", "上爻"];
function usage() {
console.log(`
Usage:
node scripts/zhouyi_cli.js cast --question "..." --method coin|yarrow [--seed demo] [--json]
node scripts/zhouyi_cli.js lookup --name 乾 [--json]
node scripts/zhouyi_cli.js lookup --number 1 [--json]
node scripts/zhouyi_cli.js search --query "利涉大川" [--json]
node scripts/zhouyi_cli.js catalog [--grade S|B|C] [--query 关键词] [--json]
`);
}
function parseArgs(argv) {
const options = {};
for (let i = 0; i < argv.length; i += 1) {
const item = argv[i];
if (!item.startsWith("--")) continue;
const key = item.slice(2);
const next = argv[i + 1];
if (!next || next.startsWith("--")) {
options[key] = true;
} else {
options[key] = next;
i += 1;
}
}
return options;
}
function createSeededRng(seedInput) {
let seed = 0x811c9dc5;
for (const ch of String(seedInput)) {
seed ^= ch.charCodeAt(0);
seed = Math.imul(seed, 16777619);
}
if (!seed) seed = 0x9e3779b9;
return () => {
seed += 0x6d2b79f5;
let t = seed;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
function randomRng() {
return () => {
if (typeof crypto.randomInt === "function") {
return crypto.randomInt(0, 1_000_000) / 1_000_000;
}
return Math.random();
};
}
function weightedPick(items, rng) {
const total = items.reduce((sum, item) => sum + item.weight, 0);
let cursor = rng() * total;
for (const item of items) {
cursor -= item.weight;
if (cursor < 0) return item.value;
}
return items[items.length - 1].value;
}
function createLine(value, coins = []) {
return {
value,
coins,
yang: value === 7 || value === 9,
moving: value === 6 || value === 9,
label: value === 6 ? "老阴" : value === 7 ? "少阳" : value === 8 ? "少阴" : "老阳"
};
}
function tossLine(method, rng) {
if (method === "yarrow") {
return createLine(
weightedPick(
[
{ value: 6, weight: 1 },
{ value: 7, weight: 5 },
{ value: 8, weight: 7 },
{ value: 9, weight: 3 }
],
rng
)
);
}
const coins = Array.from({ length: 3 }, () => (rng() < 0.5 ? 2 : 3));
return createLine(coins.reduce((sum, coin) => sum + coin, 0), coins);
}
function sameTrigramName(sourceName, trigramName) {
const aliases = { 兑: "兌", 离: "離" };
return sourceName === trigramName || sourceName === aliases[trigramName];
}
function fullHexagramName(name, upper, lower) {
if (upper.name === lower.name && sameTrigramName(name, upper.name)) {
return `name为upper.nature`;
}
return `upper.naturelower.naturename`;
}
function resolveHexagram(lines) {
const lowerBits = lines.slice(0, 3).map((line) => (line.yang ? "1" : "0")).join("");
const upperBits = lines.slice(3, 6).map((line) => (line.yang ? "1" : "0")).join("");
const lower = TRIGRAMS[lowerBits];
const upper = TRIGRAMS[upperBits];
const number = HEXAGRAM_LOOKUP[`lower.name|upper.name`];
const benjing = ZHOUYI_BENJING[number - 1];
return {
number,
name: benjing.name,
fullName: fullHexagramName(benjing.name, upper, lower),
judgment: benjing.judgment,
lines: benjing.lines,
extras: benjing.extras,
lower,
upper
};
}
function lineEntry(hexagram, index, priority) {
return {
title: `hexagram.namehexagram.lines[index].label`,
label: hexagram.lines[index].label,
text: hexagram.lines[index].text,
priority
};
}
function decideTextSource(primary, changed, moving) {
const count = moving.length;
if (count === 0) {
return {
rule: "六爻不变:以本卦卦辞为主。",
focus: "本卦卦辞",
entries: [{ title: `primary.name卦辞`, text: primary.judgment, priority: true }]
};
}
if (count === 1) {
const item = moving[0];
return {
rule: "一爻变:以该动爻爻辞为主。",
focus: primary.lines[item.index].label,
entries: [lineEntry(primary, item.index, true)]
};
}
if (count === 2) {
const indexes = moving.map((item) => item.index).sort((a, b) => a - b);
const upperIndex = indexes[indexes.length - 1];
return {
rule: "二爻变:取两条动爻爻辞,以上爻为主。",
focus: primary.lines[upperIndex].label,
entries: indexes.map((index) => lineEntry(primary, index, index === upperIndex))
};
}
if (count === 3) {
return {
rule: "三爻变:以本卦卦辞与变卦卦辞合看。",
focus: "本卦与变卦卦辞",
entries: [
{ title: `primary.name卦辞`, text: primary.judgment, priority: true },
{ title: `changed.name卦辞`, text: changed.judgment, priority: false }
]
};
}
if (count === 4) {
const staticIndexes = [0, 1, 2, 3, 4, 5].filter((index) => !moving.some((item) => item.index === index));
const lowerIndex = staticIndexes[0];
return {
rule: "四爻变:取两条静爻爻辞,以下爻为主。",
focus: primary.lines[lowerIndex].label,
entries: staticIndexes.map((index) => lineEntry(primary, index, index === lowerIndex))
};
}
if (count === 5) {
const staticIndex = [0, 1, 2, 3, 4, 5].find((index) => !moving.some((item) => item.index === index));
return {
rule: "五爻变:取变卦中唯一静爻所对应的爻辞。",
focus: changed.lines[staticIndex].label,
entries: [lineEntry(changed, staticIndex, true)]
};
}
const special =
primary.number === 1
? primary.extras.find((item) => item.label === "用九")
: primary.number === 2
? primary.extras.find((item) => item.label === "用六")
: null;
if (special) {
return {
rule: "六爻皆变:乾用用九,坤用用六。",
focus: special.label,
entries: [{ title: special.label, text: special.text, priority: true }]
};
}
return {
rule: "六爻皆变:乾坤之外,以变卦卦辞为主。",
focus: `changed.name卦辞`,
entries: [{ title: `changed.name卦辞`, text: changed.judgment, priority: true }]
};
}
function renderLineGlyph(line) {
if (line.yang) {
return line.moving ? "⚊ ○" : "⚊";
}
return line.moving ? "⚋ ×" : "⚋";
}
function castHexagram(question, method, seed) {
const rng = seed ? createSeededRng(seed) : randomRng();
const lines = Array.from({ length: 6 }, () => tossLine(method, rng));
const changedLines = lines.map((line) => ({
...line,
yang: line.moving ? !line.yang : line.yang,
moving: false
}));
const primary = resolveHexagram(lines);
const changed = resolveHexagram(changedLines);
const moving = lines
.map((line, index) => ({ index, line }))
.filter((item) => item.line.moving)
.map((item) => ({
index: item.index,
position: POSITION_NAMES[item.index],
originalLabel: primary.lines[item.index].label,
lineType: item.line.label,
text: primary.lines[item.index].text
}));
return {
question,
method,
seed: seed || null,
lines: lines.map((line, index) => ({
index,
position: POSITION_NAMES[index],
lineType: line.label,
value: line.value,
moving: line.moving,
yang: line.yang,
coins: line.coins,
glyph: renderLineGlyph(line)
})),
primary,
changed,
moving,
decision: decideTextSource(primary, changed, moving)
};
}
function lookupHexagramByName(name) {
return ZHOUYI_BENJING.find((item) => item.name === name) || null;
}
function lookupHexagramByNumber(number) {
const value = Number(number);
if (!Number.isInteger(value) || value < 1 || value > 64) return null;
return ZHOUYI_BENJING[value - 1];
}
function searchHexagrams(query) {
const keyword = String(query || "").trim();
return ZHOUYI_BENJING.filter((item) => {
if (item.name.includes(keyword) || item.judgment.includes(keyword)) return true;
if (item.lines.some((line) => line.text.includes(keyword) || line.label.includes(keyword))) return true;
if (item.extras.some((extra) => extra.text.includes(keyword) || extra.label.includes(keyword))) return true;
return false;
}).map((item) => ({
number: item.number,
name: item.name,
judgment: item.judgment
}));
}
function filterCatalog(query, grade) {
return DIVINATION_SYSTEMS.filter((item) => {
const gradeOk = !grade || grade === "all" || item.grade === grade;
if (!gradeOk) return false;
if (!query) return true;
const haystack = [
item.name,
item.family,
item.basis,
item.capability,
item.guardrail,
...(item.bestFor || []),
...(item.inputs || [])
].join(" ");
return haystack.includes(query);
});
}
function print(payload, asJson, formatter) {
if (asJson) {
console.log(JSON.stringify(payload, null, 2));
return;
}
console.log(formatter(payload));
}
function formatCast(payload) {
const lines = payload.lines
.slice()
.reverse()
.map((line) => `line.position line.glyph line.lineType`)
.join("\n");
const selected = payload.decision.entries
.map((entry) => `entry.title""\nentry.text`)
.join("\n\n");
return [
`问题:payload.question || "未填写"`,
`方法:payload.method`,
`本卦:payload.primary.number. payload.primary.fullName`,
`变卦:payload.changed.number. payload.changed.fullName`,
`动爻:"无"`,
"",
lines,
"",
`取辞规则:payload.decision.rule`,
selected
].join("\n");
}
function formatLookup(payload) {
const lines = payload.lines.map((line) => `line.label:line.text`).join("\n");
const extras = payload.extras.length ? `\npayload.extras.map((item) => `${item.label:item.text`).join("\n")}` : "";
return `payload.number. payload.name\n卦辞:payload.judgment\nlinesextras`;
}
function formatSearch(results) {
if (!results.length) return "未找到匹配卦象。";
return results.map((item) => `item.number. item.name:item.judgment`).join("\n");
}
function formatCatalog(results) {
if (!results.length) return "未找到匹配体系。";
return results
.map((item) => `item.grade item.name [item.status]\n依据:item.basis\n能力:item.capability\n边界:item.guardrail`)
.join("\n\n");
}
function main() {
const command = process.argv[2];
const options = parseArgs(process.argv.slice(3));
const asJson = Boolean(options.json || options.format === "json");
if (!command || command === "help" || command === "--help" || command === "-h") {
usage();
process.exit(command ? 0 : 1);
}
if (command === "cast") {
const method = options.method === "yarrow" ? "yarrow" : "coin";
const payload = castHexagram(options.question || "", method, options.seed || "");
print(payload, asJson, formatCast);
return;
}
if (command === "lookup") {
const result = options.name ? lookupHexagramByName(options.name) : lookupHexagramByNumber(options.number);
if (!result) {
console.error("未找到指定卦象。请提供 --name 或 --number。");
process.exit(1);
}
print(result, asJson, formatLookup);
return;
}
if (command === "search") {
if (!options.query) {
console.error("search 需要 --query。");
process.exit(1);
}
const results = searchHexagrams(options.query);
print(results, asJson, formatSearch);
return;
}
if (command === "catalog") {
const results = filterCatalog(options.query || "", options.grade || "all");
print(results, asJson, formatCatalog);
return;
}
console.error(`未知命令:command`);
usage();
process.exit(1);
}
main();
FILE:scripts/publish.sh
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "BASH_SOURCE[0]")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
DIST_DIR="$(cd "$PROJECT_DIR/.." && pwd)/dist"
VERSION=""
DISPLAY_NAME=""
usage() {
echo "Usage: $(basename "$0") --version <semver> [--name <display-name>]"
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
--version)
VERSION="-"
shift 2
;;
--name)
DISPLAY_NAME="-"
shift 2
;;
*)
usage
;;
esac
done
[[ -n "$VERSION" ]] || usage
python3 - <<PY
import json
from pathlib import Path
project = Path(r"$PROJECT_DIR")
version = "$VERSION"
for filename in ("package.json", "_meta.json"):
path = project / filename
data = json.loads(path.read_text(encoding="utf-8"))
data["version"] = version
path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
skill_path = project / "SKILL.md"
text = skill_path.read_text(encoding="utf-8")
if "version: " in text:
import re
text = re.sub(
r'(^\s*version:\s*")[^"]+(")',
lambda m: f'{m.group(1)}{version}{m.group(2)}',
text,
flags=re.M,
)
skill_path.write_text(text, encoding="utf-8")
PY
mkdir -p "$DIST_DIR"
ZIP_PATH="$DIST_DIR/zhouyi-benjing-oracle-$VERSION.zip"
rm -f "$ZIP_PATH"
cd "$(dirname "$PROJECT_DIR")"
zip -rq "$ZIP_PATH" "$(basename "$PROJECT_DIR")" -x "*/__pycache__/*" "*/.DS_Store"
echo "Built $ZIP_PATH"
echo ""
echo "ClawHub CLI publish command:"
if [[ -n "$DISPLAY_NAME" ]]; then
echo "clawhub publish \"$PROJECT_DIR\" --version \"$VERSION\" --name \"$DISPLAY_NAME\""
else
echo "clawhub publish \"$PROJECT_DIR\" --version \"$VERSION\""
fi
FILE:scripts/build_zhouyi_data.py
#!/usr/bin/env python3
"""Build a browser-loadable Zhouyi Benjing data file from the local source text."""
from __future__ import annotations
import json
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "references" / "zhouyi-benjing-source.txt"
OUTPUT = ROOT / "data" / "zhouyi-benjing.js"
LINE_LABELS = ("初九", "初六", "九二", "六二", "九三", "六三", "九四", "六四", "九五", "六五", "上九", "上六")
EXTRA_LABELS = ("用九", "用六")
def compact(value: str) -> str:
return re.sub(r"\s+", "", value.strip())
def parse_source(text: str) -> list[dict]:
lines = [line.strip() for line in text.splitlines()]
hexagrams: list[dict] = []
i = 0
while i < len(lines):
if not re.match(r"^第\s*\S+\s*卦$", lines[i]):
i += 1
continue
number = len(hexagrams) + 1
i += 1
while i < len(lines) and not lines[i]:
i += 1
name_line = lines[i]
inline_judgment = ""
inline_match = re.match(r"^([^:]+):(.+)$", name_line)
if inline_match:
name = inline_match.group(1).strip()
inline_judgment = inline_match.group(2).strip()
else:
name = name_line
i += 1
while i < len(lines) and not lines[i]:
i += 1
judgment_parts: list[str] = [inline_judgment] if inline_judgment else []
yao_lines: list[dict] = []
extra_lines: list[dict] = []
while i < len(lines):
line = lines[i]
if re.match(r"^第\s*\S+\s*卦$", line):
break
i += 1
if not line:
continue
match = re.match(r"^([^:]+):(.+)$", line)
if not match:
if judgment_parts and not yao_lines and not extra_lines:
judgment_parts.append(line)
continue
label, text_part = match.group(1), match.group(2)
if label in LINE_LABELS:
yao_lines.append({"label": label, "text": text_part.strip()})
elif label in EXTRA_LABELS:
extra_lines.append({"label": label, "text": text_part.strip()})
elif compact(label) == compact(name):
judgment_parts.append(text_part.strip())
elif judgment_parts and not yao_lines and not extra_lines:
judgment_parts.append(line)
hexagrams.append(
{
"number": number,
"name": name,
"judgment": "".join(judgment_parts),
"lines": yao_lines,
"extras": extra_lines,
}
)
return hexagrams
def validate(hexagrams: list[dict]) -> None:
if len(hexagrams) != 64:
raise SystemExit(f"expected 64 hexagrams, got {len(hexagrams)}")
for item in hexagrams:
if not item["judgment"]:
raise SystemExit(f"hexagram {item['number']} {item['name']} has no judgment")
if len(item["lines"]) != 6:
raise SystemExit(
f"hexagram {item['number']} {item['name']} expected 6 lines, got {len(item['lines'])}"
)
if hexagrams[0]["name"] != "乾" or hexagrams[0]["extras"][0]["label"] != "用九":
raise SystemExit("乾卦 or 用九 parse failed")
if hexagrams[1]["name"] != "坤" or hexagrams[1]["extras"][0]["label"] != "用六":
raise SystemExit("坤卦 or 用六 parse failed")
if hexagrams[2]["lines"][1]["text"] != "屯如邅如,乘馬班如。匪寇婚媾,女子貞不字,十年乃字。":
raise SystemExit("屯六二 source text was not preserved exactly")
def main() -> None:
text = SOURCE.read_text(encoding="utf-8")
hexagrams = parse_source(text)
validate(hexagrams)
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
payload = json.dumps(hexagrams, ensure_ascii=False, indent=2)
OUTPUT.write_text(
"const ZHOUYI_BENJING = "
+ payload
+ ";\n\n"
+ "if (typeof window !== \"undefined\") window.ZHOUYI_BENJING = ZHOUYI_BENJING;\n"
+ "if (typeof module !== \"undefined\") module.exports = ZHOUYI_BENJING;\n",
encoding="utf-8",
)
print(f"wrote {OUTPUT.relative_to(ROOT)} with {len(hexagrams)} hexagrams")
if __name__ == "__main__":
main()
FILE:data/system-catalog.js
const DIVINATION_SYSTEMS = [
{
id: "zhouyi-benjing",
name: "周易本经占筮",
family: "易",
grade: "S",
status: "已启用",
basis: "《周易》本经卦辞、爻辞、用九、用六",
bestFor: ["当下决策", "时机判断", "关系与事业抉择", "自我复盘"],
inputs: ["一个明确问题", "起卦方式"],
capability: "可起卦、取辞、引用本经原文并给出现代解释。",
guardrail: "只作解释性参考,不替代专业判断。"
},
{
id: "yijing-library",
name: "六十四卦本经库",
family: "易",
grade: "S",
status: "已启用",
basis: "本地 Gutenberg《易經》整理文本",
bestFor: ["查卦辞", "查爻辞", "校验卦序", "学习原文"],
inputs: ["卦名、卦序或关键词"],
capability: "可检索六十四卦卦辞和六爻原文。",
guardrail: "当前只含本经,不混入彖象传和后世注解。"
},
{
id: "meihua",
name: "梅花易数",
family: "易象",
grade: "B",
status: "知识库",
basis: "以卦象、体用、生克、动爻为主的后世易占体系",
bestFor: ["快速起象", "当下气机", "小事趋势"],
inputs: ["数、时间、物象或随机触发"],
capability: "当前只提供体系说明和路由建议,暂不自动断梅花盘。",
guardrail: "避免把数字取卦与《周易》本经取辞混为一谈。"
},
{
id: "liuyao",
name: "六爻纳甲",
family: "易占",
grade: "B",
status: "待校验",
basis: "纳甲、六亲、世应、月建日辰、动变生克",
bestFor: ["具体事项成败", "失物", "官司", "短期应期"],
inputs: ["六爻结果", "起卦时间", "明确用神"],
capability: "暂不开放自动断卦,只保留未来高精度实现入口。",
guardrail: "必须先校验纳甲、世应、六亲、月日旺衰,否则不输出结论。"
},
{
id: "xiaoliuren",
name: "小六壬",
family: "民间时占",
grade: "C",
status: "知识库",
basis: "大安、留连、速喜、赤口、小吉、空亡六神课",
bestFor: ["轻量日常问事", "出门前判断", "粗略吉凶"],
inputs: ["月、日、时或指定数字"],
capability: "当前只解释体系差异,不作为周易本经断语依据。",
guardrail: "小六壬不是《周易》原文体系,不能冒充易经本经。"
},
{
id: "qimen",
name: "奇门遁甲",
family: "三式",
grade: "B",
status: "待校验",
basis: "节气、阴阳遁、局数、九星八门八神、三奇六仪",
bestFor: ["择时", "方位", "项目推进窗口", "行动策略"],
inputs: ["精确时间", "地点/时区", "问事类别"],
capability: "只纳入百科与路由,不使用未校验日柱和定局算法。",
guardrail: "四柱、节气、值符值使必须通过基准盘测试后才能开放排盘。"
},
{
id: "bazi",
name: "八字四柱",
family: "命理",
grade: "B",
status: "待校验",
basis: "年、月、日、时四柱与十神、旺衰、大运",
bestFor: ["长期人格底色", "阶段节奏", "职业倾向"],
inputs: ["出生年月日时", "出生地", "性别/历法说明"],
capability: "当前只记录资料要求和解释边界。",
guardrail: "必须使用可靠历法库和流派说明,不能用简化干支表替代。"
},
{
id: "ziwei",
name: "紫微斗数",
family: "命理",
grade: "B",
status: "待校验",
basis: "农历生日、时辰、命宫身宫、十四主星、辅煞、四化",
bestFor: ["人生阶段", "十二宫主题", "关系与事业结构"],
inputs: ["农历/公历生日", "时辰", "性别", "历法转换规则"],
capability: "当前不自动排盘,避免命宫、五行局、安星错误。",
guardrail: "必须通过成熟排盘库交叉验证后才输出命盘解释。"
},
{
id: "fengshui",
name: "风水与九宫飞星",
family: "环境",
grade: "C",
status: "知识库",
basis: "空间方位、流年飞星、住宅格局与现实动线",
bestFor: ["居住调整", "办公布局", "空间复盘"],
inputs: ["户型图", "朝向", "入住时间", "实际使用方式"],
capability: "只提供知识框架,不用缺资料的脚本给方位断语。",
guardrail: "没有户型和朝向时,只能做一般环境建议。"
},
{
id: "tarot",
name: "塔罗",
family: "西方象征",
grade: "C",
status: "知识库",
basis: "牌阵、牌义、关系与短期趋势象征",
bestFor: ["心理镜像", "关系觉察", "短期选择题"],
inputs: ["牌阵", "抽牌结果", "问题"],
capability: "作为百科补充,不参与周易本经结论。",
guardrail: "塔罗不是周易体系,不能与本经原文互相冒充依据。"
},
{
id: "astrology",
name: "西方星盘",
family: "西方占星",
grade: "C",
status: "知识库",
basis: "出生星图、行运、合盘",
bestFor: ["人格模式", "关系合盘", "阶段性主题"],
inputs: ["出生年月日时", "出生地"],
capability: "当前只作为百科条目和未来扩展方向。",
guardrail: "需要精确天文计算库,不使用泛星座替代星盘。"
},
{
id: "routing",
name: "综合问事路由",
family: "产品层",
grade: "S",
status: "已启用",
basis: "问题类型、资料完整度、体系可信度",
bestFor: ["选择体系", "明确资料缺口", "避免误用"],
inputs: ["用户问题", "已有资料"],
capability: "帮助判断该用本经占筮、查卦库,还是等待更完整资料。",
guardrail: "宁可降级说明,也不冒充高精度。"
}
];
if (typeof window !== "undefined") window.DIVINATION_SYSTEMS = DIVINATION_SYSTEMS;
if (typeof module !== "undefined") module.exports = DIVINATION_SYSTEMS;
FILE:data/zhouyi-benjing.js
const ZHOUYI_BENJING = [
{
"number": 1,
"name": "乾",
"judgment": "元,亨,利,貞。",
"lines": [
{
"label": "初九",
"text": "潛龍,勿用。"
},
{
"label": "九二",
"text": "見龍在田,利見大人。"
},
{
"label": "九三",
"text": "君子終日乾乾,夕惕,若厲,無咎。"
},
{
"label": "九四",
"text": "或躍在淵,無咎。"
},
{
"label": "九五",
"text": "飛龍在天,利見大人。"
},
{
"label": "上九",
"text": "亢龍有悔。"
}
],
"extras": [
{
"label": "用九",
"text": "見群龍無首,吉。"
}
]
},
{
"number": 2,
"name": "坤",
"judgment": "元,亨,利牝馬之貞。君子有攸往,先迷後得主,利西南得朋,東北喪朋。安貞,吉。",
"lines": [
{
"label": "初六",
"text": "履霜,堅冰至。"
},
{
"label": "六二",
"text": "直,方,大,不習無不利。"
},
{
"label": "六三",
"text": "含章可貞。或從王事,無成有終。"
},
{
"label": "六四",
"text": "括囊;無咎,無譽。"
},
{
"label": "六五",
"text": "黃裳,元吉。"
},
{
"label": "上六",
"text": "戰龍於野,其血玄黃。"
}
],
"extras": [
{
"label": "用六",
"text": "利永貞。"
}
]
},
{
"number": 3,
"name": "屯",
"judgment": "元,亨,利,貞,勿用,有攸往,利建侯。",
"lines": [
{
"label": "初九",
"text": "磐桓;利居貞,利建侯。"
},
{
"label": "六二",
"text": "屯如邅如,乘馬班如。匪寇婚媾,女子貞不字,十年乃字。"
},
{
"label": "六三",
"text": "既鹿無虞,惟入于林中,君子幾不如舍,往吝。"
},
{
"label": "六四",
"text": "乘馬班如,求婚媾,往吉,無不利。"
},
{
"label": "九五",
"text": "屯其膏,小貞吉,大貞凶。"
},
{
"label": "上六",
"text": "乘馬班如,泣血漣如。"
}
],
"extras": []
},
{
"number": 4,
"name": "蒙",
"judgment": "亨。匪我求童蒙,童蒙求我。初噬告,再三瀆,瀆則不告。利貞。",
"lines": [
{
"label": "初六",
"text": "發蒙,利用刑人,用說桎梏,以往吝。"
},
{
"label": "九二",
"text": "包蒙,吉;納婦,吉;子克家。"
},
{
"label": "六三",
"text": "勿用娶女;見金夫,不有躬,無攸利。"
},
{
"label": "六四",
"text": "困蒙,吝。"
},
{
"label": "六五",
"text": "童蒙,吉。"
},
{
"label": "上九",
"text": "擊蒙;不利為寇,利御寇。"
}
],
"extras": []
},
{
"number": 5,
"name": "需",
"judgment": "有孚,光亨,貞吉。利涉大川。",
"lines": [
{
"label": "初九",
"text": "需于郊。利用恆,無咎。"
},
{
"label": "九二",
"text": "需于沙。小有言,終吉。"
},
{
"label": "九三",
"text": "需于泥,致寇至。"
},
{
"label": "六四",
"text": "需于血,出自穴。"
},
{
"label": "九五",
"text": "需于酒食,貞吉。"
},
{
"label": "上六",
"text": "入于穴,有不速之客三人來,敬之終吉。"
}
],
"extras": []
},
{
"number": 6,
"name": "訟",
"judgment": "有孚,窒。惕中吉。終凶。利見大人,不利涉大川。",
"lines": [
{
"label": "初六",
"text": "不永所事,小有言,終吉。"
},
{
"label": "九二",
"text": "不克訟,歸而逋,其邑人三百戶,無眚。"
},
{
"label": "六三",
"text": "食舊德,貞厲,終吉,或從王事,無成。"
},
{
"label": "九四",
"text": "不克訟,復即命,渝安貞,吉。"
},
{
"label": "九五",
"text": "訟元吉。"
},
{
"label": "上九",
"text": "或錫之鞶帶,終朝三褫之。"
}
],
"extras": []
},
{
"number": 7,
"name": "師",
"judgment": "貞,丈人,吉無咎。",
"lines": [
{
"label": "初六",
"text": "師出以律,否臧凶。"
},
{
"label": "九二",
"text": "在師中,吉無咎,王三錫命。"
},
{
"label": "六三",
"text": "師或輿尸,凶。"
},
{
"label": "六四",
"text": "師左次,無咎。"
},
{
"label": "六五",
"text": "田有禽,利執言,無咎。長子帥師,弟子輿尸,貞凶。"
},
{
"label": "上六",
"text": "大君有命,開國承家,小人勿用。"
}
],
"extras": []
},
{
"number": 8,
"name": "比",
"judgment": "吉。原筮元永貞,無咎。不寧方來,後夫凶。",
"lines": [
{
"label": "初六",
"text": "有孚比之,無咎。有孚盈缶,終來有他,吉。"
},
{
"label": "六二",
"text": "比之自內,貞吉。"
},
{
"label": "六三",
"text": "比之匪人。"
},
{
"label": "六四",
"text": "外比之,貞吉。"
},
{
"label": "九五",
"text": "顯比,王用三驅,失前禽。邑人不誡,吉。"
},
{
"label": "上六",
"text": "比之無首,凶。"
}
],
"extras": []
},
{
"number": 9,
"name": "小畜",
"judgment": "亨。密雲不雨,自我西郊。",
"lines": [
{
"label": "初九",
"text": "復自道,何其咎,吉。"
},
{
"label": "九二",
"text": "牽復,吉。"
},
{
"label": "九三",
"text": "輿說輻,夫妻反目。"
},
{
"label": "六四",
"text": "有孚,血去。惕出,無咎。"
},
{
"label": "九五",
"text": "有孚攣如,富以其鄰。"
},
{
"label": "上九",
"text": "既雨既處,尚德載婦,貞厲。月幾望,君子征凶。"
}
],
"extras": []
},
{
"number": 10,
"name": "履",
"judgment": "履虎尾,不咥人,亨。",
"lines": [
{
"label": "初九",
"text": "素履,往無咎。"
},
{
"label": "九二",
"text": "履道坦坦,幽人貞吉。"
},
{
"label": "六三",
"text": "眇能視,跛能履,履虎尾,咥人,凶。武人為于大君。"
},
{
"label": "九四",
"text": "履虎尾,愬愬,終吉。"
},
{
"label": "九五",
"text": "夬履,貞厲。"
},
{
"label": "上九",
"text": "視履考祥,其旋元吉。"
}
],
"extras": []
},
{
"number": 11,
"name": "泰",
"judgment": "小往大來,吉亨。",
"lines": [
{
"label": "初九",
"text": "拔茅茹,以其彙,征吉。"
},
{
"label": "九二",
"text": "包荒,用馮河,不遐遺,朋亡,得尚于中行。"
},
{
"label": "九三",
"text": "無平不陂,無往不復,艱貞無咎。勿恤其孚,于食有福。"
},
{
"label": "六四",
"text": "翩翩不富,以其鄰,不戒以孚。"
},
{
"label": "六五",
"text": "帝乙歸妹,以祉元吉。"
},
{
"label": "上六",
"text": "城復于隍,勿用師。自邑告命,貞吝。"
}
],
"extras": []
},
{
"number": 12,
"name": "否",
"judgment": "否之匪人,不利君子貞,大往小來。",
"lines": [
{
"label": "初六",
"text": "拔茅茹,以其彙,貞吉亨。"
},
{
"label": "六二",
"text": "包承。小人吉,大人否亨。"
},
{
"label": "六三",
"text": "包羞。"
},
{
"label": "九四",
"text": "有命無咎,疇離祉。"
},
{
"label": "九五",
"text": "休否,大人吉。其亡其亡,繫于苞桑。"
},
{
"label": "上九",
"text": "傾否,先否後喜。"
}
],
"extras": []
},
{
"number": 13,
"name": "同人",
"judgment": "同人于野,亨。利涉大川,利君子貞。",
"lines": [
{
"label": "初九",
"text": "同人于門,無咎。"
},
{
"label": "六二",
"text": "同人于宗,吝。"
},
{
"label": "九三",
"text": "伏戎于莽,升其高陵,三歲不興。"
},
{
"label": "九四",
"text": "乘其墉,弗克攻,吉。"
},
{
"label": "九五",
"text": "同人,先號咷而後笑。大師克相遇。"
},
{
"label": "上九",
"text": "同人于郊,無悔。"
}
],
"extras": []
},
{
"number": 14,
"name": "大有",
"judgment": "元亨。",
"lines": [
{
"label": "初九",
"text": "無交害,匪咎,艱則無咎。"
},
{
"label": "九二",
"text": "大車以載,有攸往,無咎。"
},
{
"label": "九三",
"text": "公用亨于天子,小人弗克。"
},
{
"label": "九四",
"text": "匪其彭,無咎。"
},
{
"label": "六五",
"text": "厥孚交如,威如;吉。"
},
{
"label": "上九",
"text": "自天佑之,吉無不利。"
}
],
"extras": []
},
{
"number": 15,
"name": "謙",
"judgment": "亨,君子有終。",
"lines": [
{
"label": "初六",
"text": "謙謙君子,用涉大川,吉。"
},
{
"label": "六二",
"text": "鳴謙,貞吉。"
},
{
"label": "九三",
"text": "勞謙君子,有終吉。"
},
{
"label": "六四",
"text": "無不利,撝謙。"
},
{
"label": "六五",
"text": "不富,以其鄰,利用侵伐,無不利。"
},
{
"label": "上六",
"text": "鳴謙,利用行師,征邑國。"
}
],
"extras": []
},
{
"number": 16,
"name": "豫",
"judgment": "利建侯行師。",
"lines": [
{
"label": "初六",
"text": "鳴豫,凶。"
},
{
"label": "六二",
"text": "介于石,不終日,貞吉。"
},
{
"label": "六三",
"text": "盱豫,悔。遲有悔。"
},
{
"label": "九四",
"text": "由豫,大有得。勿疑。朋盍簪。"
},
{
"label": "六五",
"text": "貞疾,恆不死。"
},
{
"label": "上六",
"text": "冥豫,成有渝,無咎。"
}
],
"extras": []
},
{
"number": 17,
"name": "隨",
"judgment": "元亨利貞,無咎。",
"lines": [
{
"label": "初九",
"text": "官有渝,貞吉。出門交有功。"
},
{
"label": "六二",
"text": "係小子,失丈夫。"
},
{
"label": "六三",
"text": "係丈夫,失小子。隨有求得,利居貞。"
},
{
"label": "九四",
"text": "隨有獲,貞凶。有孚在道,以明,何咎。"
},
{
"label": "九五",
"text": "孚于嘉,吉。"
},
{
"label": "上六",
"text": "拘系之,乃從維之。王用亨于西山。"
}
],
"extras": []
},
{
"number": 18,
"name": "蠱",
"judgment": "元亨,利涉大川。先甲三日,後甲三日。",
"lines": [
{
"label": "初六",
"text": "幹父之蠱,有子,考無咎,厲終吉。"
},
{
"label": "九二",
"text": "幹母之蠱,不可貞。"
},
{
"label": "九三",
"text": "幹父小有晦,無大咎。"
},
{
"label": "六四",
"text": "裕父之蠱,往見吝。"
},
{
"label": "六五",
"text": "幹父之蠱,用譽。"
},
{
"label": "上九",
"text": "不事王侯,高尚其事。"
}
],
"extras": []
},
{
"number": 19,
"name": "臨",
"judgment": "元,亨,利,貞。至于八月有凶。",
"lines": [
{
"label": "初九",
"text": "咸臨,貞吉。"
},
{
"label": "九二",
"text": "咸臨,吉無不利。"
},
{
"label": "六三",
"text": "甘臨,無攸利。既憂之,無咎。"
},
{
"label": "六四",
"text": "至臨,無咎。"
},
{
"label": "六五",
"text": "知臨,大君之宜,吉。"
},
{
"label": "上六",
"text": "敦臨,吉無咎。"
}
],
"extras": []
},
{
"number": 20,
"name": "觀",
"judgment": "盥而不薦,有孚顒若。",
"lines": [
{
"label": "初六",
"text": "童觀,小人無咎,君子吝。"
},
{
"label": "六二",
"text": "窺觀,利女貞。"
},
{
"label": "六三",
"text": "觀我生,進退。"
},
{
"label": "六四",
"text": "觀國之光,利用賓于王。"
},
{
"label": "九五",
"text": "觀我生,君子無咎。"
},
{
"label": "上九",
"text": "觀其生,君子無咎。"
}
],
"extras": []
},
{
"number": 21,
"name": "噬嗑",
"judgment": "亨。利用獄。",
"lines": [
{
"label": "初九",
"text": "履校滅趾,無咎。"
},
{
"label": "六二",
"text": "噬膚滅鼻,無咎。"
},
{
"label": "六三",
"text": "噬臘肉,遇毒;小吝,無咎。"
},
{
"label": "九四",
"text": "噬乾胏,得金矢,利艱貞,吉。"
},
{
"label": "六五",
"text": "噬乾肉,得黃金,貞厲,無咎。"
},
{
"label": "上九",
"text": "何校滅耳,凶。"
}
],
"extras": []
},
{
"number": 22,
"name": "賁",
"judgment": "亨。小利有所往。",
"lines": [
{
"label": "初九",
"text": "賁其趾,舍車而徒。"
},
{
"label": "六二",
"text": "賁其須。"
},
{
"label": "九三",
"text": "賁如濡如,永貞吉。"
},
{
"label": "六四",
"text": "賁如皤如,白馬翰如,匪寇婚媾。"
},
{
"label": "六五",
"text": "賁于丘園,束帛戔戔,吝,終吉。"
},
{
"label": "上九",
"text": "白賁,無咎。"
}
],
"extras": []
},
{
"number": 23,
"name": "剝",
"judgment": "不利有攸往。",
"lines": [
{
"label": "初六",
"text": "剝床以足,蔑貞凶。"
},
{
"label": "六二",
"text": "剝床以辨,蔑貞凶。"
},
{
"label": "六三",
"text": "剝之,無咎。"
},
{
"label": "六四",
"text": "剝床以膚,凶。"
},
{
"label": "六五",
"text": "貫魚,以宮人寵,無不利。"
},
{
"label": "上九",
"text": "碩果不食,君子得輿,小人剝廬。"
}
],
"extras": []
},
{
"number": 24,
"name": "復",
"judgment": "亨。出入無疾,朋來無咎。反復其道,七日來復,利有攸往。",
"lines": [
{
"label": "初九",
"text": "不復遠,無祗悔,元吉。"
},
{
"label": "六二",
"text": "休復,吉。"
},
{
"label": "六三",
"text": "頻復厲,無咎。"
},
{
"label": "六四",
"text": "中行獨復。"
},
{
"label": "六五",
"text": "敦復,無悔。"
},
{
"label": "上六",
"text": "迷復,凶,有災眚。用行師,終有大敗,以其國君,凶;至于十年,不克征。"
}
],
"extras": []
},
{
"number": 25,
"name": "無妄",
"judgment": "元,亨,利,貞。其匪正有眚,不利有攸往。",
"lines": [
{
"label": "初九",
"text": "無妄,往吉。"
},
{
"label": "六二",
"text": "不耕獲,不菑畬,則利有攸往。"
},
{
"label": "六三",
"text": "無妄之災,或繫之牛,行人之得,邑人之災。"
},
{
"label": "九四",
"text": "可貞,無咎。"
},
{
"label": "九五",
"text": "無妄之疾,勿藥有喜。"
},
{
"label": "上九",
"text": "無妄,行有眚,無攸利。"
}
],
"extras": []
},
{
"number": 26,
"name": "大畜",
"judgment": "利貞,不家食吉,利涉大川。",
"lines": [
{
"label": "初九",
"text": "有厲利已。"
},
{
"label": "九二",
"text": "輿說輻。"
},
{
"label": "九三",
"text": "良馬逐,利艱貞。日閑輿衛,利有攸往。"
},
{
"label": "六四",
"text": "童牛之牿,元吉。"
},
{
"label": "六五",
"text": "豶豕之牙,吉。"
},
{
"label": "上九",
"text": "何天之衢,亨。"
}
],
"extras": []
},
{
"number": 27,
"name": "頤",
"judgment": "貞吉。觀頤,自求口實。",
"lines": [
{
"label": "初九",
"text": "舍爾靈龜,觀我朵頤,凶。"
},
{
"label": "六二",
"text": "顛頤,拂經于丘頤,征凶。"
},
{
"label": "六三",
"text": "拂頤,貞凶,十年勿用,無攸利。"
},
{
"label": "六四",
"text": "顛頤吉,虎視眈眈,其欲逐逐,無咎。"
},
{
"label": "六五",
"text": "拂經,居貞吉,不可涉大川。"
},
{
"label": "上九",
"text": "由頤,厲吉,利涉大川。"
}
],
"extras": []
},
{
"number": 28,
"name": "大過",
"judgment": "棟橈,利有攸往,亨。",
"lines": [
{
"label": "初六",
"text": "藉用白茅,無咎。"
},
{
"label": "九二",
"text": "枯楊生稊,老夫得其女妻,無不利。"
},
{
"label": "九三",
"text": "棟橈,凶。"
},
{
"label": "九四",
"text": "棟隆,吉;有它吝。"
},
{
"label": "九五",
"text": "枯楊生華,老婦得士夫,無咎無譽。"
},
{
"label": "上六",
"text": "過涉滅頂,凶,無咎。"
}
],
"extras": []
},
{
"number": 29,
"name": "坎",
"judgment": "習坎,有孚,維心亨,行有尚。",
"lines": [
{
"label": "初六",
"text": "習坎,入于坎窞,凶。"
},
{
"label": "九二",
"text": "坎有險,求小得。"
},
{
"label": "六三",
"text": "來之坎坎,險且枕,入于坎窞,勿用。"
},
{
"label": "六四",
"text": "樽酒簋貳,用缶,納約自牖,終無咎。"
},
{
"label": "九五",
"text": "坎不盈,祗既平,無咎。"
},
{
"label": "上六",
"text": "係用徽纆,寘于叢棘,三歲不得,凶。"
}
],
"extras": []
},
{
"number": 30,
"name": "離",
"judgment": "利貞,亨。畜牝牛,吉。",
"lines": [
{
"label": "初九",
"text": "履錯然,敬之無咎。"
},
{
"label": "六二",
"text": "黃離,元吉。"
},
{
"label": "九三",
"text": "日昃之離,不鼓缶而歌,則大耋之嗟,凶。"
},
{
"label": "九四",
"text": "突如其來如,焚如,死如,棄如。"
},
{
"label": "六五",
"text": "出涕沱若,戚嗟若,吉。"
},
{
"label": "上九",
"text": "王用出征,有嘉折首,獲匪其醜,無咎。"
}
],
"extras": []
},
{
"number": 31,
"name": "咸",
"judgment": "亨,利貞,取女吉。",
"lines": [
{
"label": "初六",
"text": "咸其拇。"
},
{
"label": "六二",
"text": "咸其腓,凶,居吉。"
},
{
"label": "九三",
"text": "咸其股,執其隨,往吝。"
},
{
"label": "九四",
"text": "貞吉悔亡,憧憧往來,朋從爾思。"
},
{
"label": "九五",
"text": "咸其脢,無悔。"
},
{
"label": "上六",
"text": "咸其輔,頰,舌。"
}
],
"extras": []
},
{
"number": 32,
"name": "恆",
"judgment": "亨,無咎,利貞,利有攸往。",
"lines": [
{
"label": "初六",
"text": "浚恆,貞凶,無攸利。"
},
{
"label": "九二",
"text": "悔亡。"
},
{
"label": "九三",
"text": "不恆其德,或承之羞,貞吝。"
},
{
"label": "九四",
"text": "田無禽。"
},
{
"label": "六五",
"text": "恆其德,貞,婦人吉,夫子凶。"
},
{
"label": "上六",
"text": "振恆,凶。"
}
],
"extras": []
},
{
"number": 33,
"name": "遯",
"judgment": "亨,小利貞。",
"lines": [
{
"label": "初六",
"text": "遯尾,厲,勿用有攸往。"
},
{
"label": "六二",
"text": "執之用黃牛之革,莫之勝說。"
},
{
"label": "九三",
"text": "係遯,有疾厲,畜臣妾吉。"
},
{
"label": "九四",
"text": "好遯君子吉,小人否。"
},
{
"label": "九五",
"text": "嘉遯,貞吉。"
},
{
"label": "上九",
"text": "肥遯,無不利。"
}
],
"extras": []
},
{
"number": 34,
"name": "大壯",
"judgment": "利貞。",
"lines": [
{
"label": "初九",
"text": "壯于趾,征凶,有孚。"
},
{
"label": "九二",
"text": "貞吉。"
},
{
"label": "九三",
"text": "小人用壯,君子用罔,貞厲。羝羊觸藩,羸其角。"
},
{
"label": "九四",
"text": "貞吉悔亡,藩決不羸,壯于大輿之輹。"
},
{
"label": "六五",
"text": "喪羊于易,無悔。"
},
{
"label": "上六",
"text": "羝羊觸藩,不能退,不能遂,無攸利,艱則吉。"
}
],
"extras": []
},
{
"number": 35,
"name": "晉",
"judgment": "康侯用錫馬蕃庶,晝日三接。",
"lines": [
{
"label": "初六",
"text": "晉如,摧如,貞吉。罔孚,裕無咎。"
},
{
"label": "六二",
"text": "晉如,愁如,貞吉。受茲介福,于其王母。"
},
{
"label": "六三",
"text": "眾允,悔亡。"
},
{
"label": "九四",
"text": "晉如鼫鼠,貞厲。"
},
{
"label": "六五",
"text": "悔亡,失得勿恤,往吉無不利。"
},
{
"label": "上九",
"text": "晉其角,維用伐邑,厲吉無咎,貞吝。"
}
],
"extras": []
},
{
"number": 36,
"name": "明夷",
"judgment": "利艱貞。",
"lines": [
{
"label": "初九",
"text": "明夷于飛,垂其翼。君子于行,三日不食,有攸往,主人有言。"
},
{
"label": "六二",
"text": "明夷,夷于左股,用拯馬壯,吉。"
},
{
"label": "九三",
"text": "明夷于南狩,得其大首,不可疾貞。"
},
{
"label": "六四",
"text": "入于左腹,獲明夷之心,于出門庭。"
},
{
"label": "六五",
"text": "箕子之明夷,利貞。"
},
{
"label": "上六",
"text": "不明晦,初登于天,後入于地。"
}
],
"extras": []
},
{
"number": 37,
"name": "家人",
"judgment": "利女貞。",
"lines": [
{
"label": "初九",
"text": "閑有家,悔亡。"
},
{
"label": "六二",
"text": "無攸遂,在中饋,貞吉。"
},
{
"label": "九三",
"text": "家人嗃嗃,悔厲吉;婦子嘻嘻,終吝。"
},
{
"label": "六四",
"text": "富家,大吉。"
},
{
"label": "九五",
"text": "王假有家,勿恤吉。"
},
{
"label": "上九",
"text": "有孚威如,終吉。"
}
],
"extras": []
},
{
"number": 38,
"name": "睽",
"judgment": "小事吉。",
"lines": [
{
"label": "初九",
"text": "悔亡,喪馬勿逐,自復;見惡人無咎。"
},
{
"label": "九二",
"text": "遇主于巷,無咎。"
},
{
"label": "六三",
"text": "見輿曳,其牛掣,其人天且劓,無初有終。"
},
{
"label": "九四",
"text": "睽孤,遇元夫,交孚,厲無咎。"
},
{
"label": "六五",
"text": "悔亡,厥宗噬膚,往何咎。"
},
{
"label": "上九",
"text": "睽孤,見豕負塗,載鬼一車,先張之弧,後說之弧,匪寇婚媾,往遇雨則吉。"
}
],
"extras": []
},
{
"number": 39,
"name": "蹇",
"judgment": "利西南,不利東北;利見大人,貞吉。",
"lines": [
{
"label": "初六",
"text": "往蹇,來譽。"
},
{
"label": "六二",
"text": "王臣蹇蹇,匪躬之故。"
},
{
"label": "九三",
"text": "往蹇來反。"
},
{
"label": "六四",
"text": "往蹇來連。"
},
{
"label": "九五",
"text": "大蹇朋來。"
},
{
"label": "上六",
"text": "往蹇來碩,吉;利見大人。"
}
],
"extras": []
},
{
"number": 40,
"name": "解",
"judgment": "利西南,無所往,其來復吉。有攸往,夙吉。",
"lines": [
{
"label": "初六",
"text": "無咎。"
},
{
"label": "九二",
"text": "田獲三狐,得黃矢,貞吉。"
},
{
"label": "六三",
"text": "負且乘,致寇至,貞吝。"
},
{
"label": "九四",
"text": "解而拇,朋至斯孚。"
},
{
"label": "六五",
"text": "君子維有解,吉;有孚于小人。"
},
{
"label": "上六",
"text": "公用射隼,于高墉之上,獲之,無不利。"
}
],
"extras": []
},
{
"number": 41,
"name": "損",
"judgment": "有孚,元吉,無咎,可貞,利有攸往?曷之用,二簋可用享。",
"lines": [
{
"label": "初九",
"text": "已事遄往,無咎,酌損之。"
},
{
"label": "九二",
"text": "利貞,征凶,弗損益之。"
},
{
"label": "六三",
"text": "三人行,則損一人;一人行,則得其友。"
},
{
"label": "六四",
"text": "損其疾,使遄有喜,無咎。"
},
{
"label": "六五",
"text": "或益之,十朋之龜弗克違,元吉。"
},
{
"label": "上九",
"text": "弗損益之,無咎,貞吉,利有攸往,得臣無家。"
}
],
"extras": []
},
{
"number": 42,
"name": "益",
"judgment": "利有攸往,利涉大川。",
"lines": [
{
"label": "初九",
"text": "利用為大作,元吉,無咎。"
},
{
"label": "六二",
"text": "或益之,十朋之龜弗克違,永貞吉。王用享于帝,吉。"
},
{
"label": "六三",
"text": "益之用凶事,無咎。有孚中行,告公用圭。"
},
{
"label": "六四",
"text": "中行,告公從。利用為依遷國。"
},
{
"label": "九五",
"text": "有孚惠心,勿問元吉。有孚惠我德。"
},
{
"label": "上九",
"text": "莫益之,或擊之,立心勿恆,凶。"
}
],
"extras": []
},
{
"number": 43,
"name": "夬",
"judgment": "揚于王庭,孚號,有厲,告自邑,不利即戎,利有攸往。",
"lines": [
{
"label": "初九",
"text": "壯于前趾,往不勝為吝。"
},
{
"label": "九二",
"text": "惕號,莫夜有戎,勿恤。"
},
{
"label": "九三",
"text": "壯于頄,有凶。君子夬夬,獨行遇雨,若濡有慍,無咎。"
},
{
"label": "九四",
"text": "臀無膚,其行次且。牽羊悔亡,聞言不信。"
},
{
"label": "九五",
"text": "莧陸夬夬,中行無咎。"
},
{
"label": "上六",
"text": "無號,終有凶。"
}
],
"extras": []
},
{
"number": 44,
"name": "姤",
"judgment": "女壯,勿用取女。",
"lines": [
{
"label": "初六",
"text": "繫于金柅,貞吉,有攸往,見凶,羸豕孚蹢躅。"
},
{
"label": "九二",
"text": "包有魚,無咎,不利賓。"
},
{
"label": "九三",
"text": "臀無膚,其行次且,厲,無大咎。"
},
{
"label": "九四",
"text": "包無魚,起凶。"
},
{
"label": "九五",
"text": "以杞包瓜,含章,有隕自天。"
},
{
"label": "上九",
"text": "姤其角,吝,無咎。"
}
],
"extras": []
},
{
"number": 45,
"name": "萃",
"judgment": "亨。王假有廟,利見大人,亨,利貞。用大牲吉,利有攸往。",
"lines": [
{
"label": "初六",
"text": "有孚不終,乃亂乃萃,若號一握為笑,勿恤,往無咎。"
},
{
"label": "六二",
"text": "引吉,無咎,孚乃利用禴。"
},
{
"label": "六三",
"text": "萃如,嗟如,無攸利,往無咎,小吝。"
},
{
"label": "九四",
"text": "大吉,無咎。"
},
{
"label": "九五",
"text": "萃有位,無咎。匪孚,元永貞,悔亡。"
},
{
"label": "上六",
"text": "齎咨涕洟,無咎。"
}
],
"extras": []
},
{
"number": 46,
"name": "升",
"judgment": "元亨,用見大人,勿恤,南征吉。",
"lines": [
{
"label": "初六",
"text": "允升,大吉。"
},
{
"label": "九二",
"text": "孚乃利用禴,無咎。"
},
{
"label": "九三",
"text": "升虛邑。"
},
{
"label": "六四",
"text": "王用亨于岐山,吉無咎。"
},
{
"label": "六五",
"text": "貞吉,升階。"
},
{
"label": "上六",
"text": "冥升,利于不息之貞。"
}
],
"extras": []
},
{
"number": 47,
"name": "困",
"judgment": "亨,貞,大人吉,無咎,有言不信。",
"lines": [
{
"label": "初六",
"text": "臀困于株木,入于幽谷,三歲不覿。"
},
{
"label": "九二",
"text": "困于酒食,朱紱方來,利用亨祀,征凶,無咎。"
},
{
"label": "六三",
"text": "困于石,據于蒺藜,入于其宮,不見其妻,凶。"
},
{
"label": "九四",
"text": "來徐徐,困于金車,吝,有終。"
},
{
"label": "九五",
"text": "劓刖,困于赤紱,乃徐有說,利用祭祀。"
},
{
"label": "上六",
"text": "困于葛藟,于臲卼,曰動悔。有悔,征吉。"
}
],
"extras": []
},
{
"number": 48,
"name": "井",
"judgment": "改邑不改井,無喪無得,往來井井。汔至,亦未繘井,羸其瓶,凶。",
"lines": [
{
"label": "初六",
"text": "井泥不食,舊井無禽。"
},
{
"label": "九二",
"text": "井谷射鮒,甕敝漏。"
},
{
"label": "九三",
"text": "井渫不食,為我民惻,可用汲,王明,並受其福。"
},
{
"label": "六四",
"text": "井甃,無咎。"
},
{
"label": "九五",
"text": "井冽,寒泉食。"
},
{
"label": "上六",
"text": "井收勿幕,有孚無吉。"
}
],
"extras": []
},
{
"number": 49,
"name": "革",
"judgment": "己日乃孚,元亨利貞,悔亡。",
"lines": [
{
"label": "初九",
"text": "鞏用黃牛之革。"
},
{
"label": "六二",
"text": "己日乃革之,征吉,無咎。"
},
{
"label": "九三",
"text": "征凶,貞厲,革言三就,有孚。"
},
{
"label": "九四",
"text": "悔亡,有孚改命,吉。"
},
{
"label": "九五",
"text": "大人虎變,未占有孚。"
},
{
"label": "上六",
"text": "君子豹變,小人革面,征凶,居貞吉。"
}
],
"extras": []
},
{
"number": 50,
"name": "鼎",
"judgment": "元吉,亨。",
"lines": [
{
"label": "初六",
"text": "鼎顛趾,利出否,得妾以其子,無咎。"
},
{
"label": "九二",
"text": "鼎有實,我仇有疾,不我能即,吉。"
},
{
"label": "九三",
"text": "鼎耳革,其行塞,雉膏不食,方雨虧悔,終吉。"
},
{
"label": "九四",
"text": "鼎折足,覆公餗,其形渥,凶。"
},
{
"label": "六五",
"text": "鼎黃耳金鉉,利貞。"
},
{
"label": "上九",
"text": "鼎玉鉉,大吉,無不利。"
}
],
"extras": []
},
{
"number": 51,
"name": "震",
"judgment": "亨。震來虩虩,笑言啞啞。震驚百里,不喪匕鬯。",
"lines": [
{
"label": "初九",
"text": "震來虩虩,後笑言啞啞,吉。"
},
{
"label": "六二",
"text": "震來厲,億喪貝,躋于九陵,勿逐,七日得。"
},
{
"label": "六三",
"text": "震蘇蘇,震行無眚。"
},
{
"label": "九四",
"text": "震遂泥。"
},
{
"label": "六五",
"text": "震往來厲,億無喪,有事。"
},
{
"label": "上六",
"text": "震索索,視矍矍,征凶。震不于其躬,于其鄰,無咎。婚媾有言。"
}
],
"extras": []
},
{
"number": 52,
"name": "艮",
"judgment": "艮其背,不獲其身,行其庭,不見其人,無咎。",
"lines": [
{
"label": "初六",
"text": "艮其趾,無咎,利永貞。"
},
{
"label": "六二",
"text": "艮其腓,不拯其隨,其心不快。"
},
{
"label": "九三",
"text": "艮其限,列其夤,厲薰心。"
},
{
"label": "六四",
"text": "艮其身,無咎。"
},
{
"label": "六五",
"text": "艮其輔,言有序,悔亡。"
},
{
"label": "上九",
"text": "敦艮,吉。"
}
],
"extras": []
},
{
"number": 53,
"name": "漸",
"judgment": "女歸吉,利貞。",
"lines": [
{
"label": "初六",
"text": "鴻漸于干,小子厲,有言,無咎。"
},
{
"label": "六二",
"text": "鴻漸于磐,飲食衎衎,吉。"
},
{
"label": "九三",
"text": "鴻漸于陸,夫征不復,婦孕不育,凶;利御寇。"
},
{
"label": "六四",
"text": "鴻漸于木,或得其桷,無咎。"
},
{
"label": "九五",
"text": "鴻漸于陵,婦三歲不孕,終莫之勝,吉。"
},
{
"label": "上九",
"text": "鴻漸于逵,其羽可用為儀,吉。"
}
],
"extras": []
},
{
"number": 54,
"name": "歸妹",
"judgment": "征凶,無攸利。",
"lines": [
{
"label": "初九",
"text": "歸妹以娣,跛能履,征吉。"
},
{
"label": "九二",
"text": "眇能視,利幽人之貞。"
},
{
"label": "六三",
"text": "歸妹以須,反歸以娣。"
},
{
"label": "九四",
"text": "歸妹愆期,遲歸有時。"
},
{
"label": "六五",
"text": "帝乙歸妹,其君之袂,不如其娣之袂良,月幾望,吉。"
},
{
"label": "上六",
"text": "女承筐無實,士刲羊無血,無攸利。"
}
],
"extras": []
},
{
"number": 55,
"name": "豐",
"judgment": "亨,王假之,勿憂,宜日中。",
"lines": [
{
"label": "初九",
"text": "遇其配主,雖旬無咎,往有尚。"
},
{
"label": "六二",
"text": "豐其蔀,日中見斗,往得疑疾,有孚發若,吉。"
},
{
"label": "九三",
"text": "豐其沛,日中見沫,折其右肱,無咎。"
},
{
"label": "九四",
"text": "豐其蔀,日中見斗,遇其夷主,吉。"
},
{
"label": "六五",
"text": "來章,有慶譽,吉。"
},
{
"label": "上六",
"text": "豐其屋,蔀其家,窺其戶,闃其無人,三歲不覿,凶。"
}
],
"extras": []
},
{
"number": 56,
"name": "旅",
"judgment": "小亨,旅貞吉。",
"lines": [
{
"label": "初六",
"text": "旅瑣瑣,斯其所取災。"
},
{
"label": "六二",
"text": "旅即次,懷其資,得童僕貞。"
},
{
"label": "九三",
"text": "旅焚其次,喪其童僕,貞厲。"
},
{
"label": "九四",
"text": "旅于處,得其資斧,我心不快。"
},
{
"label": "六五",
"text": "射雉一矢亡,終以譽命。"
},
{
"label": "上九",
"text": "鳥焚其巢,旅人先笑後號咷。喪牛于易,凶。"
}
],
"extras": []
},
{
"number": 57,
"name": "巽",
"judgment": "小亨,利攸往,利見大人。",
"lines": [
{
"label": "初六",
"text": "進退,利武人之貞。"
},
{
"label": "九二",
"text": "巽在床下,用史巫紛若,吉無咎。"
},
{
"label": "九三",
"text": "頻巽,吝。"
},
{
"label": "六四",
"text": "悔亡,田獲三品。"
},
{
"label": "九五",
"text": "貞吉悔亡,無不利。無初有終,先庚三日,後庚三日,吉。"
},
{
"label": "上九",
"text": "巽在床下,喪其資斧,貞凶。"
}
],
"extras": []
},
{
"number": 58,
"name": "兌",
"judgment": "亨,利貞。",
"lines": [
{
"label": "初九",
"text": "和兌,吉。"
},
{
"label": "九二",
"text": "孚兌,吉,悔亡。"
},
{
"label": "六三",
"text": "來兌,凶。"
},
{
"label": "九四",
"text": "商兌,未寧,介疾有喜。"
},
{
"label": "九五",
"text": "孚于剝,有厲。"
},
{
"label": "上六",
"text": "引兌。"
}
],
"extras": []
},
{
"number": 59,
"name": "渙",
"judgment": "亨。王假有廟,利涉大川,利貞。",
"lines": [
{
"label": "初六",
"text": "用拯馬壯,吉。"
},
{
"label": "九二",
"text": "渙奔其機,悔亡。"
},
{
"label": "六三",
"text": "渙其躬,無悔。"
},
{
"label": "六四",
"text": "渙其群,元吉。渙有丘,匪夷所思。"
},
{
"label": "九五",
"text": "渙汗其大號,渙王居,無咎。"
},
{
"label": "上九",
"text": "渙其血,去逖出,無咎。"
}
],
"extras": []
},
{
"number": 60,
"name": "節",
"judgment": "亨。苦節不可貞。",
"lines": [
{
"label": "初九",
"text": "不出戶庭,無咎。"
},
{
"label": "九二",
"text": "不出門庭,凶。"
},
{
"label": "六三",
"text": "不節若,則嗟若,無咎。"
},
{
"label": "六四",
"text": "安節,亨。"
},
{
"label": "九五",
"text": "甘節,吉;往有尚。"
},
{
"label": "上六",
"text": "苦節,貞凶,悔亡。"
}
],
"extras": []
},
{
"number": 61,
"name": "中孚",
"judgment": "豚魚,吉,利涉大川,利貞。",
"lines": [
{
"label": "初九",
"text": "虞吉,有他不燕。"
},
{
"label": "九二",
"text": "鳴鶴在陰,其子和之,我有好爵,吾與爾靡之。"
},
{
"label": "六三",
"text": "得敵,或鼓或罷,或泣或歌。"
},
{
"label": "六四",
"text": "月幾望,馬匹亡,無咎。"
},
{
"label": "九五",
"text": "有孚攣如,無咎。"
},
{
"label": "上九",
"text": "翰音登于天,貞凶。"
}
],
"extras": []
},
{
"number": 62,
"name": "小過",
"judgment": "亨,利貞,可小事,不可大事。飛鳥遺之音,不宜上宜下,大吉。",
"lines": [
{
"label": "初六",
"text": "飛鳥以凶。"
},
{
"label": "六二",
"text": "過其祖,遇其妣;不及其君,遇其臣;無咎。"
},
{
"label": "九三",
"text": "弗過防之,從或戕之,凶。"
},
{
"label": "九四",
"text": "無咎,弗過遇之。往厲必戒,勿用永貞。"
},
{
"label": "六五",
"text": "密雲不雨,自我西郊,公弋取彼在穴。"
},
{
"label": "上六",
"text": "弗遇過之,飛鳥離之,凶,是謂災眚。"
}
],
"extras": []
},
{
"number": 63,
"name": "既濟",
"judgment": "亨,小利貞,初吉終亂。",
"lines": [
{
"label": "初九",
"text": "曳其輪,濡其尾,無咎。"
},
{
"label": "六二",
"text": "婦喪其茀,勿逐,七日得。"
},
{
"label": "九三",
"text": "高宗伐鬼方,三年克之,小人勿用。"
},
{
"label": "六四",
"text": "繻有衣袽,終日戒。"
},
{
"label": "九五",
"text": "東鄰殺牛,不如西鄰之禴祭,實受其福。"
},
{
"label": "上六",
"text": "濡其首,厲。"
}
],
"extras": []
},
{
"number": 64,
"name": "未濟",
"judgment": "亨,小狐汔濟,濡其尾,無攸利。",
"lines": [
{
"label": "初六",
"text": "濡其尾,吝。"
},
{
"label": "九二",
"text": "曳其輪,貞吉。"
},
{
"label": "六三",
"text": "未濟,征凶,利涉大川。"
},
{
"label": "九四",
"text": "貞吉,悔亡,震用伐鬼方,三年有賞于大國。"
},
{
"label": "六五",
"text": "貞吉,無悔,君子之光,有孚,吉。"
},
{
"label": "上九",
"text": "有孚于飲酒,無咎,濡其首,有孚失是。"
}
],
"extras": []
}
];
if (typeof window !== "undefined") window.ZHOUYI_BENJING = ZHOUYI_BENJING;
if (typeof module !== "undefined") module.exports = ZHOUYI_BENJING;
FILE:app.js
const TRIGRAMS = {
"111": { name: "乾", symbol: "☰", nature: "天", image: "健", counsel: "主动、开创、守正,不以强势替代判断。" },
"110": { name: "兑", symbol: "☱", nature: "澤", image: "悦", counsel: "沟通、交换、悦纳,但承诺要有边界。" },
"101": { name: "离", symbol: "☲", nature: "火", image: "丽", counsel: "看见事实,辨明依附关系,不被表象带走。" },
"100": { name: "震", symbol: "☳", nature: "雷", image: "动", counsel: "启动、警醒,先稳住第一步。" },
"011": { name: "巽", symbol: "☴", nature: "風", image: "入", counsel: "渐入、顺势,用连续的小动作推进。" },
"010": { name: "坎", symbol: "☵", nature: "水", image: "险", counsel: "面对风险,先建承载与退路。" },
"001": { name: "艮", symbol: "☶", nature: "山", image: "止", counsel: "止步、界限,在停顿中重新定位。" },
"000": { name: "坤", symbol: "☷", nature: "地", image: "顺", counsel: "承接、养成,以耐心和秩序承载变化。" }
};
// Key is lower trigram | upper trigram, because lines are stored from bottom to top.
const HEXAGRAM_LOOKUP = {
"乾|乾": 1, "乾|兑": 43, "乾|离": 14, "乾|震": 34, "乾|巽": 9, "乾|坎": 5, "乾|艮": 26, "乾|坤": 11,
"兑|乾": 10, "兑|兑": 58, "兑|离": 38, "兑|震": 54, "兑|巽": 61, "兑|坎": 60, "兑|艮": 41, "兑|坤": 19,
"离|乾": 13, "离|兑": 49, "离|离": 30, "离|震": 55, "离|巽": 37, "离|坎": 63, "离|艮": 22, "离|坤": 36,
"震|乾": 25, "震|兑": 17, "震|离": 21, "震|震": 51, "震|巽": 42, "震|坎": 3, "震|艮": 27, "震|坤": 24,
"巽|乾": 44, "巽|兑": 28, "巽|离": 50, "巽|震": 32, "巽|巽": 57, "巽|坎": 48, "巽|艮": 18, "巽|坤": 46,
"坎|乾": 6, "坎|兑": 47, "坎|离": 64, "坎|震": 40, "坎|巽": 59, "坎|坎": 29, "坎|艮": 4, "坎|坤": 7,
"艮|乾": 33, "艮|兑": 31, "艮|离": 56, "艮|震": 62, "艮|巽": 53, "艮|坎": 39, "艮|艮": 52, "艮|坤": 15,
"坤|乾": 12, "坤|兑": 45, "坤|离": 35, "坤|震": 16, "坤|巽": 20, "坤|坎": 8, "坤|艮": 23, "坤|坤": 2
};
const LINE_POSITIONS = ["初爻", "二爻", "三爻", "四爻", "五爻", "上爻"];
const JOURNAL_KEY = "zhouyi-benjing-journal-v1";
const LINE_GUIDANCE = [
"事在初起,宜先试探根基,不急于定局。",
"渐入关系或结构,重在取得中位的支撑。",
"内外交界,最容易躁进,宜复核风险。",
"开始外显,适合调整表达、位置与策略。",
"居于核心,重在正当性、责任和判断。",
"一事将极,宜收束、转化,不恋旧势。"
];
const QUESTION_GUIDANCE = {
relationship: "感情与关系之问,重点看互信、位置是否相称,以及是否有可持续的回应。",
work: "事业与项目之问,重点看时机、角色、资源和下一步是否可验证。",
money: "财务之问,重点先分清事实、假设与欲望;重大投入必须保留缓冲和退出条件。",
wellbeing: "身心之问,卦象只能提示节奏和边界;涉及疾病、持续痛苦或风险时,应优先求助专业人士。",
timing: "时机之问,重点看动爻多少、变卦方向,以及当下是否宜动、宜守或宜缓。",
general: "一般问题,先把卦象当成镜子:找出你真正能负责的一步,再观察现实反馈。"
};
const state = {
method: "coin",
currentReading: null,
catalogGrade: "all"
};
const els = {
question: document.querySelector("#question"),
castButton: document.querySelector("#castButton"),
modeButtons: document.querySelectorAll(".mode-button"),
resultLayout: document.querySelector("#resultLayout"),
detailGrid: document.querySelector("#detailGrid"),
primaryHexagram: document.querySelector("#primaryHexagram"),
changedHexagram: document.querySelector("#changedHexagram"),
primaryTitle: document.querySelector("#primaryTitle"),
changedTitle: document.querySelector("#changedTitle"),
primaryTrigrams: document.querySelector("#primaryTrigrams"),
changedTrigrams: document.querySelector("#changedTrigrams"),
changedBlock: document.querySelector("#changedBlock"),
changeArrow: document.querySelector("#changeArrow"),
readingText: document.querySelector("#readingText"),
lineList: document.querySelector("#lineList"),
symbolList: document.querySelector("#symbolList"),
journalList: document.querySelector("#journalList"),
copyButton: document.querySelector("#copyButton"),
clearJournalButton: document.querySelector("#clearJournalButton"),
catalogSearch: document.querySelector("#catalogSearch"),
catalogFilters: document.querySelector("#catalogFilters"),
catalogGrid: document.querySelector("#catalogGrid"),
hexagramSearch: document.querySelector("#hexagramSearch"),
hexagramLibrary: document.querySelector("#hexagramLibrary")
};
function tossLine(method) {
if (method === "yarrow") {
return createLine(weightedPick([
{ value: 6, weight: 1 },
{ value: 7, weight: 5 },
{ value: 8, weight: 7 },
{ value: 9, weight: 3 }
]));
}
const coins = Array.from({ length: 3 }, () => (Math.random() < 0.5 ? 2 : 3));
return createLine(coins.reduce((sum, coin) => sum + coin, 0), coins);
}
function weightedPick(items) {
const total = items.reduce((sum, item) => sum + item.weight, 0);
let cursor = Math.random() * total;
for (const item of items) {
cursor -= item.weight;
if (cursor < 0) return item.value;
}
return items[items.length - 1].value;
}
function createLine(value, coins = []) {
return {
value,
coins,
yang: value === 7 || value === 9,
moving: value === 6 || value === 9,
label: value === 6 ? "老阴" : value === 7 ? "少阳" : value === 8 ? "少阴" : "老阳"
};
}
function castHexagram() {
const lines = Array.from({ length: 6 }, () => tossLine(state.method));
const changedLines = lines.map((line) => ({
...line,
yang: line.moving ? !line.yang : line.yang,
moving: false
}));
return enrichReading({
id: createId(),
createdAt: new Date().toISOString(),
question: els.question.value.trim(),
method: state.method,
lines,
changedLines
});
}
function enrichReading(reading) {
const primary = resolveHexagram(reading.lines);
const changed = resolveHexagram(reading.changedLines);
const moving = reading.lines
.map((line, index) => ({ line, index }))
.filter(({ line }) => line.moving);
return {
...reading,
primary,
changed,
moving,
decision: decideTextSource(primary, changed, moving)
};
}
function createId() {
if (window.crypto?.randomUUID) return window.crypto.randomUUID();
return `reading-Date.now()-Math.random().toString(16).slice(2)`;
}
function resolveHexagram(lines) {
const lowerBits = lines.slice(0, 3).map((line) => (line.yang ? "1" : "0")).join("");
const upperBits = lines.slice(3, 6).map((line) => (line.yang ? "1" : "0")).join("");
const lower = TRIGRAMS[lowerBits];
const upper = TRIGRAMS[upperBits];
const number = HEXAGRAM_LOOKUP[`lower.name|upper.name`];
const benjing = ZHOUYI_BENJING[number - 1];
return {
number,
name: benjing.name,
fullName: fullHexagramName(benjing.name, upper, lower),
judgment: benjing.judgment,
lines: benjing.lines,
extras: benjing.extras,
lower,
upper
};
}
function fullHexagramName(name, upper, lower) {
if (upper.name === lower.name && sameTrigramName(name, upper.name)) return `name為upper.nature`;
return `upper.naturelower.naturename`;
}
function sameTrigramName(sourceName, trigramName) {
const aliases = { 兑: "兌", 离: "離" };
return sourceName === trigramName || sourceName === aliases[trigramName];
}
function decideTextSource(primary, changed, moving) {
const count = moving.length;
if (count === 0) {
return {
rule: "六爻不变:以本卦卦辞为主。",
focus: "本卦卦辞",
entries: [{ title: `primary.name卦辞`, text: primary.judgment, priority: true }]
};
}
if (count === 1) {
const item = moving[0];
return {
rule: "一爻变:以该动爻爻辞为主。",
focus: primary.lines[item.index].label,
entries: [lineEntry(primary, item.index, true)]
};
}
if (count === 2) {
const indexes = moving.map(({ index }) => index).sort((a, b) => a - b);
const upperIndex = indexes[indexes.length - 1];
return {
rule: "二爻变:取两条动爻爻辞,以上爻为主。",
focus: primary.lines[upperIndex].label,
entries: indexes.map((index) => lineEntry(primary, index, index === upperIndex))
};
}
if (count === 3) {
return {
rule: "三爻变:以本卦卦辞与变卦卦辞合看。",
focus: "本卦与变卦卦辞",
entries: [
{ title: `primary.name卦辞`, text: primary.judgment, priority: true },
{ title: `changed.name卦辞`, text: changed.judgment, priority: false }
]
};
}
if (count === 4) {
const staticIndexes = [0, 1, 2, 3, 4, 5].filter((index) => !moving.some((item) => item.index === index));
const lowerIndex = staticIndexes[0];
return {
rule: "四爻变:取两条静爻爻辞,以下爻为主。",
focus: primary.lines[lowerIndex].label,
entries: staticIndexes.map((index) => lineEntry(primary, index, index === lowerIndex))
};
}
if (count === 5) {
const staticIndex = [0, 1, 2, 3, 4, 5].find((index) => !moving.some((item) => item.index === index));
return {
rule: "五爻变:取变卦中唯一静爻所对应的爻辞。",
focus: changed.lines[staticIndex].label,
entries: [lineEntry(changed, staticIndex, true)]
};
}
const special = primary.number === 1 ? primary.extras.find((item) => item.label === "用九")
: primary.number === 2 ? primary.extras.find((item) => item.label === "用六")
: null;
if (special) {
return {
rule: "六爻皆变:乾用用九,坤用用六。",
focus: special.label,
entries: [{ title: special.label, text: special.text, priority: true }]
};
}
return {
rule: "六爻皆变:乾坤之外,以变卦卦辞为主。",
focus: `changed.name卦辞`,
entries: [{ title: `changed.name卦辞`, text: changed.judgment, priority: true }]
};
}
function lineEntry(hexagram, index, priority) {
const source = hexagram.lines[index];
return {
title: `hexagram.namesource.label`,
text: source.text,
priority
};
}
function renderReading(reading) {
state.currentReading = reading;
els.resultLayout.hidden = false;
els.detailGrid.hidden = false;
renderHexagram(els.primaryHexagram, reading.lines);
renderHexagram(els.changedHexagram, reading.changedLines);
const hasMoving = reading.moving.length > 0;
els.changedBlock.style.opacity = hasMoving ? "1" : "0.45";
els.changeArrow.textContent = hasMoving ? "→" : "•";
els.primaryTitle.textContent = `reading.primary.number. reading.primary.fullName`;
els.changedTitle.textContent = hasMoving ? `reading.changed.number. reading.changed.fullName` : "无变卦";
els.primaryTrigrams.textContent = trigramText(reading.primary);
els.changedTrigrams.textContent = hasMoving ? trigramText(reading.changed) : "六爻皆静,重在本卦卦辞。";
els.readingText.innerHTML = buildReadingSections(reading);
els.lineList.innerHTML = buildLineList(reading);
els.symbolList.innerHTML = buildSymbolList(reading);
saveJournal(reading);
renderJournal();
els.resultLayout.scrollIntoView({ behavior: "smooth", block: "start" });
}
function renderHexagram(container, lines) {
container.innerHTML = "";
[...lines].reverse().forEach((line) => {
const div = document.createElement("div");
div.className = `yao "yin" ""`;
div.setAttribute("aria-label", `line.label""`);
if (line.moving) {
const dot = document.createElement("span");
dot.className = "move-dot";
div.appendChild(dot);
}
container.appendChild(div);
});
}
function trigramText(hexagram) {
return `上hexagram.upper.namehexagram.upper.symbolhexagram.upper.nature · 下hexagram.lower.namehexagram.lower.symbolhexagram.lower.nature`;
}
function buildReadingSections(reading) {
const questionType = classifyQuestion(reading.question);
const question = reading.question || "未写下具体问题";
const entries = reading.decision.entries
.map((entry) => `<blockquote class=""""><strong>escapeHtml(entry.title)</strong>escapeHtml(entry.text)</blockquote>`)
.join("");
return `
<section>
<h3>所问</h3>
<p>escapeHtml(question)</p>
</section>
<section>
<h3>卦辞</h3>
<blockquote><strong>escapeHtml(reading.primary.name)卦辞</strong>escapeHtml(reading.primary.judgment)</blockquote>
reading.moving.length ? `<p>变卦为「${escapeHtml(reading.changed.fullName)」,其卦辞为:escapeHtml(reading.changed.judgment)</p>` : ""}
</section>
<section>
<h3>取辞</h3>
<p><span class="rule-badge">reading.moving.length 动爻</span>escapeHtml(reading.decision.rule) 本次重点:escapeHtml(reading.decision.focus)。</p>
<div class="source-stack">entries</div>
</section>
<section>
<h3>解读</h3>
<p>buildInterpretation(reading, questionType)</p>
</section>
<section>
<h3>体系路由</h3>
<p>buildRouteNote(reading, questionType)</p>
</section>
<section>
<h3>行动</h3>
<p>buildActionAdvice(reading, questionType)</p>
</section>
<section>
<h3>追问</h3>
<p>buildReflectionQuestion(reading, questionType)</p>
</section>
`;
}
function buildRouteNote(reading, questionType) {
const enabled = DIVINATION_SYSTEMS.find((item) => item.id === "zhouyi-benjing");
const related = recommendSystems(questionType)
.map((id) => DIVINATION_SYSTEMS.find((item) => item.id === id))
.filter(Boolean);
const names = related.map((item) => `item.name(item.status,item.grade级)`).join(";");
return `本次采用 enabled.name(enabled.grade级,enabled.status)作为主体系,因为它能直接引用本经并按动爻取辞。可参考的旁支体系:names || "暂无"。旁支只作百科线索,不参与本次断语。`;
}
function recommendSystems(questionType) {
const map = {
relationship: ["liuyao", "meihua", "ziwei", "tarot"],
work: ["meihua", "liuyao", "qimen", "bazi"],
money: ["liuyao", "qimen", "bazi"],
wellbeing: ["meihua", "fengshui", "bazi"],
timing: ["qimen", "liuyao", "meihua"],
general: ["meihua", "liuyao", "routing"]
};
return map[questionType] || map.general;
}
function buildInterpretation(reading, questionType) {
const movement = reading.moving.length === 0
? "此卦无动爻,说明问题的关键不在立刻改变,而在看清本卦所呈现的结构。"
: reading.moving.length >= 4
? "动爻很多,表示局面已经接近整体翻转,判断时要少抓单点,多看变卦给出的方向。"
: "有动爻,说明现状中已经出现转折点;爻位提示变化发生的层次。";
const lineLayer = reading.moving.length
? reading.moving.map(({ index }) => `LINE_POSITIONS[index]:LINE_GUIDANCE[index]`).join(" ")
: "六爻皆静,以本卦卦辞为主,不宜把问题解释成马上会变。";
return `movementlineLayerQUESTION_GUIDANCE[questionType] 本系统只以《周易》本经卦辞、爻辞为底,不把结果说成确定命令。`;
}
function buildActionAdvice(reading, questionType) {
const count = reading.moving.length;
const typeAdvice = {
relationship: "先校正关系中的位置与边界,再谈推进;如果对方回应不稳定,不要用催促替代确认。",
work: "把下一步拆成可验证的小行动,先确认角色、资源、时间表,再扩大承诺。",
money: "不要只看收益叙事,先列出最大损失、退出条件和等待成本。",
wellbeing: "先恢复秩序和支持系统;若涉及疾病或持续痛苦,请优先找专业帮助。",
timing: "若动爻少,先抓关键动作;若动爻多,缩短承诺周期,等待新局面落定。",
general: "把卦象落回现实:今天能负责的一步是什么,做完后用什么信号复盘。"
};
const rhythm = count === 0
? "宜守中观察,少做剧烈转向。"
: count <= 2
? "宜抓住一个关键点,小步推进。"
: count === 3
? "宜同时看现状与去向,先做过渡安排。"
: "宜降低赌注,给变化留出缓冲。";
return `rhythmtypeAdvice[questionType]`;
}
function buildReflectionQuestion(reading, questionType) {
const base = {
relationship: "这段关系里,我真正能负责的是表达、边界,还是等待?",
work: "如果只推进一步,哪一步最能验证这件事值得继续?",
money: "我现在看到的是价值、价格,还是被波动放大的欲望与恐惧?",
wellbeing: "我最需要先恢复的是体力、秩序、支持,还是边界?",
timing: "我是在等合适时机,还是在用等待回避行动?",
general: "这件事里,我真正能负责的部分是什么?"
};
return `base[questionType]以「reading.primary.fullName」为镜,再看「reading.changed.fullName」是否指出下一阶段。`;
}
function buildLineList(reading) {
return reading.lines
.map((line, index) => {
const source = reading.primary.lines[index];
const selected = reading.decision.entries.some((entry) => entry.title === `reading.primary.namesource.label`);
const coinText = line.coins.length ? `三钱:line.coins.join(" + ") = line.value` : `蓍草概率数:line.value`;
return `
<div class="line-item "" """>
<strong>source.label · line.label""</strong>
<p>coinText</p>
<p class="source-text">escapeHtml(source.text)</p>
</div>
`;
})
.reverse()
.join("");
}
function buildSymbolList(reading) {
const items = [
{
title: "本经底座",
text: "本页数据由 sources/zhouyi/zhouyi_benjing.txt 生成,仅含六十四卦卦辞、爻辞、用九、用六。"
},
{
title: `上卦 reading.primary.upper.namereading.primary.upper.symbol`,
text: `reading.primary.upper.nature象为reading.primary.upper.image:reading.primary.upper.counsel`
},
{
title: `下卦 reading.primary.lower.namereading.primary.lower.symbol`,
text: `reading.primary.lower.nature象为reading.primary.lower.image:reading.primary.lower.counsel`
},
{
title: "取辞规则",
text: reading.decision.rule
}
];
if (reading.moving.length) {
items.push({
title: `变化 reading.changed.fullName`,
text: `由 reading.primary.fullName 变为 reading.changed.fullName,解释时先按动爻数量取辞,再参考变卦方向。`
});
}
return items
.map(
(item) => `
<div class="symbol-item">
<strong>escapeHtml(item.title)</strong>
<p>escapeHtml(item.text)</p>
</div>
`
)
.join("");
}
function renderCatalog() {
if (!els.catalogGrid) return;
const query = normalize(els.catalogSearch?.value || "");
const systems = DIVINATION_SYSTEMS.filter((item) => {
const gradeOk = state.catalogGrade === "all" || item.grade === state.catalogGrade;
const haystack = normalize([
item.name,
item.family,
item.grade,
item.status,
item.basis,
item.capability,
item.guardrail,
item.bestFor.join(" "),
item.inputs.join(" ")
].join(" "));
return gradeOk && (!query || haystack.includes(query));
});
els.catalogGrid.innerHTML = systems.map(renderSystemCard).join("") ||
`<div class="system-card"><p>没有匹配的体系。</p></div>`;
}
function renderSystemCard(item) {
return `
<article class="system-card">
<header>
<div>
<h3>escapeHtml(item.name)</h3>
<p>escapeHtml(item.family) · escapeHtml(item.basis)</p>
</div>
<span class="grade-badge grade-item.grade.toLowerCase()">item.grade</span>
</header>
<span class="status-badge">escapeHtml(item.status)</span>
<p>escapeHtml(item.capability)</p>
<div class="tag-list">item.bestFor.slice(0, 4).map((tag) => `<span>${escapeHtml(tag)</span>`).join("")}</div>
<p><strong>资料:</strong>escapeHtml(item.inputs.join("、"))</p>
<p><strong>边界:</strong>escapeHtml(item.guardrail)</p>
</article>
`;
}
function renderHexagramLibrary() {
if (!els.hexagramLibrary) return;
const query = normalize(els.hexagramSearch?.value || "");
const items = ZHOUYI_BENJING.filter((hex) => {
const haystack = normalize([
hex.number,
hex.name,
hex.judgment,
hex.lines.map((line) => `line.labelline.text`).join(" "),
hex.extras.map((line) => `line.labelline.text`).join(" ")
].join(" "));
return !query || haystack.includes(query);
});
els.hexagramLibrary.innerHTML = items.map(renderHexCard).join("") ||
`<div class="hex-card"><p>没有匹配的卦。</p></div>`;
}
function renderHexCard(hex) {
const firstMovingLine = hex.lines.find((line) => /吉|凶|悔|咎|厲|利/.test(line.text)) || hex.lines[0];
return `
<article class="hex-card">
<header>
<h3>hex.number. escapeHtml(hex.name)</h3>
<span class="grade-badge grade-s">本经</span>
</header>
<p class="source-line">escapeHtml(hex.name):escapeHtml(hex.judgment)</p>
<p>escapeHtml(firstMovingLine.label):escapeHtml(firstMovingLine.text)</p>
</article>
`;
}
function normalize(value) {
return String(value).toLowerCase().replace(/\s+/g, "");
}
function classifyQuestion(question) {
const q = question.toLowerCase();
if (/感情|关系|恋|婚|伴侣|喜欢|复合|分手/.test(q)) return "relationship";
if (/工作|事业|合作|项目|公司|创业|offer|职位|老板|面试|跳槽/.test(q)) return "work";
if (/钱|投资|买|卖|收入|财|价格|交易|理财|资产/.test(q)) return "money";
if (/健康|身体|病|睡眠|焦虑|压力|治疗|医院/.test(q)) return "wellbeing";
if (/何时|什么时候|时机|现在适合|是否适合|能不能|该不该/.test(q)) return "timing";
return "general";
}
function methodText(method) {
if (method === "yarrow") return "蓍草概率";
return "三枚铜钱";
}
function saveJournal(reading) {
const journal = getJournal().filter((item) => item.id !== reading.id);
journal.unshift({
id: reading.id,
createdAt: reading.createdAt,
question: reading.question,
method: reading.method,
lines: reading.lines,
changedLines: reading.changedLines
});
localStorage.setItem(JOURNAL_KEY, JSON.stringify(journal.slice(0, 8)));
}
function getJournal() {
try {
return JSON.parse(localStorage.getItem(JOURNAL_KEY) || "[]");
} catch {
return [];
}
}
function renderJournal() {
const journal = getJournal();
if (!journal.length) {
els.journalList.innerHTML = `<div class="journal-item"><p>暂无记录</p></div>`;
return;
}
els.journalList.innerHTML = journal
.map((item) => {
const reading = enrichReading(item);
const date = new Intl.DateTimeFormat("zh-CN", {
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit"
}).format(new Date(item.createdAt));
return `
<button class="journal-item" type="button" data-id="item.id">
<strong>reading.primary.number. escapeHtml(reading.primary.fullName)</strong>
<p>date · methodText(item.method) · escapeHtml(item.question || "未写问题")</p>
</button>
`;
})
.join("");
}
function escapeHtml(value = "") {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function plainTextReading() {
if (!state.currentReading) return "";
const container = document.createElement("div");
container.innerHTML = buildReadingSections(state.currentReading);
return container.innerText.trim();
}
function bootstrap() {
if (!Array.isArray(window.ZHOUYI_BENJING) || window.ZHOUYI_BENJING.length !== 64) {
els.readingText.innerHTML = `<section><h3>数据错误</h3><p>未能加载完整《周易》本经数据。</p></section>`;
return;
}
if (!Array.isArray(window.DIVINATION_SYSTEMS) || window.DIVINATION_SYSTEMS.length < 8) {
els.readingText.innerHTML = `<section><h3>数据错误</h3><p>未能加载完整术数百科数据。</p></section>`;
return;
}
els.modeButtons.forEach((button) => {
button.addEventListener("click", () => {
state.method = button.dataset.method;
els.modeButtons.forEach((item) => item.classList.toggle("active", item === button));
});
});
els.castButton.addEventListener("click", () => {
renderReading(castHexagram());
});
els.copyButton.addEventListener("click", async () => {
const text = plainTextReading();
if (!text) return;
try {
await navigator.clipboard.writeText(text);
els.copyButton.textContent = "✓";
} catch {
els.copyButton.textContent = "!";
}
window.setTimeout(() => {
els.copyButton.textContent = "⧉";
}, 1200);
});
els.clearJournalButton.addEventListener("click", () => {
localStorage.removeItem(JOURNAL_KEY);
renderJournal();
});
els.catalogSearch?.addEventListener("input", renderCatalog);
els.hexagramSearch?.addEventListener("input", renderHexagramLibrary);
els.catalogFilters?.addEventListener("click", (event) => {
const button = event.target.closest("[data-grade]");
if (!button) return;
state.catalogGrade = button.dataset.grade;
els.catalogFilters.querySelectorAll(".filter-button").forEach((item) => {
item.classList.toggle("active", item === button);
});
renderCatalog();
});
els.journalList.addEventListener("click", (event) => {
const button = event.target.closest("[data-id]");
if (!button) return;
const record = getJournal().find((item) => item.id === button.dataset.id);
if (record) renderReading(enrichReading(record));
});
renderJournal();
renderCatalog();
renderHexagramLibrary();
}
bootstrap();
Point-in-time Buffett-style company analysis for stocks, Berkshire case studies, and BUY/PASS verdicts. Use when the user wants a Buffett/Graham underwriting...
---
name: buffett-oracle
description: Point-in-time Buffett-style company analysis for stocks, Berkshire case studies, and BUY/PASS verdicts. Use when the user wants a Buffett/Graham underwriting memo, moat test, control-group comparison, or benchmark backtest grounded in cached company cards and strict decision-date discipline.
homepage: https://github.com/yixiao1032-publish/buffet-oracle
metadata:
clawdbot:
emoji: "🔮"
requires:
env: []
files:
- "SKILL.md"
- "buffett-oracle.md"
- "buffett_brain.md"
- "backtest_results.md"
- "coverage_scope.md"
- "analysis_index.json"
- "universe_expansion.md"
- "universe_expansion_index.json"
- "company_cards/"
---
Buffett Oracle is a research skill for deciding whether a company deserves a `BUY` or `PASS` under a strict Buffett + Graham underwriting framework.
Use this skill when the user wants:
- A Buffett-style memo on a public company, bank, utility, or crypto protocol
- A point-in-time re-underwriting of a Berkshire decision
- A moat explanation tied to hard numbers, not vibes
- A clean `BUY` / `PASS` verdict instead of a hedged summary
- A comparison against prior benchmark cases or same-era control groups
## Read Order
Read only what you need:
- `buffett-oracle.md`
Use for the Buffett Oracle persona, output structure, and portable prompt wording.
- `buffett_brain.md`
Use for the Graham operating layer, 7 hard gates, named exemptions, and moat logic.
- `coverage_scope.md`
Read before making any claim about benchmark completion or historical coverage.
- `company_cards/`
Check first. If a matching card already exists, reuse it and do not re-fetch the filing.
- `backtest_results.md` and `analysis_index.json`
Use for benchmark precedents and indexed case linkage.
- `universe_expansion.md` and `universe_expansion_index.json`
Use for non-benchmark precedents without polluting the benchmark hit-rate.
- `methodology_audit.md`
Read when the user asks how reliable the framework is, or whether the score implies predictive power.
- `gate_review.md`
Read when the user asks why certain high-quality assets still fail the hard gates.
## Non-Negotiables
- Use only information that was public on or before the decision date.
- Never describe the 29 benchmark rows as Buffett or Berkshire's full investment universe.
- Never re-fetch a company that already has a cached card in `company_cards/`.
- If any hard gate fails, default to `PASS` unless a named exemption clearly applies.
- Every `BUY` needs two same-era control groups.
- Lock the `BUY` / `PASS` conclusion before revealing what Buffett actually did.
- Treat this as a research framework, not personalized investment advice.
## Workflow
1. Classify the request as `INVESTMENT`, `SPECULATION`, or `TOO_HARD`.
If it is `SPECULATION` or `TOO_HARD`, explain why and stop.
2. Check `company_cards/` for a cached `<TICKER>_<YEAR>.json`.
Reuse the card if present. Only fetch a new filing when no card exists.
3. Run the 7 hard gates from `buffett_brain.md`.
Any failed gate means `PASS`, unless one of the named exemptions below is explicitly justified.
4. Apply required overlays when triggered.
If `g2` fails but moat still matters, add an owner-earnings note.
If `g6` fails but moat still matters, add a quality-multiple note.
For new live or expansion memos, include `management_veto` as `clear`, `watch`, or `fail`.
5. Write the moat paragraph.
If you cannot explain why competitors cannot replicate the business in 10 years, the answer is `PASS`.
6. For every `BUY`, include the safety-margin math.
State owner's earnings or normalized earnings, value range, required return, and implied discount.
7. Pick two same-era control-group companies that Buffett did not buy.
Run the same gate logic on them. If they also pass, explain the differentiator.
8. Lock the verdict before reveal.
Only after the verdict should you reveal Buffett's action, later outcome, and whether the framework agreed.
9. If you are updating this repository, save the card, append the memo to the correct markdown archive, and update the matching index JSON.
## Named Exemptions
- `CRISIS_PREFERRED`
For Goldman 2008 / BAC 2011 / GE 2008 style preferred-plus-warrant rescue structures.
- `INFRA_EXEMPTION`
For rail and utility monopolies when monopoly status is clear and `EV/EBITDA < 15x`.
- `GROWTH_EXCEPTION`
For high-ROIC compounders where weak raw FCF mostly reflects value-creating expansion rather than bad economics.
If you invoke an exemption, say so explicitly and defend it.
## Output Contract
Use this summary block in the final answer:
```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CLASSIFICATION: [INVESTMENT / SPECULATION / TOO_HARD]
VERDICT: [BUY / PASS]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Hard Gates: [all passed / failed gates / exemption applied]
Named Exemption: [CRISIS_PREFERRED / INFRA_EXEMPTION / GROWTH_EXCEPTION / none]
Moat Type: [brand / network / switching cost / cost advantage / none]
Safety Margin: [owner's earnings, value range, required return, implied discount]
Key Conviction: [one sentence]
Key Risk: [one sentence]
Control Group: [Company A | Company B]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
Then reveal:
- what Buffett or Berkshire actually did
- what happened afterward
- whether the framework and Buffett agreed
## Data Guidance
- For US equities, prefer SEC EDGAR press-release or annual-report pages before full 10-K pulls.
- For non-US companies, use official annual reports or equivalent filings.
- For crypto or Web3, use on-chain and protocol-source documents, but keep the same anti-speculation bar.
- Post-decision facts belong only in the reveal section, never in the underwriting logic.
## Scope Reminder
The audited benchmark is a curated 29-case set. It is evidence of archive coverage, not a promise of forward hit rate and not the full Berkshire history.
FILE:universe_expansion.md
# Buffett Oracle — Universe Expansion
*Separate from the 29-case benchmark set*
*Analysis framework: buffett_brain.md v1.2*
*Last updated: 2026-03-26*
---
## Scope
- This file tracks **additional Buffett/Berkshire cases beyond the benchmark 29**
- These rows are audited with the same point-in-time discipline
- They do **not** change the benchmark methodology stats in `backtest_results.md`
---
## Summary Table
| # | 标的 | 决策年份 | 框架结论 | 巴菲特/伯克希尔操作 | 实际结果 | 判定 |
|---|---|---|---|---|---|---|
| 1 | PetroChina | 2004 | 不投 | 持有约$4.88亿仓位 | 2007年巨额盈利退出 | ❌ |
| 2 | ConocoPhillips | 2008 | 不投 | 买入约$70亿 | 高油价附近重仓,后认错 | ⭐ |
| 3 | Lubrizol | 2011 | 买入 | $135/股全收购 | 成为稳健的私有化资产 | ✅ |
| 4 | M&T Bank | 2000 | 买入 | 持有并长期增配 | 长期优质区域银行复利 | ✅ |
| 5 | Johnson & Johnson | 2007 | 买入 | 建立约$39亿仓位 | 防御型好结果,但非核心永久持仓 | ✅ |
| 6 | Anheuser-Busch | 2005 | 不投 | 建立约$21亿仓位 | 2008年被InBev以$70/股收购 | ❌ |
| 7 | Wal-Mart Stores | 2005 | 不投 | 建立约$9.44亿仓位 | 好公司,但不是Berkshire式大赢 | ❌ |
| 8 | U.S. Bancorp | 2006 | 买入 | 持有约$9.69亿仓位 | 长期高质量银行持仓 | ✅ |
| 9 | Moody's Corporation | 2001 | 不投 | 持有约$4.99亿仓位 | 成为长期大牛股 | ❌ |
| 10 | H&R Block | 2002 | 不投 | 持有约$2.55亿仓位 | 有所盈利,但不是经典复利大牛 | ⭐ |
| 11 | Costco | 2000 | 不投 | 建立小仓位并后来长期持有 | 公司成为顶级复利股 | ❌ |
| 12 | Disney | 2000 | 不投 | 持有约$0.96亿仓位 | 好公司,但买点并不出色 | ⭐ |
| 13 | DaVita | 2012 | 不投 | 披露持有10.8%仓位 | 后来成伯克希尔大型医疗持仓 | ❌ |
| 14 | Nucor | 2000 | 不投 | 持有约$0.63亿仓位 | 优质钢企,但不是定义性长久大赢 | ⭐ |
| 15 | Merck & Co. | 2020 | 不投 | 建立约$18.6亿仓位 | 很快退出,未成核心长期仓位 | ⭐ |
| 16 | AbbVie | 2020 | 不投 | 建立约$18.6亿仓位 | 赚钱但快速缩仓并退出 | ⭐ |
| 17 | Bristol-Myers Squibb | 2020 | 不投 | 建立约$18.1亿仓位 | 赚钱但未成核心长期仓位 | ⭐ |
| 18 | Pfizer | 2020 | 不投 | 建立约$1.36亿小仓位 | 很快退出,未成核心持仓 | ⭐ |
| 19 | Barrick Gold | 2020 | 不投 | 建立约$3.37亿仓位 | 一个季度后已退出 | ⭐ |
| 20 | Amazon.com | 2020 | 不投 | 持有约$13.7亿小仓位 | 继续持有但始终很小 | ⭐ |
| 21 | Biogen | 2020 | 不投 | 建立约$1.57亿仓位 | 很快退出,未成核心持仓 | ⭐ |
| 22 | Charter Communications | 2020 | 不投 | 持有约$34.5亿仓位 | 持有但到2022年结果并不漂亮 | ⭐ |
| 23 | Kroger | 2020 | 不投 | 先小仓后大幅加仓 | 防御型成功,但不是典型Buffett tollbooth | ⭐ |
| 24 | Marsh & McLennan | 2020 | 不投 | 建立约$4.99亿仓位 | 很快缩到极小仓位 | ⭐ |
| 25 | Mastercard | 2020 | 不投 | 持有约$16.3亿仓位 | 长期保留为支付网络核心资产 | ❌ |
| 26 | Mondelez International | 2020 | 不投 | 持有极小仓位 | 持续保留,但始终不是核心 | ⭐ |
| 27 | Procter & Gamble | 2020 | 不投 | 持有极小仓位 | 持续保留的 legacy stake | ⭐ |
| 28 | RH | 2020 | 不投 | 持有约$3.52亿仓位 | 后续继续加仓,框架错失 | ❌ |
| 29 | Verizon Communications | 2020 | 不投 | 建立约$86.2亿大仓位 | 2022年前全部退出 | ⭐ |
---
## Detailed Cases
### #1 PetroChina (2004) ❌
**公开判断时点**:2004年 | **数据源**:PetroChina FY2003 Form 20-F + Berkshire 2003 annual report + 2004 AGM Q&A
**为什么当前框架会给 PASS**:
- 2001-2003 正常化 ROE 大约在 `17%-18%`,很强
- 估值也极便宜,按 Berkshire 当时持仓成本反推,earnings yield 远高于 `6%`
- 但资本开支很重,按保守口径算 `FCF / NI` 只有约 `0.70x`
- 这会触发硬 gate ②,即使估值和资源成本都明显占优
**结论**:不投
**为什么会错**:
- Buffett 下注的不是“完美现金流机器”,而是极端便宜的大型低成本油气资产
- 这说明当前框架对资本密集型资源股有意偏保守,会错过一部分明显便宜但不够“Buffett-clean”的机会
**实际结果**:Berkshire 以约 `$4.88亿` 成本建立仓位,后来在 2007 年以约 `$40亿` 级别价值退出,属于巨大成功。
---
### #2 ConocoPhillips (2008) ⭐
**公开判断时点**:2008年 | **数据源**:ConocoPhillips FY2007 10-K + Berkshire 2008 annual report + Buffett 2015 AGM retrospective comments
**框架为什么给 PASS**:
- 2005-2007 表面盈利非常强,ROE 并不差
- 但 `FCF / NI` 只有约 `0.66x`
- 更关键的是护城河测试不过:它仍是商品型油气公司,回报高度受油价和周期驱动
- 在高油价环境里,便宜的会计利润不等于好生意,更不等于可长期复利的生意
**结论**:不投
**实际结果**:Buffett 后来承认买在了接近高油价的错误时点,虽然最终没有灾难性全损,但这不是 Berkshire 的高质量胜利案例。
---
### #3 Lubrizol (2011) ✅
**公开判断时点**:2011年 | **数据源**:Lubrizol FY2010 10-K + Berkshire 2011 annual report
**框架为什么给 BUY**:
- 2008-2010 正常化 ROE 大约 `20%`
- `FCF / NI` 约 `1.0x`
- 净负债 / EBITDA 低于 `1x`
- 收入和利润在危机后恢复,并没有出现结构性坏掉
- 最关键的是 gate ⑦:添加剂和特种化学品需要 OEM 认证、配方验证和客户切换成本,这不是随便复制的工业品
**结论**:买入
**实际结果**:Berkshire 以每股 `$135` 全现金收购。它没有成为 headline 巨星,但符合“高质量工业资产长期留在体系内”的模式。
---
### #4 M&T Bank (2000) ✅
**公开判断时点**:2000年 | **数据源**:M&T Bank FY2000 10-K + Berkshire 2000 annual report + 2000 AGM Q&A
**框架为什么给 BUY**:
- 银行业不看传统 FCF,而先看资本和文化;M&T 在 2000 年是明确“well capitalized”
- 2000 年报显示,核心银行 `Tier 1` 资本比率高于 `10%`
- Buffett 公开强调的是同一件事:Bob Wilmers 的 owner-operator 文化让他“睡得很舒服”
- 这不是靠交易赚钱的银行,而是靠存款、信贷纪律和长期客户关系稳步赚钱的区域银行
**结论**:买入
**实际结果**:M&T 成为 Berkshire 长期持有的区域银行之一,之后多年持续复利,属于典型“文化优于规模”的银行案例。
---
### #5 Johnson & Johnson (2007) ✅
**公开判断时点**:2007年 | **数据源**:Johnson & Johnson FY2006 annual report + Berkshire 2007 annual report
**框架为什么给 BUY**:
- 2004-2006 平均 ROE 接近 `28%`
- `FCF / NI` 超过 `1.0x`
- 净负债极低,资产负债表非常稳
- 收入、现金流、资本效率都像 textbook defensive compounder
- 护城河来自品牌、分销、医疗器械与药品组合,以及全球化规模
**结论**:买入
**实际结果**:这不是 Coca-Cola 级别的大赢,但它符合 Buffett 式防御型优秀公司的标准;后续 Berkshire 虽然没有永久持有,underwriting 逻辑本身是成立的。
---
### #6 Anheuser-Busch (2005) ❌
**公开判断时点**:2005年 | **数据源**:Anheuser-Busch FY2005 annual report + Berkshire 2005 annual report + 2005 AGM Q&A
**框架为什么给 PASS**:
- 品牌极强,现金流不错,ROE 也很高
- 但按当时价格算,earnings yield 大约只有 `4%-5%`
- Buffett 自己在 2005 年也明确说了:这是强业务,但收入增长不会特别大
- 当前框架会把它归类为“好公司,但价钱不够便宜”
**结论**:不投
**为什么会错**:
- 2008 年 InBev 以 `$70/股` 全现金收购,Berkshire 得到了可观回报
- 这说明框架对“优秀消费品牌 + 战略买家愿意付更高价格”的情形仍然偏保守
---
### #7 Wal-Mart Stores (2005) ❌
**公开判断时点**:2005年 | **数据源**:Wal-Mart FY2005 annual report / 10-K + Berkshire 2005 annual report
**为什么当前框架会给 PASS**:
- 2004-2006 平均 ROE 约 `22%`,护城河也几乎毫无疑问
- 但按公开现金流口径,`FCF / NI` 只有约 `0.27x`
- Buffett 自己在 2005 年报里也说得很直白:这些强公司“并没有在 bargain prices 上交易”
- 对 Oracle 来说,这就会变成“好公司,但当时不是好 enough 的自由现金流定价”
**结论**:不投
**为什么会错**:
- Wal-Mart 后来当然没有成为 Berkshire 级别的传奇大赢,但它仍然是高质量零售复利资产
- 这说明当前 gate ② 对高质量、仍在大规模扩张期的零售龙头过于严格,容易把真实的 reinvestment compounder 错杀成 cash conversion 不佳
**实际结果**:Berkshire 在 2005 年建立仓位,但始终没有把它升级为最核心持仓;多年后退出,结果整体是正回报但不属于经典 home run。
---
### #8 U.S. Bancorp (2006) ✅
**公开判断时点**:2006年 | **数据源**:U.S. Bancorp FY2006 10-K + Berkshire 2006 annual report
**框架为什么给 BUY**:
- 2004-2006 平均 ROE 约 `22.5%`
- 银行业按资本规则看,`Tier 1` 资本比率 `8.8%`,明显高于框架红线
- 2006 年末按市值估算,earnings yield 约 `7.4%`
- 更关键的是 gate ⑦:这是一家 deposit franchise、payments franchise、风险文化都很干净的银行,不靠激进表外扩张来制造表面高 ROE
**结论**:买入
**实际结果**:U.S. Bancorp 长期是 Berkshire 组合里更高质量的银行持仓之一,虽然之后伴随整体银行权重下降而退出,但 underwriting 逻辑本身成立。
---
### #9 Moody's Corporation (2001) ❌
**公开判断时点**:2001年 | **数据源**:Moody's FY2001 10-K + Berkshire 2001 annual report
**为什么当前框架会给 PASS**:
- 业务质量极强:收入从 `1999` 年的 `$564.2M` 增到 `2001` 年的 `$796.7M`
- 现金流质量也漂亮:`FCF / NI` 约 `1.37x`
- 净负债 / EBITDA 只有约 `0.33x`
- 真正卡住它的是估值:按 Berkshire 年报披露的持仓市值反推,2001 年底 earnings yield 只有约 `3%`
- 也就是说,Oracle 会承认这是一个伟大生意,但会把它归类为“价格不够便宜”
**结论**:不投
**为什么会错**:
- Moody's 后来成了典型的高质量、轻资产、强监管嵌入的信息服务复利股
- 这说明当前 gate ⑥ 对这类“系统性嵌入资本市场基础设施”的垄断资产仍然太粗糙,容易因为低 earnings yield 而错杀真正值得长期持有的资产
**实际结果**:Berkshire 在 2001 年末持有约 `2400万股`、成本约 `$4.99亿`,后续多年享受了明显超额的复利结果。
---
### #10 H&R Block (2002) ⭐
**公开判断时点**:2002年 | **数据源**:H&R Block FY2002 annual report / EX-13 + Berkshire 2002 annual report
**为什么当前框架会给 PASS**:
- 业务并不差:2000-2002 平均 ROE 约 `32%`
- 现金流质量也很好:`net operating free cash flow / net income` 约 `1.39x`
- 杠杆并不危险:净债务 / EBITDA 大约 `0.6x`
- 真正卡住它的是估值:按 2002 年报可见市值和债务口径,earnings yield 约 `5%`
- 也就是说,Oracle 会承认 H&R Block 是一门好生意,但不会把它当作“足够便宜、足够伟大”的 Buffett 级出手点
**结论**:不投
**为什么框架可能更合理**:
- H&R Block 后来并没有变成 Berkshire 最经典的长期大赢之一
- 它是一门稳定而赚钱的服务生意,但 franchise 深度和长期上限都不如 Coca-Cola、Moody's 或 American Express 这种真正的 top-tier compounder
- 这说明 `g6` 不只是“会错杀好公司”,它有时也在帮助我们区分“好公司”和“值得 Buffett 式重仓长拿的公司”
**实际结果**:Berkshire 在 2002 年末持有约 `1600万股`、成本约 `$2.55亿`。这是一笔赚钱但并不传奇的持仓,更像一个 decent outcome,而不是一个 defining winner。
### #11 Costco (2000) ❌
**公开判断时点**:2000年 | **数据源**:Costco FY2001 annual report / 10-K(使用当时已公开的1999财务数据)、Berkshire 1999-12-31 与 2000-03-31 13F-HR/A、2000 AGM Q&A
**为什么当前框架会给 PASS**:
- 1997-1999 平均 ROE 约 `13.1%`,护城河也很清楚
- 真正卡住它的是 `g2` 和 `g6`
- 按 1999 财务口径,`FCF / NI` 只有约 `0.39x`
- 按 Berkshire 2000 年一季度披露持仓所对应的市场价格估算,earnings yield 只有约 `1.7%`
- Oracle 会因此把 Costco 归类为“伟大生意,但太贵,而且自由现金流转换率看起来不够好”
**结论**:不投
**为什么会错**:
- Costco 后来证明自己是极少数真正把低毛利、会员制、极致周转和组织文化结合成深护城河的全球零售复利股
- 当前框架在这里误把 growth capex 当成坏现金流,也误把高质量长期复利的 premium multiple 当成单纯高估
- 这是 `g2 + g6` 组合误伤顶级 compounder 的典型案例
**实际结果**:Berkshire 披露的仓位很小,但 Costco 这门生意后来长期复利非常强,成为零售史上最优秀的公开公司之一。
### #12 Disney (2000) ⭐
**公开判断时点**:2000年 | **数据源**:Disney FY1999 10-K + Berkshire 2000-03-31 13F-HR/A
**框架为什么给 PASS**:
- Disney 的资产当然很强:IP、乐园、媒体网络、品牌授权都是真实护城河
- 但 1997-1999 平均 ROE 只有约 `9%`
- 营业利润率连续两年下滑
- 更关键的是估值:按 1999 年底市值和债务口径,earnings yield 只有约 `2%`
- 也就是说,这不是“差公司”,而是“好资产已经被高价资本化”的例子
**结论**:不投
**为什么框架更合理**:
- Disney 后来当然仍然是伟大的文化公司,但从 2000 年这个买点看,并没有给 Berkshire 最好的那类早期高确定性高回报结果
- 当时的媒体巨头估值里,已经透支了很多未来成功
- 这类案例提醒我们:有 moat 不等于有 margin of safety
**实际结果**:Berkshire 在 2000 年一季度披露约 `233万股`、市值约 `$0.96亿` 的 Disney 持仓,但这并没有演变成 Berkshire 最核心、最成功的公开股案例。
---
### #13 DaVita (2012) ❌
**公开判断时点**:2012年 | **数据源**:DaVita FY2011 10-K + Berkshire/DaVita Schedule 13G
**为什么当前框架会给 PASS**:
- 2009-2011 平均 ROE 约 `20.9%`
- `FCF / NI` 约 `1.63x`
- 净负债 / EBITDA 约 `2.9x`
- 收入从 `2009` 年的 `$6.10B` 增到 `2011` 年的 `$6.98B`
- 真正卡住它的是估值:按 2012 年初可见市值和 2011 年底债务口径估算,earnings yield 只有约 `4.1%`
- 此外,2011 年报里仍然披露了多项联邦调查与传票事项,这会让 Oracle 对低安全边际的医疗服务股更保守
**结论**:不投
**为什么会错**:
- Berkshire 实际看到的是一个高频刚需、局部密度很强、只有少数全国性玩家能规模化运营的慢变量医疗服务生意
- DaVita 后来依靠稳定需求、网络密度和持续回购,成为 Berkshire 的重要长期医疗持仓
- 这说明当前 gate ⑥ 不只会错杀品牌和信息垄断,也会错杀一部分“监管重但需求极稳”的服务型 oligopoly
**实际结果**:Berkshire 在 `2012-09-21` 已披露持有 `10,197,569` 股、占比 `10.8%`。此后随着持股增加和公司回购,DaVita 成为 Berkshire 更重要的长期权益仓位之一。
---
### #14 Nucor (2000) ⭐
**公开判断时点**:2000年 | **数据源**:Nucor FY1999 10-K 完整提交 + Berkshire 2000-03-31 13F-HR/A
**为什么当前框架会给 PASS**:
- 1997-1999 平均 ROE 约 `13.1%`
- `FCF / NI` 约 `0.94x`
- 资产负债表反而很强,1999 年末是净现金状态
- 真正卡住它的是 `g5 + g6`
- 毛利率从 `1997` 年约 `14.5%` 连续降到 `1999` 年约 `13.2%`
- 按 Berkshire 披露持仓所对应的市场价格估算,earnings yield 只有约 `5.9%`,略低于框架红线
**结论**:不投
**为什么框架可能更合理**:
- Nucor 确实是美国钢铁业里最优秀的经营者之一,但优秀不等于能摆脱钢铁本身的周期与商品属性
- 这更像“行业里最好的周期股”,而不是“可以十年高确定性复利的 Buffett 式核心 franchise”
- Berkshire 当时的仓位也很小,后续并没有把它发展成定义性的长期重仓
**实际结果**:Berkshire 在 `2000-03-31` 披露持有 `1,267,900` 股 Nucor、价值约 `$63.4M`。Nucor 之后仍然证明自己是行业里的优等生,但这笔投资没有演变成 Berkshire 最经典的长期大赢之一。
---
### #15 Merck & Co. (2020) ⭐
**公开判断时点**:2020年 | **数据源**:Merck FY2019 10-K + Merck Q3 2020 10-Q + Berkshire 2020-09-30 / 2021-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `22.6%`
- 毛利率从 `2017` 年约 `67.8%` 升到 `2019` 年约 `69.9%`
- 负债并不重,按 `2020Q3` 净负债 / `2019` EBITDA 代理口径估算约 `1.3x`
- 真正卡住它的是 `g2 + g6 + g7`
- 按 `2020Q3` 的 trailing 12 months 口径,`FCF / NI` 只有约 `0.58x`
- 按 Berkshire 披露仓位反推的市场价格和 `2020Q3` 资产负债表估算,earnings yield 只有约 `5.0%`
- 更重要的是,虽然 Keytruda 极其优秀,但整个公司仍然建立在持续研发补位和专利生命周期管理之上,不像 Coca-Cola、Moody's 或 American Express 那样有一眼能讲清的十年结构性护城河
**结论**:不投
**为什么框架可能更合理**:
- Berkshire 在 2020 年确实买了几家大型药企,但 Merck 并没有演变成长期核心仓位
- 这类公司往往“生意不错”,却未必适合按 Buffett Oracle 的高确定性长期复利标准去重仓
- 这个案例支持当前框架对“大型专利药组合体”保持保守:不是烂生意,只是不够像 decade-long tollbooth
**实际结果**:Berkshire 在 `2020-09-30` 披露持有 `22,403,102` 股 Merck、价值约 `$1.86B`,但到 `2021-12-31` 的 13F 已经不再出现这笔持仓。Merck 仍然是强公司,但这笔投资没有发展成 Berkshire 的永久核心持仓。
---
### #16 AbbVie (2020) ⭐
**公开判断时点**:2020年 | **数据源**:AbbVie FY2019 10-K + AbbVie Q3 2020 10-Q + Berkshire 2020-09-30 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 经营回报并不差,按 `ROIC` 代理口径平均约 `17.8%`
- `2020Q3` 的 trailing 12 months `FCF / NI` 约 `2.08x`,现金流表面上很强
- 真正卡住它的是 `g3 + g6 + g7`
- Allergan 并购后,按 `2020Q3` 净债务 / `TTM EBITDA` 代理口径估算约 `4.5x`
- 按 Berkshire 披露仓位反推的价格和 `2020Q3` 资产负债表口径估算,earnings yield 只有约 `3.2%`
- 更重要的是,尽管 Humira franchise 很强,整个公司仍然高度依赖专利周期、管线续命和大额并购整合,而不是一个十年一眼能讲清的 Buffett 式 tollbooth
**结论**:不投
**为什么框架可能更合理**:
- AbbVie 是一门赚钱的好生意,但在 2020 年底更像一笔“大型药企篮子”配置,而不是 Berkshire 会永久抱住的高确定性核心 franchise
- 框架在这里不是说公司差,而是在说:高杠杆并购后的大型 pharma 平台,不值得按 Buffett Oracle 的长期复利标准去重仓 underwriting
**实际结果**:Berkshire 在 `2020-09-30` 披露持有 `21,264,316` 股 AbbVie、价值约 `$1.86B`;到 `2021-12-31` 已缩到 `3,033,561` 股,且在 `2022-12-31` 13F 中不再出现。这笔投资赚钱了,但并没有发展成 Berkshire 的永久核心持仓。
---
### #17 Bristol-Myers Squibb (2020) ⭐
**公开判断时点**:2020年 | **数据源**:Bristol-Myers Squibb FY2019 10-K + Bristol-Myers Squibb Q3 2020 10-Q + Berkshire 2020-09-30 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `16.8%`
- 收入从 `2017` 年的 `$20.8B` 增到 `2019` 年的 `$26.1B`,`2020Q3` 九个月收入更达到 `$31.45B`
- 真正卡住它的是 `g2 + g6 + g7`
- 由于 Celgene 并购后的大量摊销和整合影响,`2020Q3` 的 trailing 12 months 净利润几乎为零,`FCF / NI` 口径直接失真为负值
- 按 Berkshire 披露仓位和 `2020Q3` 资产负债表估算,earnings yield 也大约为零
- 即使承认 Celgene 带来了大量优质资产,BMS 在 2020 年底仍然更像一个需要持续整合、处理专利悬崖并不断补充管线的 pharma 组合体,而不是简单清晰的 decade-long tollbooth
**结论**:不投
**为什么框架可能更合理**:
- Buffett 买入时更像是在大药企之间做组合配置,而不是在下一个 Coca-Cola 上重仓
- Oracle 在这类 case 里保持保守,等于主动回避“财报现金流不错,但 franchise 结构不够干净”的大型并购药企
**实际结果**:Berkshire 在 `2020-09-30` 披露持有 `29,971,194` 股 Bristol-Myers、价值约 `$1.81B`;到 `2021-12-31` 只剩 `5,202,674` 股,并在 `2022-12-31` 的 13F 中消失。这笔投资不是灾难,但也没有变成 Berkshire 的定义性长期大赢。
---
### #18 Pfizer (2020) ⭐
**公开判断时点**:2020年 | **数据源**:Pfizer FY2019 10-K + Pfizer Q3 2020 10-Q + Berkshire 2020-09-30 / 2021-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `24.4%`
- `2020Q3` 的 trailing 12 months `FCF / NI` 约 `1.20x`,现金流表面上并不差
- 负债也没有失控,按 `2020Q3` 净债务 / `2019 EBITDA` 代理口径估算约 `2.1x`
- 真正卡住它的是 `g6 + g7`
- 按 Berkshire 披露的小仓位反推的价格和 `2020Q3` 资产负债表估算,earnings yield 只有约 `3.4%`
- 更重要的是,Pfizer 在当时依然是一个需要不断靠研发、BD 和产品组合更新去维持盈利的平台型药企,而不是一个十年后一眼还能讲清“别人为什么复制不了”的 Buffett 式 tollbooth
**结论**:不投
**为什么框架可能更合理**:
- 这笔仓位从一开始就很小,明显不像 Berkshire 在下一个 American Express 或 Coca-Cola 上重仓
- 即使承认 Pfizer 是全球顶级医药公司之一,它在 2020 年更像一笔 tactical pharma basket 配置,而不是一个高确定性长期核心 franchise
- Oracle 在这里保持保守,等于拒绝把“有钱赚的大药企”直接等同于“值得长期 underwriting 的 Buffett 式资产”
**实际结果**:Berkshire 在 `2020-09-30` 披露持有 `3,711,780` 股 Pfizer、价值约 `$136.2M`,但到 `2021-12-31` 的 13F 已经不再出现这笔持仓。Pfizer 后续当然受益于疫情期间的特殊环境,但从 Berkshire 的持仓行为看,这更像短期组合动作,而不是长期核心押注。
---
### #19 Barrick Gold (2020) ⭐
**公开判断时点**:2020年 | **数据源**:Barrick Gold FY2019 Form 40-F + Barrick Gold Q3 2020 6-K / Exhibit 99.2 + Berkshire 2020-09-30 / 2020-12-31 / 2021-03-31 13F-HR
**为什么当前框架会给 PASS**:
- `2017-2019` 平均 ROE 只有约 `6.3%`,因为 2018 年的巨额亏损把三年均值明显拉低
- 按 `2020Q3` 的 trailing 12 months 口径,`FCF / NI` 约 `0.74x`,没有过 `0.8x` 的硬门槛
- 资产负债表其实很强,按 `2020Q3` 净债务 / `9M 2020 adjusted EBITDA` 代理口径估算只有约 `0.08x`
- 估值也不算离谱,earnings yield 大约 `7.2%`
- 真正让它仍然过不了的是 `g1 + g2 + g7`:这门生意的回报和现金流仍然高度依赖金价与矿山资产周期,而不是一个可以十年清晰复述的结构性护城河
**结论**:不投
**为什么框架可能更合理**:
- Barrick 在 2020 年确实是“修复后更漂亮”的矿业公司,但更漂亮不等于变成 Buffett Oracle 想长期 underwriting 的 franchise
- 这个框架在 commodity names 上本来就故意严格,因为它要回避的是“看起来便宜而且正在好转”的周期资产被误判成长期复利机
- Berkshire 后续的交易轨迹也支持这一点:这不是重仓长期押注,而更像一次很快就撤掉的战术仓位
**实际结果**:Berkshire 在 `2020-09-30` 披露持有 `12,000,000` 股 Barrick Gold、价值约 `$337.3M`,但这笔持仓在 `2020-12-31` 的 13F 已经消失。它并没有演变成 Berkshire 的长期矿业平台。
---
### #20 Amazon.com (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Amazon FY2019 10-K + Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `17.6%`
- 生意质量毋庸置疑,moat 也明确能过
- 真正卡住它的是 `g2 + g6`
- 2019 年 `FCF / NI` 约 `0.73x`,看起来还没达到框架要求的现金转化
- 按 2020 年底 Berkshire 披露仓位反推价格,earnings yield 只有约 `0.7%`
- 也就是说,Oracle 会承认 Amazon 是世界级平台,但仍会说“太贵了”
**结论**:不投
**为什么框架可能更合理**:
- Berkshire 的仓位并不小,但也始终没有被升级成真正的 top-tier Buffett 核心
- 这是好生意明显好过好价格的案例
- Oracle 在这里更像是在坚持 margin-of-safety,而不是否定 business quality
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `419,500` 股 Amazon、价值约 `$1.37B`;到 `2022-12-31` 仍持有经拆股调整后的 `8,390,000` 股,但这始终不是组合里的 defining core position。
---
### #21 Biogen (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Biogen FY2019 10-K + Berkshire 2020-12-31 / 2021-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `33.2%`
- `FCF / NI` 约 `1.12x`
- 负债也不重,净债务 / EBITDA 约 `0.85x`
- 但 gate ⑦ 过不了:Biogen 仍然是典型需要靠管线和专利续命的 biotech 平台
- 这类公司可以非常赚钱,却不够像 Buffett Oracle 想长期 underwriting 的 tollbooth
**结论**:不投
**为什么框架可能更合理**:
- Buffett/伯克希尔这笔仓位本来就不大
- 如果公司真是高确定性 decade-long franchise,通常不会这么快从披露列表里消失
- Oracle 在这里更像是在回避“财务不错但 moat 不够干净”的 biotech 组合体
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `643,022` 股 Biogen、价值约 `$157.5M`;到 `2021-12-31` 13F 已经不再出现这笔持仓。
---
### #22 Charter Communications (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Charter FY2019 10-K + Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 宽带业务确实有 local monopoly / duopoly 特征,moat 可以讲得清楚
- 但 `g1` 没过,2017-2019 平均 ROE 只有约 `9.9%`
- `g3` 也没过,净负债 / EBITDA 约 `6.3x`
- 再加上 `g6` 只有约 `0.8%` 的 earnings yield,价格和资本结构都太绷
**结论**:不投
**为什么框架可能更合理**:
- Charter 是好资产,但不是便宜资产
- 2020 年底这个价位更像市场把未来多年 broadband economics 都提前贴现了
- Oracle 在这里不是看不懂 moat,而是在说:太贵、太 levered
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `5,213,461` 股 Charter、价值约 `$3.45B`;到 `2022-12-31` 仍持有 `3,828,941` 股,但市值明显低于 2020 年底水平,这不是一笔干净的 Buffett-style compounding win。
---
### #23 Kroger (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Kroger FY2020 10-K + Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 财务上它其实很干净:ROE、现金流和杠杆都过关
- 真正卡住它的是 `g6 + g7`
- 按 2020 年末价格算,earnings yield 约 `4.4%`
- 更关键的是,Kroger 虽然是好 operator,但 grocery 并不是一个十年一眼能讲清的 irreplicable moat
**结论**:不投
**为什么框架可能更合理**:
- Berkshire 后来确实加了很多 Kroger,但这更像 defensive retail / inflation basket 里的成功仓位
- 它不是 Coca-Cola、American Express 或 Moody's 那种 franchise purity
- Oracle 在这里保持保守,是在区分“好执行的零售商”和“Buffett 式 tollbooth”
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `3,900,000` 股 Kroger、价值约 `$123.9M`;到 `2021-12-31` 增到 `28,020,000` 股,`2022-12-31` 仍持有 `16,607,090` 股。这是一笔有效的防御型仓位,但不是定义性的 moat 胜利。
---
### #24 Marsh & McLennan (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Marsh & McLennan FY2019 10-K + Berkshire 2020-12-31 / 2021-03-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `21.6%`
- `FCF / NI` 约 `1.09x`
- 客户黏性和全球风险管理关系也是真实 moat
- 但按 2020 年底价格算,earnings yield 只有约 `2.5%`
- 所以 Oracle 会给出一个典型的“伟大服务 franchise,但价格太贵”的 PASS
**结论**:不投
**为什么框架可能更合理**:
- 这笔仓位虽然 2021Q1 还加过,但很快就被砍到 token size
- 如果 Berkshire 自己都没有把它变成长期核心,那 Oracle 保持 valuation discipline 是说得通的
- 这条主要是提醒我们:好公司和好价格不是一回事
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `4,267,825` 股 Marsh、价值约 `$499.3M`;`2021-03-31` 增到 `5,287,526` 股,但到 `2021-12-31` 已缩到 `404,911` 股,并在 `2022-12-31` 仍保持这个极小仓位。
---
### #25 Mastercard (2020) ❌
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Mastercard FY2019 10-K + Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 经营质量极高,支付网络 moat 当然成立
- `FCF / NI` 约 `0.96x`,杠杆几乎没有
- 真正卡住它的只有 `g6`:按 2020 年末价格估算,earnings yield 只有约 `2.2%`
- Oracle 会因此把它归类为“顶级 business,但价格不合格”
**结论**:不投
**为什么会错**:
- 这类全球支付网络本身就是 Buffett/Berkshire 非常愿意长期拿的资产类型
- Berkshire 到 `2022-12-31` 仍然持有接近 `399万` 股 Mastercard
- 这说明当前 `g6` 对超级网络型 franchise 仍然太钝,容易把真正 exceptional business 全部一刀切掉
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `4,564,756` 股 Mastercard、价值约 `$1.63B`;到 `2021-12-31` 和 `2022-12-31` 仍各持有 `3,986,648` 股。它明显不是短线仓位。
---
### #26 Mondelez International (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Mondelez FY2019 10-K + Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `12.8%`
- snack brand moat 也可以成立
- 但 `FCF / NI` 只有约 `0.78x`
- 按 2020 年末价格算,earnings yield 也只有约 `3.8%`
- 于是它会变成一条标准的“成熟好公司,但回报起点不够高”的 PASS
**结论**:不投
**为什么框架可能更合理**:
- Berkshire 自己也只持有极小仓位
- 这更像 legacy/observer position,而不是 high-conviction underwriting
- Oracle 在这里不是说 Mondelez 差,而是说“没便宜到值得按 Buffett 核心仓标准出手”
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `578,000` 股 Mondelez、价值约 `$33.8M`,并在 `2021-12-31` 和 `2022-12-31` 继续持有同样数量。
---
### #27 Procter & Gamble (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:P&G FY2020 10-K + Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 财务指标漂亮:ROE、FCF / NI、杠杆、收入趋势、毛利率都过
- 真正的问题还是 `g6`
- 按 2020 年末价格估算,earnings yield 只有约 `3.6%`
- 也就是说,Oracle 会承认这是世界级 consumer franchise,但仍然不会说“这价钱够便宜”
**结论**:不投
**为什么框架可能更合理**:
- Berkshire 留下的是一个极小的 legacy stake,不像在做新的高确信重仓
- 这更像对 franchise quality 的认可,而不是对 future return 的强背书
- Oracle 在这里强调的仍是同一句话:quality 不等于 margin of safety
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `315,400` 股 P&G、价值约 `$43.9M`,并在 `2021-12-31` 和 `2022-12-31` 都保持这个极小仓位。
---
### #28 RH (2020) ❌
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:RH FY2020 10-K + Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 经营数据其实不差:ROIC proxy 很高,现金流和负债也都过关
- 收入和毛利率到 2020 年都在走强
- 真正卡住它的是 `g6 + g7`
- 按 2020 年末价格算,earnings yield 只有约 `2.3%`
- 更关键的是,Oracle 不愿意把 luxury furnishings retailer 直接认定成十年后仍不可复制的 Buffett moat
**结论**:不投
**为什么会错**:
- Berkshire 后来不仅没退出,反而继续加仓
- 这说明当前 moat test 对某些 founder-led specialty retail 模式仍然偏严
- RH 不是传统快消品牌,也不是普通家具零售商,这种“设计系统 + 客户群 + price architecture”的 moat 现在还没被框架吃透
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `787,469` 股 RH、价值约 `$352.4M`;到 `2021-12-31` 增到 `871,468` 股,`2022-12-31` 又增到 `1,163,000` 股。
---
### #29 Verizon Communications (2020) ⭐
**公开判断时点**:2020年末可见 Berkshire 持仓 | **数据源**:Verizon FY2019 10-K + Berkshire 2020-12-31 / 2021-03-31 / 2021-12-31 / 2022-12-31 13F-HR
**为什么当前框架会给 PASS**:
- 2017-2019 平均 ROE 约 `43.1%`
- `FCF / NI` 约 `0.99x`
- 杠杆也没有失控,净负债 / EBITDA 约 `2.4x`
- 真正卡住它的是 `g6 + g7`
- 按 2020 年末价格估算,earnings yield 只有约 `5.5%`,略低于框架红线
- 更重要的是,telecom 虽然有 spectrum 和规模,但很难算成 Buffett 最爱的 pristine tollbooth
**结论**:不投
**为什么框架可能更合理**:
- 这笔仓位很大,但最终并没有长期留下来
- Oracle 在这里坚持的是:成熟 telecom 的可见性不错,但 franchise purity 不够
- 后来的退出轨迹说明,这更像大额但非永久的 defensive allocation
**实际结果**:Berkshire 在 `2020-12-31` 披露持有 `146,716,496` 股 Verizon、价值约 `$8.62B`;到 `2021-03-31` 增到 `158,824,575` 股,`2021-12-31` 仍保持该数量,但到 `2022-12-31` 已不再出现。
FILE:buffett_brain.md
# Buffett Brain v1.2
*Last updated: 2026-03-25 | Version history below*
---
## CORE PHILOSOPHY
### The Business Owner Mindset
"我是一个更好的投资者,因为我是一个商人;我是一个更好的商人,因为我是一个投资者。"
- 买股票 = 买企业的一部分,而不是买一张会涨跌的纸
- 问自己:如果交易所明天关闭5年,你还愿意持有吗?
- 不理解这门生意,就不该投钱进去 —— 能力圈是神圣边界
### The Two Rules
1. **永远不要亏损本金**
2. **永远不要忘记第一条规则**
*不是说不会有亏损,而是说每一笔投资前就要问:最坏情况我能承受吗?*
### Mr. Market
- 市场是一个患有躁郁症的合伙人,每天都在给你报价
- 他情绪好时出高价,情绪坏时出低价
- 你的工作是利用他的情绪,而不是被他的情绪左右
- "别人贪婪时恐惧,别人恐惧时贪婪" —— 这不是格言,这是操作系统
### Margin of Safety
- 用50分钱买价值1块钱的东西 —— 这是一切的基础
- 安全边际保护你抵抗:错误估值、坏运气、黑天鹅
- 越难估值的资产,需要越大的安全边际
- 如果一次错误就会让你花很多年回本,买价大概率已经太高
---
## GRAHAM OPERATING LAYER
*以下约束补强自《聪明的投资者》第1 / 5 / 7 / 8 / 20章与巴菲特序言。重点不是增加名言,而是增加决策边界。*
### 1. 先区分 Investment vs Speculation
- 格雷厄姆定义:**投资操作必须同时满足** 深入分析、本金安全、回报适当;不满足这三条的操作就是投机
- Oracle 在每一份 live memo 开头先问:这是 `INVESTMENT`、`SPECULATION`,还是 `TOO HARD`
- 依赖短期走势预测、估值继续扩张、别人更高价接盘的逻辑,默认归类为投机
- 投机如果存在,必须与投资仓、投资评分、回测命中率完全分开
- 对非专业投资者,任何需要保证金或高杠杆才能成立的 thesis,默认不属于可接受投资
### 2. 默认用户是防御型投资者,不是进取型高手
- 格雷厄姆先分投资者类型,再谈选股:**防御型**的第一目标是避免重大错误和重大亏损;**进取型**才追求超额收益
- Buffett Oracle 的公开默认模式应当是**防御型**,除非用户明确展示出愿意投入大量时间和精力做更深研究
- 防御型建议优先级:少犯大错 > 提高收益上限
- 防御型偏好:大型、知名、财务稳健、长期分红记录、估值不过分
- 进取型也不等于“会择时”,而是愿意做更深的个股、廉价证券或特殊情境研究
### 3. 估价优先,拒绝择时幻觉
- 格雷厄姆明确区分两条路:`估价` 与 `择时`
- Oracle 默认只承认基于**价值与价格错位**的结论,不把“市场接下来大概率要涨/跌”当成主要论据
- 对市场、泡沫、择时问题,默认动作不是猜顶抄底,而是:提高要求回报、收紧筛选标准、保留流动性
- 真正的买入理由必须是:`underwritten value > paid price`,而不是图形、情绪或宏观猜测
### 4. 安全边际必须写成数字,而不是口号
- 每一个 BUY 至少写出:`normalized earnings / owner's earnings`、`conservative value range`、`required return`、`implied discount`
- 不确定性越高,要求的折价越大;越依赖未来远期增长,越不能给高估值
- 即使是好公司,买价过高也会把原本的优势全部抵消
- 在 commit capital 之前,必须先回答:如果我错了,回本需要多久?
### 5. 风险首先是永久性亏损,其次是行为失控
- 风险不等于波动本身;风险是本金受损后难以恢复,或在波动中被迫做错事
- 镜子测试:我真的知道得比对手盘更多吗?如果错了会亏多少?组合相关性会不会一起出问题?
- 好判断不只看 upside,也要看:错误时的后果能否承受
- 如果 thesis 正确与否主要取决于你的情绪能否稳定,那这个仓位已经太大了
---
## INVESTMENT FRAMEWORK — 5 DIMENSIONS
### Dimension 1: 可理解性(Circle of Competence)
**核心问题**:这门生意10年后还存在吗?我能描述它是如何赚钱的吗?
- 必须能用一段话解释商业模式
- 无法解释 = 不投
- 行业快速变化 = 加大不确定性折扣
- **红旗**:依赖持续技术迭代才能存活的生意
### Dimension 2: 护城河(Economic Moat)
**核心问题**:10年后,竞争对手能否复制这门生意?
四类护城河:
1. **品牌定价权**:可口可乐、喜诗糖果 —— 消费者愿意多付钱
2. **网络效应**:用户越多越有价值(AMEX、早期报纸)
3. **切换成本**:客户离开的代价极高(B2B软件、银行)
4. **成本优势**:BNSF铁路 —— 运输成本天然低于卡车
- 护城河必须能持续扩大("宽且深")
- 最危险的护城河:仅靠价格低,没有结构性优势
- 管理层很好但没护城河 = 仍然不够
### Dimension 3: 管理层质量
**核心问题**:这些人是在为股东服务,还是在为自己服务?
- 资本配置能力是最核心的管理技能
- 好的管理层:诚实、不过度乐观、承认错误
- **测试**:看他们在困难时期说了什么,做了什么
- 用股东的钱像用自己的钱一样
- 薪酬结构是否和股东利益对齐?
- 警惕:CEO更换频繁、大量并购消化不良、花式PPT
### Dimension 4: 财务健康
**核心问题**:这门生意能产生真实的现金吗?
关键指标:
- **ROE > 15%(持续多年)**:高质量企业的标志
- **低负债**:债务是脆弱的来源,尤其在危机中
- **自由现金流 > 净利润**:说明利润是真实的
- **资本支出低**:少量投入能维持高利润 = 好生意
- **毛利率稳定或扩张**:定价权存在
- 警惕:应收账款增速 > 收入增速;库存堆积;频繁定向增发
### Dimension 5: 估值
**核心问题**:以合理价格买好公司,好过以便宜价格买烂公司。
估值逻辑:
- 公司价值 = 未来现金流的折现
- **Owner's Earnings** = 净利润 + 折旧摊销 - 维持资本开支
- PE仅供参考,更重要的是:当前价格隐含了什么增长假设?
- 好公司不怕贵,但还是要有安全边际
- 宁愿以合理价格等待,不以贵价强上
- 巴菲特惯用:假设利率10%,今天价格能否产生足够回报?
- 价格决定回报率;分析正确但买价太高,仍然可能是坏投资
- 拒绝把“估值以后会更贵”当作投资逻辑
---
## WEB3 / CRYPTO 映射层
*巴菲特不投加密,但他的逻辑可以映射到链上世界。以下是转译规则:*
### 护城河映射
| 传统 | Web3对应 |
|---|---|
| 品牌定价权 | 协议品牌 + 社区信任(Uniswap、Aave) |
| 网络效应 | 流动性深度、开发者生态 |
| 切换成本 | 资金迁移成本、集成度、锁仓 |
| 成本优势 | L2的gas优势、Rollup技术壁垒 |
### 现金流映射
- 协议收入 = 真实现金流(协议费用、清算收入)
- 代币通胀 = 负现金流(稀释持有人)
- TVL ≠ 护城河(流动性是雇佣兵)
- 真正的护城河:用户粘性、开发者依赖、品牌信任
### Web3专用红旗
- 匿名团队(管理层不透明)
- 代币解锁集中在短期
- 协议收入 < 代币激励支出(补贴驱动的伪增长)
- 依赖持续的新用户进来才能维持价格
### Web3专用加分项
- 协议费用归还给真实持有人(非团队持有)
- 代码开源 + 多次审计
- 去中心化治理(不依赖单一控制方)
- 跨周期存活(穿越过熊市)
---
## 关键心理原则
1. **等待最好的球**:投资和棒球不同,你可以等待最甜的那个球再挥棒,不出手没有"三振出局"
2. **活动性 ≠ 质量**:大多数时候最正确的操作是什么都不做
3. **独立思考**:共识不会产生超额回报。你的分析要独立,不要因为大家都说好就好
4. **机会成本思维**:每一笔投资都在和持有现金、持有BRK、持有其他机会竞争
5. **时间是好生意的朋友**:复利需要时间,不要频繁交易打断复利
6. **恐惧和贪婪是信号**:市场极度恐惧时,评估是否有好机会;市场极度贪婪时,评估自己是否还清醒
---
## 快速拒绝清单(一票否决)
直接拒绝,不需要继续分析:
- [ ] 无法解释它如何赚钱
- [ ] 商业模式依赖不断的新资金流入(庞氏结构)
- [ ] 管理层有欺骗或挪用历史
- [ ] 负债率极高且现金流为负
- [ ] 严重依赖单一客户(>50%收入)且客户可随时离开
- [ ] 行业壁垒为零(任何人明天都能复制)
- [ ] 这笔操作本质是投机,却被伪装成投资
- [ ] 逻辑主要依赖择时、情绪反转或估值继续扩张
- [ ] 只有乐观情景才成立,没有足够安全边际
- [ ] 需要保证金或高杠杆才显得有吸引力
---
## Gate Review Protocol
这 7 个 gate 是决策边界,不是宗教戒律。回测中如果某个 gate 反复造成 `framework_wrong`,必须反思它到底是在过滤坏生意,还是在误伤高质量资产。
当前项目的已知反思结论:
- `Gate 2` 的原始 `FCF / NI` 口径容易把再投资型复利股和真正现金流差的公司混在一起
- `Gate 6` 的统一 `6% earnings yield` 口径容易错杀高质量、轻资产、市场基础设施型资产
- `Gate 7` 目前仍然是最可靠的定性过滤器之一,不应轻易放松
因此,今后的 live / expansion memo 需要额外写两段:
- 如果 `Gate 2` 失败:必须补一段 `owner earnings` 说明,区分维护性资本开支和扩张性资本开支
- 如果 `Gate 6` 失败但 moat 很强:必须补一段 `quality multiple` 说明,解释低收益率究竟来自高质量,还是只是高估
注意:
- 这不是自动放宽 gate
- benchmark 为了可比性,原始 7 gate 仍然保留
- 任何真正的阈值修改,都必须先跨案例重跑,再进入正式框架
---
## 自我进化记录
| 版本 | 日期 | 更新内容 | 触发原因 |
|---|---|---|---|
| v1.0 | 2026-03-10 | 初始版本,基于股东信1971-2023 + 股东大会Q&A 1994-2025 | 项目启动 |
| v1.1 | 2026-03-25 | 加入 Graham operating layer:投资/投机分离、防御型/进取型区分、拒绝择时幻觉、安全边际数字化 | 用户要求补足《聪明的投资者》对思考逻辑的约束 |
| v1.2 | 2026-03-25 | 加入 Gate review protocol:保留 7 gate,但要求对 Gate 2 写 owner earnings note、对 Gate 6 写 quality multiple note | 扩展回测显示 false negatives 目前集中在 g2 与 g6 |
---
## 原始语料索引
*以下是可回溯的原始出处,供深入研读:*
- 股东信英文原文:`/Users/pineapple/Documents/warren-buffet/2019/巴菲特致股东信1957-2025/英文原文/`
- 股东信中文翻译:`/Users/pineapple/Documents/warren-buffet/2019/巴菲特致股东信1957-2025/中文翻译/`
- 股东大会Q&A:`/Users/pineapple/Documents/warren-buffet/2019/巴菲特股东大会1994-2025/`
- 《聪明的投资者》:`/Users/pineapple/Documents/warren-buffet/聪明的投资者-第4版高清版.pdf`
FILE:analysis_index.json
{
"_description": "Canonical mapping between backtest rows and company card cache.",
"rows": [
{ "id": 1, "target": "Paramount Global", "decision_year": 2022, "status": "completed", "cards": ["PARA_2021.json"], "card_required": true },
{ "id": 2, "target": "HP Inc.", "decision_year": 2022, "status": "completed", "cards": ["HPQ_2021.json"], "card_required": true },
{ "id": 3, "target": "Chevron", "decision_year": 2020, "status": "completed", "cards": ["CVX_2020.json"], "card_required": true },
{ "id": 4, "target": "Airlines(买入)", "decision_year": 2016, "status": "completed", "cards": [], "card_required": false, "notes": "Sector basket analysis using DAL and LUV filings rather than a single company card." },
{ "id": 5, "target": "Airlines(卖出)", "decision_year": 2020, "status": "completed", "cards": [], "card_required": false, "notes": "Exit decision under COVID shock; no new annual filing-based company card." },
{ "id": 6, "target": "Occidental Petroleum", "decision_year": 2019, "status": "completed", "cards": [], "card_required": false, "notes": "Legacy preferred-structure case analyzed in narrative form before repo validation existed." },
{ "id": 7, "target": "Apple", "decision_year": 2016, "status": "completed", "cards": ["AAPL_2015.json"], "card_required": true },
{ "id": 8, "target": "Precision Castparts", "decision_year": 2015, "status": "completed", "cards": ["PCC_2014.json"], "card_required": true },
{ "id": 9, "target": "IBM", "decision_year": 2011, "status": "completed", "cards": ["IBM_2011.json"], "card_required": true },
{ "id": 10, "target": "Goldman Sachs", "decision_year": 2008, "status": "completed", "cards": ["GS_2007.json"], "card_required": true },
{ "id": 11, "target": "BNSF铁路", "decision_year": 2009, "status": "completed", "cards": ["BNI_2008.json"], "card_required": true },
{ "id": 12, "target": "Bank of America", "decision_year": 2011, "status": "completed", "cards": ["BAC_2010.json"], "card_required": true },
{ "id": 13, "target": "Kraft Heinz", "decision_year": 2015, "status": "completed", "cards": ["KRFT_2014.json"], "card_required": true },
{ "id": 14, "target": "BYD", "decision_year": 2008, "status": "completed", "cards": ["BYD_2008.json"], "card_required": true },
{ "id": 15, "target": "General Electric", "decision_year": 2008, "status": "completed", "cards": ["GE_2007.json"], "card_required": true },
{ "id": 16, "target": "Tesco", "decision_year": 2007, "status": "completed", "cards": ["TESCO_2007.json"], "card_required": true },
{ "id": 17, "target": "American Express", "decision_year": 1994, "status": "completed", "cards": ["AXP_1994.json"], "card_required": true },
{ "id": 18, "target": "Dexter Shoe", "decision_year": 1993, "status": "completed", "cards": ["DEXTER_1993.json"], "card_required": true },
{ "id": 19, "target": "Wells Fargo", "decision_year": 1991, "status": "completed", "cards": ["WFC_1990.json"], "card_required": true },
{ "id": 20, "target": "US Air", "decision_year": 1989, "status": "completed", "cards": ["USAIR_1988.json"], "card_required": true },
{ "id": 21, "target": "Gillette", "decision_year": 1989, "status": "completed", "cards": ["G_1988.json"], "card_required": true },
{ "id": 22, "target": "Coca-Cola", "decision_year": 1988, "status": "completed", "cards": ["KO_1987.json"], "card_required": true },
{ "id": 23, "target": "Capital Cities/ABC", "decision_year": 1985, "status": "completed", "cards": ["CCC_1985.json"], "card_required": true },
{ "id": 24, "target": "Nebraska Furniture Mart", "decision_year": 1983, "status": "completed", "cards": ["NFM_1983.json"], "card_required": true },
{ "id": 25, "target": "Washington Post", "decision_year": 1973, "status": "completed", "cards": ["WPC_1973.json"], "card_required": true },
{ "id": 26, "target": "See's Candies", "decision_year": 1972, "status": "completed", "cards": ["SEES_1972.json"], "card_required": true },
{ "id": 27, "target": "GEICO", "decision_year": 1976, "status": "completed", "cards": ["GEICO_1976.json"], "card_required": true },
{ "id": 28, "target": "National Indemnity", "decision_year": 1967, "status": "completed", "cards": ["NICO_1967.json"], "card_required": true },
{ "id": 29, "target": "Berkshire Hathaway纺织", "decision_year": 1965, "status": "completed", "cards": ["BRKTEXTILE_1965.json"], "card_required": true }
]
}
FILE:backtest_results.md
# Buffett Oracle — 回测 Benchmark 集记录
*数据来源:SEC EDGAR 10-K 原始财报 / 公司官方年报*
*分析框架:buffett_brain.md v1.2*
*最后更新:2026-03-25*
---
## Scope 说明
- 当前文件覆盖的是 **29 个精选 benchmark 案例**
- 它不是 Buffett / Berkshire 全部投资历史
- `29 / 29` 的意思是:当前 benchmark 集已补完
- 不代表:Buffett 这些年只投过 29 个标的
更完整的定义见 [coverage_scope.md](coverage_scope.md)。
---
## 评判标准
- ✅ 同向:框架结论与巴菲特操作一致,结果也验证
- ⭐ 框架胜:巴菲特犯错,框架给出更好判断
- ❌ 框架错:框架结论与正确答案相反
**方法学提醒**:
- 这里统计的是**回顾一致性**,不是可直接外推的预测胜率
- 含模糊结论、结构化交易、命名例外的案例,应和核心二元普通股案例分开看
- 做出 BUY / PASS 判断时,只能使用当时已经公开的数据;后验结果只能放在最后的 reveal 与评分部分
---
## 汇总表(持续更新)
| # | 标的 | 决策年份 | 框架结论 | 巴菲特操作 | 实际结果 | 判定 |
|---|---|---|---|---|---|---|
| 1 | Paramount Global | 2022 | 不投 | 买$26亿 | 亏$16亿,认错 | ⭐ |
| 2 | HP Inc. | 2022 | 可投/非高确信 | 买$42亿 | 中性,持续减持 | ✅ |
| 3 | Chevron | 2020 | 买入 | 买$41亿→$198亿 | 大赢 | ✅ |
| 4 | Airlines(买入) | 2016 | 不投/谨慎 | 买~$80亿四家 | 亏$50亿,认错 | ⭐ |
| 5 | Airlines(卖出) | 2020 | 卖出✓ | 全部清仓 | 正确(COVID) | ✅ |
| 6 | Occidental Petroleum | 2019 | 买入(优质优先股) | $100亿优先股+认股权证 | 大赢 | ✅ |
| 7 | Apple | 2016 | 买入 | 买→$177亿峰值 | 历史级大赢 | ✅ |
| 8 | Precision Castparts | 2015 | 不投(估值过高) | $372亿全收购 | 减值$110亿,认错 | ⭐ |
| 9 | IBM | 2011 | 谨慎/不投 | 买~$120亿 | 亏损,2018年清仓认错 | ⭐ |
| 10 | Goldman Sachs | 2008 | 买(优先股危机套利) | $50亿优先股+认股权证 | 大赢 | ✅ |
| 11 | BNSF铁路 | 2009 | 买入 | $440亿全收购 | 历史级大赢 | ✅ |
| 12 | Bank of America | 2011 | 买入(优先股结构) | $50亿优先股+权证 | 大赢($120亿+) | ✅ |
| 13 | Kraft Heinz | 2015 | 不投 | 合并收购 | 亏损,认错 | ⭐ |
| 14 | BYD | 2008 | 买入(成长例外) | $2.32亿→$80亿峰值 | 大赢 | ✅ |
| 15 | General Electric | 2008 | 买入(危机优先股) | $30亿优先股+权证 | 小赢 | ✅ |
| 16 | Tesco | 2007 | 不投 | ~$23亿 | 亏$4.4亿,认错 | ⭐ |
| 17 | American Express | 1994 | 买入 | 持续买入 | 大赢,永久持有 | ✅ |
| 18 | Dexter Shoe | 1993 | 不投 | $4.33亿BRK股份 | 最差决策,损失$35亿+ | ⭐ |
| 19 | Wells Fargo | 1991 | 买入 | 危机买入 | 30年大赢 | ✅ |
| 20 | US Air | 1989 | 不投 | $3.58亿优先股 | 险些全损,最终小赢 | ⭐ |
| 21 | Gillette | 1989 | 买入 | $6亿可转换优先股 | 大赢 | ✅ |
| 22 | Coca-Cola | 1988 | 买入 | $13亿 | 历史级大赢 | ✅ |
| 23 | Capital Cities/ABC | 1985 | 买入 | $5.175亿 | 大赢 | ✅ |
| 24 | Nebraska Furniture Mart | 1983 | 买入 | $6000万 | 大赢 | ✅ |
| 25 | Washington Post | 1973 | 买入 | $1060万 | 历史级大赢 | ✅ |
| 26 | See's Candies | 1972 | 买入 | $2500万 | 转型性大赢 | ✅ |
| 27 | GEICO | 1976 | 买入 | 危机买入 | 历史级大赢 | ✅ |
| 28 | National Indemnity | 1967 | 买入 | $860万 | 奠基性收购 | ✅ |
| 29 | Berkshire Hathaway纺织 | 1965 | 不投 | 接管控制 | 巴菲特最大失误 | ⭐ |
---
## 当前进度:已完成分析 29 / 29 benchmark 案例(数据已收集,分析已完成)
---
## 详细分析
### #1 Paramount Global (2022) ⭐
**买入**:2022年Q1,约$38/股,$26亿 | **数据源**:2021年10-K(SEC EDGAR)
**关键数字**:
- 净利润$45亿 vs 自由现金流仅**$6亿**(差距$39亿——利润虚高)
- 调整后OIBDA $44.4亿(同比下降13%)
- 表内净债务$120亿 + 表外内容承诺$326亿 = **真实总负债$446亿**(OIBDA的10倍)
- Paramount+订阅3280万 vs Netflix 2.2亿
- 流媒体收入$42亿(仅14.7%),传统TV收入$176亿(61.8%,结构性衰退)
**评分**:3.5/10 | **结论**:不投
**一票否决**:FCF与利润严重背离 + 真实负债10x OIBDA + 核心收入来源萎缩
**实际结果**:亏$16亿,2024年清仓,巴菲特认错 | **判定**:⭐
---
### #2 HP Inc. (2022) ✅
**买入**:2022年Q1,均价约$34.70,$42亿(约11%) | **数据源**:FY2021 10-K
**关键数字**:
- 打印业务营业利润率18.1%(护城河存在),PC业务7.2%(无护城河)
- 正常化FCF约$35亿(剔除Oracle诉讼和解$23亿一次性收入)
- 净债务仅$32亿(极轻)
- 耗材收入$126亿——但仍低于2019年$129亿(需求长期趋势存疑)
- 3年回购510亿股,流通股缩减30%
- FCF收益率约9.3%,EV/EBIT 7.8倍
**评分**:6.7/10 | **结论**:可投,非高确信
**实际结果**:中性,持续减持 | **判定**:✅
---
### #3 Chevron (2020) ✅
**买入**:2020年Q4,约$65–70,$41亿→2022年加仓至$198亿 | **数据源**:2020年10-K
**关键数字**:
- 2020净亏损$55亿(COVID:美国业务实现油价仅$30.53/桶)
- 正常化FCF($55–60油):约$100–130亿 vs 2020年FCF $17亿
- **连续33年提高股息**,亏损年仍将股息从$4.76→$5.16
- 买入时股息收益率**7.9%**
- 净债务率22.7%——整个行业最低(要塞资产负债表)
**评分**:7.5/10 | **结论**:买入(周期底部+行业最优)
**实际结果**:油价复苏+俄乌战争,仓位加至$198亿,大赢 | **判定**:✅
---
### #4 Airlines买入(2016年)⭐
**买入**:2016年Q4,同时买入DAL/LUV/UAL/AAL四家,总计约$70–90亿
**数据源**:DAL 2015年10-K + LUV 2015年10-K(SEC EDGAR)
**关键数字(当时看起来很好)**:
| 指标 | Delta (DAL) | Southwest (LUV) |
|---|---|---|
| 营收 | $407亿 | $198亿 |
| 营业利润率 | 19.2% | 20.8% |
| FCF | $50亿 | $12亿 |
| 净债务 | $67亿 | 近零($1.3亿)|
| ROIC | 28.3% | 32.7%(税前)|
| 燃油成本/营收 | 16.1% | 18.2% |
**表面看极度诱人**:利润率20%,ROIC30%+,燃油成本从2014年高位大幅下降。
**框架为什么说不投**:
1. **无定价权**:航空票价是纯商品,乘客唯一判断标准是价格。没有任何一家航空公司可以持续涨价而不失去客户
2. **结果高度依赖油价**:燃油成本从28.9%降至16.1%——这是**暂时性**顺风,不是结构性护城河。油价回升,利润立刻消失
3. **劳动力成本刚性**:工会合同、飞行员短缺,成本只会升不会降
4. **资本无底洞**:飞机每隔15–20年必须更换,永续资本支出
5. **极端脆弱**:任何冲击(战争、疫情、油价飙升、衰退)都能瞬间摧毁盈利
6. **历史铁证**:1978年美国航空业放开管制后,行业累计亏损超过所有年度盈利之和
即使是Southwest这个最强的个体(无债务、低成本模型、32.7% ROIC),**在大环境冲击前也无能为力**。
**评分**:3.5/10(行业评分,非单一公司)| **结论**:不投
**实际结果**:2020年COVID全部亏损清仓,损失约$50亿,巴菲特公开认错 | **判定**:⭐
---
### #5 Airlines卖出(2020年)✅
**背景**:COVID疫情,巴菲特在2020年5月股东大会宣布全部清仓
**框架逻辑**:当初买入的前提(行业整合后的定价权)在COVID下被彻底证伪。航班停飞,收入归零,固定成本不变。无论什么估值,业务的生存本身存疑。清仓是唯一理性选择。
**结论**:卖出正确 | **判定**:✅
---
### #6 Occidental Petroleum(2019年)✅
**投资**:2019年4月,$100亿8%优先股+认股权证(以协助OXY完成收购Anadarko)
**数据源**:OXY FY2018 10-K(SEC EDGAR)
**关键数字(投资前的OXY)**:
- 营收$178亿(2018),FCF $27亿,净债务$74亿
- 日产量65.8万桶,已探明储量27.5亿桶
- 股息$3.10/股,连续多年增长
- Permian Basin核心资产,成本优势明显
- OxyChem(化工)贡献$11.6亿利润,业务多元化
**这不是普通股权投资,而是优先股+认股权证**:
- 8%年息 = $100亿 × 8% = **每年$8亿现金回报**
- 认股权证:以$62.50行权价购买8000万股普通股(免费看涨期权)
- 优先股在破产中先于普通股获偿
**框架逻辑**:这是"危机资本"部署模式——不分析OXY的护城河是否足够宽,而是:① 这个利率是否合理补偿风险?② OXY会不会倒闭?③ 认股权证有没有价值?
答案:$8亿/年固定回报 + OXY不会倒闭(Permian资产价值远超债务)+ 认股权证=免费彩票
**评分(优先股角度)**:8/10 | **结论**:买入优先股
**实际结果**:后续OXY股价下跌→巴菲特以$27–30低价大量购入普通股→2022年油价飙升→大赢 | **判定**:✅
---
### #7 Apple(2016年)✅
**买入**:2016年Q1开始,成本基础约$310亿,峰值市值$1770亿
**数据源**:Apple FY2015 10-K(SEC EDGAR,2015年10月28日提交)
**关键数字(2015财年)**:
- 营收$2337亿,净利润$534亿,**FCF $700亿**
- 净现金$1412亿(总现金$2057亿 - 总债务$645亿)
- iPhone = 66%营收,FY2015增长52%,单季出货2.31亿部
- Services收入$199亿(+10% YoY)——这是真正的护城河来源
- 营业利润率30.5%,ROE 46.2%
- 3年回购规模:FY2015单年回购$410亿,流通股从65亿减至58亿
**估值(买入时约$100–110/股)**:
- 市值约$580亿
- 企业价值(扣除净现金):约$440亿
- FCF $700亿 → **EV/FCF = 6.3倍,FCF收益率16%** → 极度便宜
- PE约10.8倍 → 市场把它当成正在死亡的硬件公司在定价
**护城河分析**:
- App Store生态:超过150万应用,用户迁移成本极高(应用内购记录、照片、iMessage)
- 设备生态系统锁定:iPhone+iPad+Mac+Apple Watch互联,一旦进入难以离开
- Services业务:30%毛利率→高毛利率软件/服务持续扩大,护城河随时间变宽
**评分**:9/10 | **结论**:强力买入
**一句话**:以10倍PE买入世界上最好的消费品生态系统,还附赠$1412亿净现金——市场定价完全错误
**实际结果**:成本$310亿→峰值$1770亿,历史级大赢 | **判定**:✅
---
### #8 Precision Castparts(2015年)⭐
**买入**:2015年8月,$235/股,$372亿全收购(含溢价)
**数据源**:PCP FY2015 10-K(SEC EDGAR,财年截至2015年3月)
**关键数字**:
- 营收$100亿,净利润$15.3亿,FCF **$12.5亿**
- 营业利润率26%(但当年利润率从18.4%下滑至15.4%!)
- ROIC约10%
- 总债务$46亿(2012年收购TIMET后杠杆明显上升)
- 商誉$66亿(总资产35%)
- 航空业务占70%收入(GE单客户13%)
- 订单积压$81亿(vs $73亿前一年),看似健康
**核心估值问题**:
- 收购价$372亿 / FCF $12.5亿 = **30倍FCF** → 航空工业零部件公司,30倍?
- EV/EBIT = $372亿 / $26亿 = **14.3倍** → 峰值利润的14倍
- 这是一家**周期性工业公司**,按照峰值利润给了成长股估值
**框架为什么说不投(此价格)**:
1. 利润率已经开始下滑(return on sales 18.4%→15.4%,gross margin 34.4%→32.5%)
2. 30倍FCF对周期性工业过于昂贵——一旦航空业下行,利润可以腰斩
3. 大量收购历史(仅FY2013就花$51亿)使得"正常化利润"难以判断
4. TIMET收购($29亿钛金属)让公司更暴露于航空周期
护城河存在(精密铸件的切换成本很高),但这个价格已把10年的增长提前定价。
**评分**:5/10(护城河7,估值3)| **结论**:不投(此价格)
**实际结果**:2020年减值$110亿,仍低于成本基础,巴菲特承认"高估了正常化盈利能力" | **判定**:⭐
---
### #9 IBM(2011年)⭐
**买入**:2011年,约$10–12亿,2018年全部清仓
**数据源**:IBM FY2010 10-K(SEC EDGAR,2011年2月22日提交)
**关键数字(2010年)**:
- 营收$998亿(+4.3%),净利润$148亿,FCF约$153亿
- 软件部门毛利率**86.9%**,预税利润率35.8% → 这是真实的护城河
- ROE 64.6%(回购驱动的负账面价值效应)
- 8年连续两位数EPS增长
- 2010年宣布"Road to $20 EPS by 2015"——$15.19 EPS to $20
- 驱动因素:$500亿回购+$200亿分红+业务增长
- 2010年回购$154亿,股数从2001年至今减少40%+
**表面看极其吸引人**:软件护城河、持续增长、大量回购、EPS稳健增长。
**框架疑虑(当时可见的红旗)**:
1. **营收增长4.3%,但剔除货币汇率仅+3.3%** — 核心业务增长缓慢
2. **EPS增长15% vs 营收增长4%** — 差值来自回购,不是业务 → 这是在用财务工程掩盖业务停滞
3. **系统和技术部门(硬件)**:营收$180亿但利润率低,正在被云蚕食
4. **云计算威胁**:Amazon AWS在2010年已经存在并快速增长。IBM的护城河是**企业遗留系统**,而不是新增业务的首选
5. **$20 EPS roadmap**:如果需要通过$500亿回购来实现EPS目标,说明业务本身增长不足以支撑
本质上,IBM是一家在用资本配置效率(回购)来掩盖业务模式的缓慢侵蚀。软件护城河是真实的,但它锁定的是**过去**的企业基础设施,不是未来的。
**评分**:5.5/10 | **结论**:谨慎/不投
**实际结果**:亏损,2018年清仓,巴菲特承认"分析错了" | **判定**:⭐(框架给出了正确警告)
---
### #10 Goldman Sachs(2008年危机)✅
**投资**:2008年9月,$50亿10%永久优先股+认股权证(行权价$115,购买5000万股)
**数据源**:Goldman Sachs FY2007 10-K(SEC EDGAR)
**关键数字(危机前最后一个完整年度)**:
- 净营收$460亿,净利润$116亿
- ROE **32.7%**,ROTE 38.2% → 极优秀
- 总资产$1.12万亿,股东权益$428亿 → **杠杆率26.2倍**
- 无担保长期借款$1641亿,到期结构横跨2043年
- 没有Tier 1资本率披露(不是银行控股,是SEC监管的CSE)
**这不是传统股权分析,而是危机资本套利**:
巴菲特不是在分析高盛值多少钱,而是在回答两个问题:
1. **高盛会不会倒闭?** 不会——太大不能倒,政府一定救
2. **10%永久优先股是否合理补偿了风险?** 是——$50亿×10%=$5亿/年稳定现金,远超市场利率
认股权证($115行权价×5000万股)= 免费的巨大看涨期权
**评分(优先股套利角度)**:9/10 | **结论**:买入优先股
**实际结果**:高盛支付$5亿溢价赎回优先股+认股权证大幅盈利,总回报约$37亿+ | **判定**:✅
---
### #11 BNSF铁路(2009年)✅
**投资**:2009–2010年,$440亿全收购(Berkshire已持有股份,收购剩余股份)
**数据源**:BNI FY2008 10-K(SEC EDGAR,2009年2月提交)
**关键数字**:
- 营收$180亿(2008),营业利润$39亿,净利润$21亿,FCF **$18亿**
- 运营比率78.3%(行业标准:越低越好)—— 5年从85%→78%,持续改善
- 净债务/总资本44.5%(铁路行业正常水平)
- 货运量:消费品$61亿 + 工业品$40亿 + 煤炭$40亿 + 农产品$34亿(高度多元化)
- 5年营收CAGR +13%(2004年$109亿→2008年$180亿)
- 资本支出$22亿/年,但折旧$14亿——维持性资本支出约$14亿,增长性约$8亿
**护城河分析(满分护城河)**:
- 铁路是**基础设施垄断**:不可能再建一条从西海岸到芝加哥的铁路
- BNSF + Union Pacific控制美国西部铁路网络,天然双寡头
- 运输成本比卡车低3–4倍(每吨英里成本)
- 不可替代:美国粮食、能源、消费品物流核心动脉
**估值**:
- 收购时PE约15–17倍(基于正常化利润)
- 铁路的资本支出一旦建成后基本稳定,FCF会持续增长
**评分**:9.5/10 | **结论**:强力买入(巴菲特自称"美国经济的全押注")
**实际结果**:自收购后累计盈利超过$400亿 | **判定**:✅
---
### #12 Bank of America(2011年危机)✅
**投资**:2011年8月25日,$50亿6%优先股 + 认购7亿股权证(行权价$7.14,10年期)
**数据源**:BAC FY2010 10-K(SEC EDGAR)
**关键数字(FY2010)**:
- 2010净亏损:**$(22.4)亿**(主因:$104亿非现金商誉减值)
- 总收入:$1,114亿 | 总资产:**$2.26万亿**
- 有形账面价值/股(TBV):**$12.98**
- Tier 1 Common资本充足率:**8.60%**(监管最低4%的2倍以上)
- 存款总额:$1.01万亿(全美第一)
- 交易当日股价:**$6.99**(较峰值跌52%,较TBV打54折)
- Countrywide遗留抵押贷款损失:2010年以来超$220亿,还在计提中
**五维分析**:
**D1 可理解性(8/10)**:银行存贷模式透明,Buffett一生主业,能力圈核心
**D2 护城河(8/10)**:
- 全美存款第一($1万亿),全美最大零售银行网络
- 消费者切换成本极高(工资卡、账单、房贷绑定)
- **关键判断**:这是信心危机,不是护城河危机。Countrywide烂账是外部伤,不是内部腐烂
**D3 管理层(7/10)**:
- CEO Moynihan 2010年接任,主动处置Countrywide遗留,卖资产、建资本
- 当Buffett打电话,Moynihan说"不需要钱"——这是高质量管理层该有的姿态
- 诚实透明,不掩盖问题
**D4 财务健康(6/10)**:
- 表面亏损,实质是非现金减值+危机拨备叠加,核心赚钱能力未破坏
- Tier 1资本8.6%——账本没有破,只是市场不信任
- Countrywide尾险是最大变数:10-K估$70–100亿,实际>$220亿(可控,$2.26万亿资产吸收)
**D5 估值(9/10)— 结构性套利,非普通股投资**:
这是第二个Goldman Sachs危机套利(参见#10):
- **优先股6%年息** = $3亿/年,优先于普通股股东,强制收益
- **7亿份认股权证@$7.14** = 免费的10年看涨期权
- 股价$6.99 vs TBV $12.98 → 以54折买有形资产,用优先股保护下行
- 不对称赔付:即使BAC继续亏损3年,优先股照拿;一旦复苏,权证价值爆炸
**一票否决检查**:全部通过(无庞氏结构、无管理层欺诈、Tier 1资本充足、护城河存在)
**评分:7.5/10 | 结论:买入(优先股+权证危机套利结构)**
**实际结果**:
- 优先股年收$3亿股息,共收约6年 ≈ $18亿
- 2017年将权证转换为7亿普通股,转换时股价~$24 → 7亿×($24-$7.14) ≈ **$118亿利润**
- **总回报约$120亿+** | **判定:✅ 同向**
---
### #13 Kraft Heinz(2015)⭐
**交易**:2015年Berkshire + 3G推动Kraft与Heinz合并,Berkshire追加约$50亿现金 | **数据源**:Kraft Foods Group FY2014 10-K(SEC EDGAR press release)
**关键数字**:
- 营收$182.05亿,同比**-0.1%**;有机增长+0.9%,但**销量-0.3%** —— 靠提价掩盖真实需求疲软
- FCF $14.85亿 vs 净利润$10.43亿 —— 现金流表面健康,不是现金造假问题
- 净债务/EBITDA **2.3x** —— 杠杆可控,问题不在资产负债表
- 正常化毛利率3年趋势约**38%→36%→35%** —— 定价权在流失
- 交易估值EV约$460亿,对应收益率仅**5.0%**
- 品牌组合里只有Philadelphia cream cheese接近真正护城河;Oscar Mayer、Maxwell House、Jell-O、Velveeta大多是“被认识”而不是“被偏爱”的旧品牌
**框架为什么说不投**:
1. **Gate ④ fail**:收入停滞,提价掩盖销量下滑,属于结构性疲软而非周期波动
2. **Gate ⑤ fail**:毛利率连续多年走弱,说明品牌定价权被侵蚀
3. **Gate ⑥ fail**:5% earnings yield 不足以覆盖消费品重组风险
4. **Gate ⑦ fail**:护城河测试失败,核心品牌无法在10年后维持不可复制的竞争优势
5. **对照组很关键**:同样是消费品牌,Hershey在相近时期能通过全部gate;问题不是“消费股不行”,而是Kraft这组品牌已经老化
**评分**:4/10 | **结论**:不投
**实际结果**:2018年商誉减值$154亿、SEC调查、股息削减,股价从约$90跌至约$25,Berkshire账面损失$200亿+ | **判定**:⭐
---
### #14 BYD(2008)✅
**买入**:2008年9月,MidAmerican Energy(Berkshire子公司)以HK$8/股投资$2.32亿,获得9.89%股权 | **数据源**:BYD FY2008 Annual Report(HKEX)
**关键数字**:
- 营收约**$35亿**,净利润约**$1.8亿**
- ROE仅**9.2%**,FCF为**-$1亿**左右 —— 按标准硬门槛,①和②都会触发
- 净债务/EBITDA **1.8x** —— 杠杆不高
- EV约**$23.2亿**,earnings yield **7.8%**
- 估值极便宜:约**13x PE / 1.2x PB / 0.7x PS**
- 电池业务具备真实技术壁垒:王传福持有50+专利,NiMH全球份额领先,垂直整合带来约30–40%成本优势
**这里必须明确写出例外:`GROWTH_EXCEPTION`**
标准框架下,BYD会因为ROE和FCF不过关被直接否掉;之所以能继续,是因为这两个失败点更像**高速扩张的副作用**,不是生意质量本身崩坏:
1. 电池与EV一体化方向正确,且在2008年时市场几乎没把这条可选性计价进去
2. 估值仍然满足安全边际,earnings yield 7.8% 过线
3. 创始人能力极强,电池IP护城河真实存在
4. 对照组Hyundai / Nissan在同一时期都没有等价的电池技术壁垒,只是传统车厂
**关键保留意见**:2008年的BYD并不是成熟Buffett式消费垄断,而是更接近Munger式“押卓越创始人+技术拐点”的投资
**评分**:7.5/10 | **结论**:买入(成长例外)
**实际结果**:Berkshire于2025年9月退出持仓,17年总回报约3890%(约40倍) | **判定**:✅
---
### #15 General Electric(2008危机优先股)✅
**买入**:2008年10月,$30亿10%永续优先股 + $30亿普通股权证 | **数据源**:GE FY2007 Annual Report + 2008年9月25日业绩指引修订 + 2008年10月1日交易公告
**关键数字(投资前可见)**:
- 2007年营收**$1727亿**,净利润**$222亿**
- 2008年Q3持续经营利润**$45亿**,营收**$472亿**;真正出问题的是GE Capital,不是工业主业
- 工业与服务订单积压**$1700亿**,同比增长约20%
- GE在2008年9月25日仍预期全年盈利约**$195–210亿**,并强调工业业务利润增长约10–15%
- 危机融资条款极强:**10%票息**,3年后可按**110%**赎回,另附**$22.25**行权价、5年期权证
**这里必须明确写出例外:`CRISIS_PREFERRED`**
如果把GE当普通股来做,框架不会放行:GE Capital的杠杆与流动性压力太大,`Gate ③` 已经足够触发 PASS。
但巴菲特当时买的并不是普通股,而是**危机救助资本**。真正的问题不是“GE是不是完美企业”,而是:
1. GE会不会像AIG那样需要政府兜底,导致私有资本没有足够保护?
2. 10%固定回报 + 110%赎回溢价,是否足以补偿危机期信用风险?
3. 如果GE活下来,$22.25的权证是否提供足够的额外上行?
框架给出的答案是:**可以买,但只能以危机优先股结构买**。因为GE的工业皇冠资产、全球装机基础、长期服务合同和准系统重要性,足以支持“不会轻易归零”的判断;而高票息和优先索偿顺位,把这笔交易从“押GE股价”变成了“以极强保护换取可观上行”的结构化救助。
**对照组很关键**:
- **AIG**:同样是危机中心,但私营资本保护不足,最终只能依赖政府纾困,PASS
- **CIT Group**:融资模式更脆弱,特许经营价值也不够强,PASS
**评分(优先股角度)**:7.5/10 | **结论**:买入(危机优先股)
**实际结果**:2011年GE赎回优先股,Berkshire累计收到约$9亿股息;2013年权证现金less行权换得1071万股GE,整体为正回报,但明显不如GS/BAC | **判定**:✅
---
### #16 Tesco(2007)⭐
**买入**:2006–2007年开始建仓,最终累计成本约**$23亿** | **数据源**:Tesco FY2007 Annual Report
**关键数字(投资前可见)**:
- 营收**£426亿**,税前利润**£26.5亿**,归母净利润**£18.9亿**
- 2005–2007三年平均ROE约**24.9%** —— 表面上非常漂亮
- 经营现金流**£26.1亿**,但扣除资本开支和无形资产投入后,FCF仅约**£3.9亿**
- 净债务**£50亿**,并不危险;但企业价值已达**£404.7亿**
- earnings yield 只有约**4.7%**,低于框架要求的6%
- 毛利率从**7.7%→8.1%**,收入仍在增长,所以问题不是“当时已经明显衰退”,而是**看起来太好了**
**框架为什么说不投**:
1. **Gate ② fail**:会计利润很强,但自由现金流很弱。Tesco本质上要持续大额开店、改店、拿地、投物流和IT,资本开支吞掉了大部分利润
2. **Gate ⑥ fail**:以当时的企业价值看,这更像“优质零售龙头的满价买入”,不是有安全边际的便宜货
3. **Gate ⑦ fail**:超市客户的切换成本极低。Clubcard、规模、选址和供应链让Tesco执行更强,但不足以构成“10年内无法复制”的结构性护城河
这正是 Buffett 框架里很经典的一类陷阱:**高ROE + 高市场份额 + 强管理层**,很容易让人误以为它是“消费垄断”,但超市零售的底层经济学仍然是价格竞争、便利竞争和资本密集。
如果一个生意要不断投入巨额资本才能维持领先,而且客户明天就能去隔壁买同样的牛奶和面包,它就不是 Buffett 最喜欢的那类复利机器。
**对照组很关键**:
- **J Sainsbury**:恢复期零售商,估值和护城河都不足,PASS
- **Wm Morrison**:Safeway整合后遗症明显,同样缺乏真正的切换成本,PASS
**评分**:4.5/10 | **结论**:不投
**实际结果**:Tesco后续遭遇折扣零售冲击、市场份额流失与会计丑闻。巴菲特在2014年承认“巨大错误”,Berkshire最终录得约$4.44亿税后损失 | **判定**:⭐
---
### #17 American Express(1994)✅
**买入**:1994年继续加仓,1995年前后完成主要建仓,累计成本约**$13.6亿** | **数据源**:American Express 1993 Annual Report + 1994年Q3 10-Q + Berkshire 1994 shareholder letter
**关键数字(投资前可见)**:
- 1994年前九个月持续经营收入**$104.8亿**,持续经营净利润**$10.45亿**
- 核心Travel Related Services(TRS)前九个月净利润**$7.62亿**,同比增长**13%**
- 全球卡片账单额前九个月达到**$1019亿**,同比增长**13%**
- 1994年Q3全球流通卡数**3560万张**,商户覆盖**380万家**,仍在扩张
- Q3时American Express Bank不良贷款仅**$3300万**,总资本充足率约**13%**
- Berkshire在1994年报中披露,其AmEx持仓已接近**10%**;按当时市值估算,American Express大约是**10–11倍盈利**的价格
**框架为什么给 BUY**:
1. **这不是普通金融股,而是闭环支付网络**。AmEx的核心不是“放贷赚息差”,而是品牌、商户网络、卡会员习惯和商务差旅关系
2. **网络效应真实存在**:高消费客群吸引商户,商户接受度又反过来强化卡会员价值,这比单纯发卡银行更难复制
3. **业务质量在改善**:1992年启动的重组后,Lehman/FDC剥离让报表更干净;1994年前三季度里,账单额、卡数、商旅业务和TRS利润都在增长
4. **估值仍然合理**:按1994盈利能力看,市场并没有把AmEx当成“不可替代的全球网络资产”去定价
这里最关键的洞见是:**金融报表不等于金融本质**。
American Express看起来像一家金融公司,但其最值钱的部分其实更接近“高端消费品牌 + 支付网络平台 + 企业差旅基础设施”的复合护城河。这类公司不能简单和普通信用卡放贷机构混在一起看。
**对照组很关键**:
- **Sears / Discover**:支付业务嵌在更弱的零售母体里,护城河没有AmEx深,PASS
- **MBNA**:是优秀发卡/放贷公司,但更像资金驱动的信用生意,不是全球品牌网络,PASS
**评分**:8.5/10 | **结论**:买入
**实际结果**:American Express成为Berkshire最经典的长期复利仓位之一,持有数十年仍是核心重仓 | **判定**:✅
---
### #18 Dexter Shoe(1993)⭐
**买入**:1993年,以 Berkshire 股票作价约**$4.33亿**完成收购 | **数据源**:Berkshire 2014 special letter
**关键数字(投资前可见)**:
- 交易对价约**$4.33亿**
- Buffett 后来披露:如果当年用现金而不是 Berkshire 股票支付,代价会小得多;因为那些股票到 2014 年已值约**$57亿**
- 真正的问题不是买贵了,而是**看错了护城河**
**框架为什么说 PASS**:
1. **Gate ⑦ fail**:Dexter 没有足够深的结构性护城河来抵抗海外制造冲击
2. 这类生意最容易骗人:历史记录很好、管理层看起来优秀、报表也不难看,但如果行业壁垒不牢,全球供给变化就能直接摧毁经济性
3. Buffett 后来自己总结得很清楚:Dexter 的商业优势很快归零,而他用来支付的 Berkshire 股票却是极其宝贵的资产
**对照组很关键**:
- **Wolverine**:也是鞋业好公司,但同样面临护城河脆弱问题,PASS
- **Stride Rite**:品牌存在,但不足以对抗全球竞争压力,PASS
**评分**:3/10 | **结论**:不投
**实际结果**:成为 Buffett 最著名的失败案例之一,机会成本巨大 | **判定**:⭐
---
### #19 Wells Fargo(1991)✅
**买入**:1989–1990年危机中逐步建仓,1991年前后市场确认,累计成本约**$2.9亿** | **数据源**:Berkshire 1990 shareholder letter
**关键数字(投资前可见)**:
- Berkshire 买入价格对应**不到 5 倍税后利润**
- Wells Fargo 资产规模约**$560亿**
- Buffett 明确写道:这家银行一直在赚**20%+ ROE**和**1.25% ROA**
- 年税前利润**超过 $10亿**
**框架为什么给 BUY**:
1. **不是所有银行都值得买,但最好的银行在恐慌时值得下重手**
2. 高 ROE + 高 ROA 同时成立,本身就说明 Wells 不是单靠高杠杆赚钱,而是有真实经营优势
3. Buffett 当时的关键判断是:加州地产恐慌可能伤估值,但不太可能摧毁这家由 Carl Reichardt 和 Paul Hazen 管理的顶级银行 franchise
4. 价格又极便宜,形成了稀有的“优秀管理层 + 强 franchise + 恐慌定价”组合
**对照组很关键**:
- **BankAmerica**:同处加州,但不具备 Wells 那种管理与经济质量,PASS
- **Security Pacific**:同样暴露于市场恐慌,但 franchise 和管理质量不如 Wells,PASS
**评分**:8.5/10 | **结论**:买入
**实际结果**:成为 Berkshire 最经典的银行危机投资之一,长期大赢 | **判定**:✅
---
### #20 US Air(1989)⭐
**买入**:1989年,Berkshire 以**$3.58亿**买入9.25%可转优先股 | **数据源**:USAir 1988业绩披露 + Berkshire 1989/1995 shareholder letters
**关键数字(投资前可见)**:
- 1988年营收约**$57亿**,净利润约**$1.65亿**
- 1989年Q1营收约**$15亿**,营业利润约**$5770万**
- 证券条款看起来很诱人:**9.25%**票息,10年赎回,可按**$60/股**转换
- 但这些都是“证券结构好看”,不是“生意本身好看”
**框架为什么说 PASS**:
1. **Gate ⑦ fail**:航空公司没有可持续护城河。乘客按价格和时刻表选票,成本端却被油价、工会、航材和景气周期反复摆布
2. **优先股结构并不能修复坏行业**。9.25%票息只是在补偿你承受一个脆弱行业的风险,并没有把 USAir 变成好生意
3. **这类交易最容易让人误判**:因为它不像买普通股那样直接暴露估值错误,而是让投资人误以为“只要条款够好,就能豁免生意质量”
这条案例非常关键,因为它和 Goldman / BAC / GE 形成了反例:
**不是所有优先股结构都值得买。**
如果底层企业没有护城河、行业经济性又太差,那么“高票息+转换权”也可能只是把坏问题包装得更体面。
**对照组很关键**:
- **Eastern Air Lines**:更脆弱的同业,PASS
- **Pan Am**:同样没有护城河、财务更差,PASS
**评分**:3.5/10 | **结论**:不投
**实际结果**:USAir 后续一度停息、接近灾难。Berkshire 最终没有本金永久损失,但 Buffett 自己后来把这笔交易视为典型失误之一 | **判定**:⭐
---
### #21 Gillette(1989)✅
**买入**:1989年7月,Berkshire 买入**$6亿**8.75%可转优先股 | **数据源**:Gillette FY1988 annual report historical tables + Berkshire 1989/1995 shareholder letters
**关键数字(投资前可见)**:
- 1988年销售额约**$35.8亿**
- 1988年EBIT约**$6.51亿**,净利润约**$2.69亿**
- 长期债务约**$16.8亿**,但放在其盈利能力面前仍可承受
- 剃须刀与刀片业务拥有极强的重复消费与高毛利替换件经济学
- Sensor 新产品周期即将启动,意味着护城河不是静态防守,而是继续加深
**框架为什么给 BUY**:
1. **这是真正的消费品护城河**。消费者会主动指定 Gillette,不是买一个“便宜就行”的剃须工具
2. **替换刀片模型非常强**:装机在先,长期复购在后,既有品牌黏性也有使用惯性
3. **创新不是破坏护城河,而是在加厚护城河**。Sensor 代表的是更深的技术与营销协同,而不是一次性的噱头
4. **即使用了优先股结构,本质上押的仍然是卓越生意**,不是危机套利
这条案例和 US Air 正好相反:
表面上都是“优先股 / 可转结构”,但 Gillette 的底层是一家顶级消费品牌企业,所以结构只是**锦上添花**;US Air 的底层则是坏行业,所以结构只是**把风险后移**。
**对照组很关键**:
- **BIC**:有一定竞争力,但没有 Gillette 那么深的高端刀片系统和创新飞轮,PASS
- **Schick / Wilkinson Sword**:能竞争,但做不到同等强度的全球品牌、专利和安装基数,PASS
**评分**:8.5/10 | **结论**:买入
**实际结果**:成为 Berkshire 最成功的结构化股权投资之一;Buffett 后来甚至说,如果当时直接买普通股,结果会更好 | **判定**:✅
---
### #22 Coca-Cola(1988)✅
**买入**:1988年开始建仓,1989年前后完成主要买入,累计成本约**$10.2亿**(后续长期持有) | **数据源**:Coca-Cola FY1987 annual report historical data + Berkshire 1988/1989 shareholder letters
**关键数字(投资前可见)**:
- 1985–1987营收从约**$42亿 → $47亿 → $54亿**
- 1985–1987三年平均ROE约**23.9%**
- 1987净利润约**$10.5亿**
- 毛利率长期稳定在**约69%**,不是脆弱制造业利润,而是浓缩液+品牌经济学
- 净负债/资本约**5.3%**,杠杆极轻
- 按Berkshire 1988年买入成本推算,企业价值大约只给了**10%+ earnings yield**,远没把它当“世纪品牌资产”来定价
**框架为什么给 BUY**:
1. **Gate ① 直接通过**:长期高ROE,而且不是靠高杠杆硬撑出来的
2. **Gate ③ 非常舒服**:作为消费品牌龙头,资产负债表几乎没有给你制造麻烦
3. **Gate ④ / ⑤ 都非常干净**:收入增长、毛利率稳定,说明品牌定价权和浓缩液模式都在发挥作用
4. **Gate ⑦ 是教科书级通过**:消费者不是想喝“可乐味碳酸饮料”,而是明确想喝“Coke”;品牌、广告、渠道、瓶装系统和全球心智占领共同构成了真正不可复制的护城河
这类案例非常重要,因为它解释了 Buffett 最理想的一种生意:
**高品牌心智 + 轻资本核心环节 + 全球分销 + 几乎无限重复消费。**
市场在1988年看到的是一家成熟饮料公司;框架看到的是一台会在几十年里持续吐出现金、并且几乎不需要重新教育消费者的品牌复利机器。
**对照组很关键**:
- **PepsiCo**:也很强,甚至会通过大部分 gate;但它不是像 Coke 那样极致纯粹的全球软饮浓缩液资产,而是掺杂了更多业务结构
- **Coca-Cola Enterprises**:同一体系里的瓶装公司,却因为资本开支重、地方竞争更强、护城河更窄而应当 PASS
**评分**:9.5/10 | **结论**:强力买入
**实际结果**:成为 Berkshire 历史上最经典的复利仓位之一,股息与市值回报都属于“历史级大赢” | **判定**:✅
---
### #23 Capital Cities/ABC(1985)✅
**买入**:1985年,Berkshire 同意以**$172.50/股**买入 300 万股,总额约**$5.175亿** | **数据源**:Berkshire 1984/1986 shareholder letters
**关键数字(投资前可见)**:
- Berkshire 交易条款写得很清楚:**300 万股 × $172.50**
- Buffett 对 Tom Murphy 和 Dan Burke 的评价也写得很清楚:**ability and integrity 都是顶级**
- 后续更直接的验证来自 1986 年:Capital Cities/ABC 被列为 Berkshire 计划永久持有的三大核心之一
**框架为什么给 BUY**:
1. **这是一笔“卓越管理层 + 稀缺媒体资产”的结合体**
2. 电视和广播资产在当时高度稀缺,本身就带有准垄断/牌照价值
3. Buffett 极少如此反复强调管理层的能力和诚信,这往往意味着资本配置能力本身就是护城河的一部分
**对照组很关键**:
- **CBS**:同为优质媒体,但 operator quality 不如 Capital Cities 这组,PASS
- **Times Mirror**:也有好资产,但没有同等强度的 operator + asset 组合,PASS
**评分**:8.5/10 | **结论**:买入
**实际结果**:成为 Berkshire 非常成功的媒体投资之一 | **判定**:✅
---
### #24 Nebraska Furniture Mart(1983)✅
**买入**:1983年,Berkshire 收购多数股权,交易金额约**$6000万** | **数据源**:Berkshire 1984/1985/2013 annual reports
**关键数字(投资后很快可见)**:
- 1984 年 operating earnings 约**$1451万**
- 1985 年 operating earnings 约**$1269万**
- 即使农场经济很差,Buffett 仍写道门店**轻松刷新销售纪录**
**框架为什么给 BUY**:
1. **护城河是极端成本优势**,不是 fancy 品牌
2. Rose Blumkin 家族的经营文化本身就是资产,Buffett 甚至说从未见过运作更好、行为更好的管理层
3. 这类零售和 Tesco 完全不同:不是靠看起来体面的大卖场模型,而是靠真正低成本和强周转把对手耗死
**对照组很关键**:
- **Sears**:规模大但没有同等低成本文化,PASS
- **Levitz**:品类相近,却没有 NFM 那种结构性成本优势,PASS
**评分**:8.5/10 | **结论**:买入
**实际结果**:成为 Berkshire 最典型的 cost-advantage 私有企业之一 | **判定**:✅
---
### #25 Washington Post(1973)✅
**买入**:1973 年中开始建仓,累计成本约**$1060万** | **数据源**:Berkshire 1985/1986 shareholder letters
**关键数字(投资前可见)**:
- 市场给 Washington Post 的总市值只有约**$1亿**
- Buffett 写得很明确:懂行的人当时就会把它估成**$4亿–$5亿**
- 也就是说,这是一家优质媒体资产以**约四折以下**价格在市场上挂牌
**框架为什么给 BUY**:
1. **这是 Graham 折价和 Buffett 质量的罕见重叠**
2. 业务本身没坏,1973–1974 年 WPC 作为企业继续表现良好
3. 护城河来自本地媒体垄断、品牌信任和广告网络
**对照组很关键**:
- **New York Times**:质量高,但没有这么夸张的折价,PASS
- **Gannett**:也有媒体资产,但没有 Post 这笔交易的质量 + 价格组合,PASS
**评分**:9/10 | **结论**:买入
**实际结果**:成为 Berkshire 历史上最经典的价值投资案例之一 | **判定**:✅
---
### #26 See's Candies(1972)✅
**买入**:1972年,Blue Chip Stamps 以**$2500万**收购 See's Candies | **数据源**:Berkshire 2014 special letter
**关键数字(投资前可见)**:
- 当年税前利润约**$400万**
- 所需净有形资产仅约**$800万**
- 卖方最初要价**$3000万**,最终成交价**$2500万**
- 等于 Buffett 用约 3 倍有形资本、约 6.25 倍税前利润,买到一门几乎不需要继续重资产投入的品牌生意
**框架为什么给 BUY**:
1. **这是真正的品牌定价权**。消费者买的是 See's,不是“散装糖果”
2. **资本开支极轻**:核心竞争力在品牌、门店习惯和节庆礼赠心智,而不是不断砸设备
3. **回报率高得惊人**:$800万净有形资产就能支撑 $400万税前利润,这是 Buffett 梦寐以求的经济模型
4. **最重要的意义不只是赚钱,而是方法论转折**:这笔交易帮助 Buffett 从“便宜资产”真正转向“伟大企业”
**对照组很关键**:
- **Whitman's**:品类相近,但没有 See's 那种区域文化级别的品牌势能,PASS
- **Fanny Farmer**:同属糖果零售,但经济质量和护城河都不够深,PASS
**评分**:9.5/10 | **结论**:强力买入
**实际结果**:成为 Berkshire 方法论最重要的转折性成功案例之一;Buffett 后来披露其累计税前利润约**$19亿**,而额外投入资本只有约**$4000万** | **判定**:✅
---
### #28 National Indemnity(1967)✅
**买入**:1967年,Berkshire 以**$860万**买下 National Indemnity 和一家小型姊妹公司 | **数据源**:Berkshire 2017 annual report + 2014 special letter
**关键数字(投资前可见)**:
- 支付价格**$860万**
- 收购时有形净资产约**$670万**
- 同时附带保险 float 约**$1940万**
- 换句话说,Buffett 只多付了约**$190万**溢价,就拿到一家通常还能实现承保利润的保险公司和一大笔可投资资金
**框架为什么给 BUY**:
1. **保险 float 是隐藏的超级杠杆**,但前提是承保纪律不能烂
2. **National Indemnity 的关键不是规模,而是文化**:承保保守、愿意放弃不合理价格的保费
3. **买入价格极好**:付出的是略高于净资产的价格,得到的却是一个能反复提供低成本资金的机器
4. **这不是普通公司收购,而是 Berkshire 整个资本配置系统的起点**
**对照组很关键**:
- **Travelers**:大型保险商,但没有这笔交易这么优的购买条款,PASS
- **Aetna Casualty**:也是好公司,但并未以这种“低溢价净资产 + 巨额 float”方式摆在 Buffett 面前,PASS
**评分**:9/10 | **结论**:买入
**实际结果**:成为 Berkshire 保险飞轮的起点。后来的全部复利故事,很大一部分都建立在这次收购提供的 float 之上 | **判定**:✅
---
### #27 GEICO(1976)✅
**买入**:1976 年危机中逆向买入,后续持续加仓并最终并入 Berkshire 核心版图 | **数据源**:Berkshire 1985/1986 shareholder letters
**关键数字(后续验证到的 franchise 强度)**:
- 1986 年 premium volume 已超过**$5亿**
- combined ratio **96.9**
- underwriting expense + loss adjustment expense ratio 仅**23.5%**
- Buffett 直接把这种成本差称为**moat around the castle**
**框架为什么给 BUY**:
1. **GEICO 的核心是成本优势,不是短期报表**
2. 即使公司一度接近破产,只要真正的护城河还在,修复资本结构后就有机会重回高质量复利
3. Buffett 后来明确说,Jack Byrne 把 GEICO 从 near-bankruptcy 拉回来的成绩极其卓越,而 Berkshire 因此获得了巨大收益
**对照组很关键**:
- **Allstate**:规模大,但成本结构不如 GEICO,PASS
- **Travelers**:重要保险公司,但在 auto 直销经济学上不如 GEICO,PASS
**评分**:8.5/10 | **结论**:买入
**实际结果**:成为 Berkshire 最重要的保险和公开股票投资之一,历史级大赢 | **判定**:✅
---
### #29 Berkshire Hathaway纺织(1965)⭐
**买入**:1962–1965年逐步买入并取得控制权 | **数据源**:Berkshire 2014 special letter + Berkshire 1972/1976 shareholder letters
**关键数字(投资前可见)**:
- 1962年股价约**$7.50/股**
- 每股营运资本约**$10.25**
- 每股账面价值约**$20.20**
- 看起来非常便宜,典型 cigar-butt
- 但到1964年底,公司净资产约**$2200万**,还欠银行约**$250万**,没有真正多余的资本可以抽走
**框架为什么说 PASS**:
1. **Gate ④ fail**:行业长期结构性下行。连 1954 年董事会记录都承认,新英格兰纺织业的大方向在恶化
2. **Gate ⑤ fail**:回报率长期糟糕,后续 Buffett 自己也承认 return on sales 和 return on capital 都不合格
3. **Gate ⑦ fail**:完全没有护城河,纯粹是成本导向的商品制造
4. **“便宜”不等于“值得买”**:如果所有资本都会被烂生意持续吞掉,那么低于营运资本买入也未必能创造好结果
这是整个 Buffett 框架里最值得刻在门上的一课:
**不要因为便宜就接手一个坏行业。**
如果生意本身持续恶化、没有定价权、没有护城河、还需要反复吞资本,那么所谓安全边际往往只是幻觉。
**对照组很关键**:
- **J.P. Stevens**:同样的纺织泥潭,PASS
- **Burlington Industries**:更大也没用,依然逃不出行业结构问题,PASS
**评分**:2/10 | **结论**:不投
**实际结果**:最终成为 Buffett 自己口中的“最大错误”之一,纺织业务在 1985 年彻底关闭 | **判定**:⭐
---
## Benchmark 队列
当前 29-case benchmark 已完成。
但这不代表 Buffett / Berkshire 的全部投资历史已经建库完成。后续如果扩容,应新增到更大的 universe 层,而不是假装这 29 条就是全集。
---
## 阶段性结论(基于已完成的 29-case benchmark)
**回顾一致性**:29案例中,框架与最终结果一致29次(⭐×9 + ✅×20,其中⭐是超越巴菲特)
**框架识别出的巴菲特失误**:
1. Paramount — 表外负债+FCF与利润背离
2. Airlines 2016 — 大宗商品行业无护城河
3. Precision Castparts — 周期性峰值估值过高
4. IBM — 营收停滞被回购掩盖
5. Kraft Heinz — 旧品牌老化被“品牌组合”幻觉掩盖
6. Tesco — 高ROE零售龙头也可能没有真正护城河,资本开支与低切换成本会吞掉复利
7. US Air — 结构再好的优先股,也救不了没有护城河的坏行业
8. Berkshire纺织 — 低于营运资本的便宜货,也可能只是资本黑洞
9. Dexter Shoe — 历史记录优秀不等于护城河坚固,全球竞争可以直接抹掉全部价值
**框架总结出的规律**:
- **危机优先股**(GS/OXY/BAC/GE)= 另一套逻辑,不用普通股护城河框架,而是用"不易归零 + 高票息补偿 + 权证上行"框架
- **成长例外**(BYD)= 只能在ROIC/技术壁垒/估值同时成立时使用,否则极易沦为讲故事
- **护城河必须持久**:航空/媒体的"护城河"是租来的(航班时刻/内容版权),会消失
- **FCF ≠ 净利润** = 最重要的单一指标,差距越大越危险
- **周期性业务的估值** = 要用穿越周期的正常化利润,绝不能用峰值利润
- **零售规模 ≠ 护城河**:商超龙头可以执行优秀,但如果客户切换成本低、资本开支重,长期并不符合Buffett理想型
- **金融外壳 ≠ 普通金融股**:AmEx这类闭环网络资产,本质更接近品牌+网络效应平台,不应和纯资金中介混为一谈
- **真正的品牌资产极其罕见**:Coca-Cola这类案例说明,一旦“消费者主动点名购买”与全球渠道绑定同时成立,框架会给出最高等级的 BUY
- **结构化证券不是免死金牌**:Gillette 之所以成功,是因为底层生意本就卓越;US Air 之所以糟糕,是因为证券结构无法掩盖行业烂经济学
- **float 是 Berkshire 的原点**:National Indemnity 说明,买到“承保不亏钱的低成本资金来源”时,复利机器会被彻底改写
- **伟大企业比便宜资产重要**:See's 和 Berkshire 纺织正好是一正一反,几乎可以当这套框架的总纲
- **真正伟大的媒体/金融 franchise 在恐慌中最值钱**:Washington Post、Capital Cities、Wells Fargo、GEICO 都说明,恐慌不是风险本身,前提是你先确认 moat 真的存在
FILE:gate_review.md
# Buffett Oracle — Gate Review
*Last updated: 2026-03-26*
## Why This Exists
Backtest accuracy headlines are not enough.
The more important question is: **which gates are filtering real junk, and which gates are systematically causing false negatives?**
Generate the live snapshot with:
```bash
python3 oracle.py gate-review
```
## Current Reading
Across the current archived set, the false negatives are not evenly distributed.
They cluster around two gates:
- `Gate 2 (FCF / Net Income)`
- `Gate 6 (Earnings Yield)`
The current expansion-track false negatives are:
- `PTR_2003.json`
- `WMT_2005.json`
- `BUD_2005.json`
- `MCO_2001.json`
- `COST_1999.json`
- `DVA_2011.json`
Those misses imply:
1. `Gate 2` is too blunt when raw free cash flow is depressed by **value-creating reinvestment** rather than by weak economics.
2. `Gate 6` is too blunt when a business is an **elite asset-light tollbooth** or a **dense recurring-service oligopoly** and the market persistently pays up for that quality.
As of the current archive snapshot:
- `Framework-wrong cases`: `6`
- `Gate 2` false-negative hits: `3`
- `Gate 6` false-negative hits: `4`
## Gate-by-Gate View
### Gate 1 — Normalized ROE / ROIC
No current evidence says this hurdle is causing false negatives.
Keep it hard.
### Gate 2 — FCF / Net Income
This gate is useful, but the raw version confuses two things:
- bad cash conversion
- heavy but productive reinvestment
Going forward, every `Gate 2` fail should include an **owner earnings note**:
- What portion of capex looks maintenance-like?
- What portion looks like expansion capex that may still create value?
- Is the business still genuinely capital hungry even after that adjustment?
### Gate 3 — Leverage
No current false negatives are coming from this gate.
Balance-sheet discipline remains non-negotiable.
### Gate 4 — Structural Revenue Decline
This gate still looks sensible.
It is not currently the source of false negatives.
### Gate 5 — Gross Margin Trend
This is a secondary deterioration check, not a primary stock picker.
Low signal, but not obviously broken.
### Gate 6 — Earnings Yield
The current `6%` floor is a conservative default, not a law of nature.
It is missing some businesses where:
- moat quality is exceptional
- incremental capital needs are low
- balance-sheet risk is low
- the business sits inside market infrastructure, category leadership, or a recurring-service oligopoly with durable local density
Going forward, every `Gate 6` fail on a clear-moat business should include a **quality multiple note**:
- Is the market paying for genuine durability or for hype?
- Is the low yield justified by asset-light compounding?
- Is this a strategic-buyer story, a compounding story, a recurring-service density story, or just overpayment?
### Gate 7 — Moat
This remains the strongest qualitative gate.
So far it is rejecting weak businesses without showing up as a clear source of false negatives.
## Operating Rule
For now, the project keeps the 7 hard gates unchanged so the benchmark remains comparable over time.
But new live and expansion memos should now do two extra checks:
1. Add an **owner earnings note** whenever `Gate 2` fails.
2. Add a **quality multiple note** whenever `Gate 6` fails on a high-moat business.
FILE:README.md
# Buffett Oracle
A collaborative framework for applying Warren Buffett's investment thinking to real companies — built with Claude Code, improved by the community.
---
## What This Is
A structured process for analyzing companies the way Buffett does:
1. **Hard gates** — 7 quantitative filters that auto-reject bad businesses
2. **Moat analysis** — qualitative assessment of competitive advantages
3. **Control groups** — every BUY must explain why comparable companies were rejected
4. **Binary output** — BUY or PASS, no hedging
5. **Point-in-time discipline** — use only data available at the decision date; later facts are for the reveal only
6. **Graham operating layer** — separate investment from speculation, default to defensive-investor logic, and prefer valuation over timing calls
The framework runs inside Claude Code. Each analysis is stored as a `company_card` so future analyses can reference past work without re-reading 10-Ks. The local `oracle.py` helper now also audits repo consistency so cards, docs, and backtest summaries do not drift apart.
Important scope note: the current repo covers a **curated 29-case benchmark set**, not the full Buffett/Berkshire investment universe. See [coverage_scope.md](coverage_scope.md).
Additional non-benchmark cases now live in a separate [universe_expansion.md](universe_expansion.md) track so new research does not pollute the benchmark hit-rate.
---
## What This Is NOT
- Not investment advice
- Not a trading bot
- Not a model being trained (Claude's weights don't change — only the framework and knowledge base evolve)
- Not a claim that Buffett only made 29 investments
---
## Quick Start
```bash
# 1. Clone
git clone https://github.com/your-username/buffett-oracle
cd buffett-oracle
# 2. Validate local repo state
python3 oracle.py status
python3 oracle.py validate
python3 oracle.py methodology
python3 oracle.py gate-review
# 3. Open in Claude Code
claude .
# Claude will automatically read CLAUDE.md and know what to do
# Then just say: "Analyze Coca-Cola 1988"
```
Requirements: [Claude Code](https://claude.ai/code) with SEC EDGAR web access.
## Website
This repo now ships with a zero-dependency static website.
```bash
# Build the public site into docs/
python3 oracle.py site --site-url https://your-domain.example
# Preview locally
python3 oracle.py serve-site --port 8000
```
The generated site includes:
- A chat-first Buffett Oracle landing page with one central question box
- Natural-language routing for company lookups, framework questions, asset-allocation prompts, and queue/progress questions
- A searchable backtest explorer backed by `company_cards/`
- A visible benchmark queue when the selected case set is not yet complete
- A methodology audit so the headline score is shown with its caveats
- Shareable metadata, manifest, robots, sitemap, favicon, and social preview assets for public publishing
## Sell / Marketplace
This repo can now generate a sellable bundle in three formats: raw files, a standalone skill folder, and a Codex plugin catalog.
```bash
python3 oracle.py marketplace-bundle
```
Artifacts are written to `dist/clawmart/`:
- `listing-copy.md` — paste-ready listing copy
- `publish-checklist.md` — upload checklist and scope caveats
- `package/buffett-oracle/` — buyer-facing raw files bundle
- `skill/buffett-oracle/` — standalone skill folder with `SKILL.md` and `agents/openai.yaml`
- `plugin-catalog/` — Codex-ready plugin catalog containing `.agents/plugins/marketplace.json`
- `buffett-oracle-clawmart-v<framework>.zip` — raw-files upload package
- `buffett-oracle-skill-v<framework>.zip` — standalone skill install zip
- `buffett-oracle-codex-plugin-v<framework>.zip` — Codex plugin install zip
The seller kit keeps the same research core across all three delivery formats: `SKILL.md`, `agents/openai.yaml`, the portable `buffett-oracle.md` prompt, framework files, cached `company_cards/`, and the repo helper CLI. It also keeps the curated-benchmark scope note in every package so marketplace listings do not accidentally overclaim coverage.
## Publish
If this repo is pushed to GitHub, the included workflow at `.github/workflows/deploy-pages.yml` will build `docs/` and deploy to GitHub Pages.
Typical flow:
```bash
git add .
git commit -m "Publish Buffett Oracle website"
git push origin main
```
Then enable **Settings → Pages → Build and deployment → GitHub Actions** in the GitHub repo.
For GitHub Pages project sites, the workflow will automatically build with:
```bash
python3 oracle.py site --site-url https://<owner>.github.io/<repo>
```
---
## Repo Structure
```
buffett-oracle/
├── agents/openai.yaml ← Skill UI metadata for Codex/OpenAI-compatible loaders
├── assets/ ← Brand assets reused by skill/plugin bundles
├── CLAUDE.md ← Instructions for Claude Code (read this)
├── buffett_brain.md ← The framework: Buffett + Graham overlay + 7 hard gates
├── backtest_results.md ← All completed analyses
├── analysis_index.json ← Canonical map from backtest rows to company cards
├── universe_expansion.md ← Separate non-benchmark expansion cases
├── universe_expansion_index.json ← Card map for expansion cases
├── buffett_investment_universe.md ← Working registry beyond current audited cards
├── methodology_audit.md ← Why the headline score is not true predictive accuracy
├── gate_review.md ← Which hard gates are helping vs. misfiring
├── coverage_scope.md ← What the 29-case benchmark does and does not cover
├── oracle.py ← CLI helper
├── site/ ← Static site source files
├── docs/ ← Generated website ready for GitHub Pages
├── company_cards/ ← Pre-extracted hard gate numbers per company
│ ├── _schema.json ← Card format definition
│ └── *.json ← One card per analyzed company/year
└── raw_data/ ← Raw 10-K extracts (gitignored by default)
```
---
## How to Contribute
See [CONTRIBUTING.md](CONTRIBUTING.md).
**Short version:**
1. Pick an unanalyzed case from `backtest_results.md`
2. Read the 10-K (or equivalent annual report)
3. Run the analysis in Claude Code following `CLAUDE.md`
4. Save the company card to `company_cards/`
5. Append results to `backtest_results.md`
Or, for non-benchmark cases, append to `universe_expansion.md`
6. Open a PR
---
## Current Progress
| Completed | Framework Version | Methodology Snapshot |
|---|---|---|
| 29 / 29 benchmark cases | v1.2 | 29/29 retrospective consistency; 3 ambiguous, 6 exceptions |
| 29 / 29 expansion cases | v1.2 | separate universe track; excluded from benchmark methodology math |
See `backtest_results.md` for benchmark details and `universe_expansion.md` for the broader universe track. For a stricter breakdown, run `python3 oracle.py methodology` and read `methodology_audit.md`. For gate-level reflection, run `python3 oracle.py gate-review` and read `gate_review.md`. For the scope boundary, read `coverage_scope.md`.
---
## Known Limitations
- **Hindsight bias**: We know outcomes before analyzing. Partially mitigated by hard gates + control groups, but not fully solvable.
- **Selection bias**: We only test companies Buffett invested in. Control groups partially address this.
- **Framework flexibility**: Qualitative moat analysis still has subjectivity.
We document these honestly. Any contributor claiming "100% accuracy, no bias" is lying.
FILE:universe_expansion_index.json
{
"_description": "Separate universe-expansion mapping. These rows are not part of the 29-case benchmark hit-rate.",
"rows": [
{ "id": 1, "target": "PetroChina", "decision_year": 2004, "status": "completed", "cards": ["PTR_2003.json"], "card_required": true },
{ "id": 2, "target": "ConocoPhillips", "decision_year": 2008, "status": "completed", "cards": ["COP_2007.json"], "card_required": true },
{ "id": 3, "target": "Lubrizol", "decision_year": 2011, "status": "completed", "cards": ["LZ_2010.json"], "card_required": true },
{ "id": 4, "target": "M&T Bank", "decision_year": 2000, "status": "completed", "cards": ["MTB_2000.json"], "card_required": true },
{ "id": 5, "target": "Johnson & Johnson", "decision_year": 2007, "status": "completed", "cards": ["JNJ_2007.json"], "card_required": true },
{ "id": 6, "target": "Anheuser-Busch", "decision_year": 2005, "status": "completed", "cards": ["BUD_2005.json"], "card_required": true },
{ "id": 7, "target": "Wal-Mart Stores", "decision_year": 2005, "status": "completed", "cards": ["WMT_2005.json"], "card_required": true },
{ "id": 8, "target": "U.S. Bancorp", "decision_year": 2006, "status": "completed", "cards": ["USB_2006.json"], "card_required": true },
{ "id": 9, "target": "Moody's Corporation", "decision_year": 2001, "status": "completed", "cards": ["MCO_2001.json"], "card_required": true },
{ "id": 10, "target": "H&R Block", "decision_year": 2002, "status": "completed", "cards": ["HRB_2002.json"], "card_required": true },
{ "id": 11, "target": "Costco", "decision_year": 2000, "status": "completed", "cards": ["COST_1999.json"], "card_required": true },
{ "id": 12, "target": "Disney", "decision_year": 2000, "status": "completed", "cards": ["DIS_1999.json"], "card_required": true },
{ "id": 13, "target": "DaVita", "decision_year": 2012, "status": "completed", "cards": ["DVA_2011.json"], "card_required": true },
{ "id": 14, "target": "Nucor", "decision_year": 2000, "status": "completed", "cards": ["NUE_1999.json"], "card_required": true },
{ "id": 15, "target": "Merck & Co.", "decision_year": 2020, "status": "completed", "cards": ["MRK_2019.json"], "card_required": true },
{ "id": 16, "target": "AbbVie", "decision_year": 2020, "status": "completed", "cards": ["ABBV_2019.json"], "card_required": true },
{ "id": 17, "target": "Bristol-Myers Squibb", "decision_year": 2020, "status": "completed", "cards": ["BMY_2019.json"], "card_required": true },
{ "id": 18, "target": "Pfizer", "decision_year": 2020, "status": "completed", "cards": ["PFE_2019.json"], "card_required": true },
{ "id": 19, "target": "Barrick Gold", "decision_year": 2020, "status": "completed", "cards": ["GOLD_2019.json"], "card_required": true },
{ "id": 20, "target": "Amazon.com", "decision_year": 2020, "status": "completed", "cards": ["AMZN_2019.json"], "card_required": true },
{ "id": 21, "target": "Biogen", "decision_year": 2020, "status": "completed", "cards": ["BIIB_2019.json"], "card_required": true },
{ "id": 22, "target": "Charter Communications", "decision_year": 2020, "status": "completed", "cards": ["CHTR_2019.json"], "card_required": true },
{ "id": 23, "target": "Kroger", "decision_year": 2020, "status": "completed", "cards": ["KR_2020.json"], "card_required": true },
{ "id": 24, "target": "Marsh & McLennan", "decision_year": 2020, "status": "completed", "cards": ["MRSH_2019.json"], "card_required": true },
{ "id": 25, "target": "Mastercard", "decision_year": 2020, "status": "completed", "cards": ["MA_2019.json"], "card_required": true },
{ "id": 26, "target": "Mondelez International", "decision_year": 2020, "status": "completed", "cards": ["MDLZ_2019.json"], "card_required": true },
{ "id": 27, "target": "Procter & Gamble", "decision_year": 2020, "status": "completed", "cards": ["PG_2020.json"], "card_required": true },
{ "id": 28, "target": "RH", "decision_year": 2020, "status": "completed", "cards": ["RH_2020.json"], "card_required": true },
{ "id": 29, "target": "Verizon Communications", "decision_year": 2020, "status": "completed", "cards": ["VZ_2019.json"], "card_required": true }
]
}
FILE:buffett-oracle.md
You are Buffett Oracle, a point-in-time investment analyst built around Warren Buffett's decision logic.
Use the bundled files as your evidence base:
- `buffett_brain.md` for the full framework
- `backtest_results.md` for the audited benchmark archive
- `coverage_scope.md` for what the benchmark does and does not cover
- `methodology_audit.md` and `gate_review.md` for caveats
- `company_cards/` for cached company facts that should be reused instead of re-fetched
Your job is not to hype stocks. Your job is to decide whether a target should be a **BUY** or **PASS** under this framework.
If the user asks for personalized financial advice, remind them this is a research framework, not individualized investment advice.
---
## Scope Rule
The benchmark archive is a **curated 29-case set**, not Buffett or Berkshire's full investment history.
Do not imply that:
- the 29 indexed rows are exhaustive
- retrospective consistency equals forward predictive accuracy
- this framework is a trading bot
---
## Pre-Analysis Classification
Before doing any gate work, classify the request as one of:
- `INVESTMENT`: thorough analysis, principal safety, adequate return
- `SPECULATION`: depends on momentum, sentiment reversal, or multiple expansion
- `TOO_HARD`: outside the framework's competence
If the answer is `SPECULATION` or `TOO_HARD`, explain why and stop.
---
## Non-Negotiable Rule
Use only information that was publicly available on or before the decision date.
Do not use later earnings, later commentary, or later outcomes to justify the original decision.
Post-decision facts belong only in the final reveal.
---
## Workflow
### 1. Check cache first
If `company_cards/<TICKER>_<YEAR>.json` already exists, load it and reuse it.
Do not re-fetch a company that already has a cached card.
### 2. Run the 7 hard gates
Apply all seven gates from `buffett_brain.md`.
If any gate fails, default to `PASS` immediately unless a named exemption explicitly applies.
Hard gates:
1. Normalized ROE / ROIC < 12% (3-year average, excluding one-time items)
2. FCF / Net Income < 0.8
3. Net Debt / EBITDA > 4x
Banks: Tier 1 Capital < 8%
4. Structural revenue decline
5. Gross margin declining 2+ consecutive years
6. Earnings yield (Net Income / EV) < 6%
7. Moat test fails
### 3. Named exemptions
Only three named exemptions exist, and each must be stated explicitly:
- `CRISIS_PREFERRED`
Use for Goldman 2008 / BAC 2011 / GE 2008 style preferred + warrant structures.
- `INFRA_EXEMPTION`
Use for rail or utility monopolies when EV / EBITDA < 15x and monopoly status is clear.
- `GROWTH_EXCEPTION`
Use only when ROIC > 20%, earnings yield still passes, and weak raw FCF reflects value-creating expansion.
### 4. Required overlays when triggered
- If Gate 2 fails but moat still looks real, add an owner-earnings note.
- If Gate 6 fails but moat still looks real, add a quality-multiple note.
- For live and expansion cases, include a management veto status: `clear`, `watch`, or `fail`.
### 5. Moat analysis
If the gates do not reject the company, answer:
Can you explain in one paragraph why competitors cannot replicate this business in 10 years?
If no, or not with confidence, the answer is `PASS`.
### 6. Control group
Every `BUY` must include two comparable companies from the same industry and era that Buffett did not buy.
Apply the same gates to them.
If the control companies also pass, explain the differentiator.
### 7. Lock conclusion before reveal
Write `BUY` or `PASS` before revealing what Buffett actually did.
Do not change the conclusion after the reveal.
---
## Output Format
Use this structure:
```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CLASSIFICATION: [INVESTMENT / SPECULATION / TOO HARD]
VERDICT: [BUY / PASS]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Hard Gates: [all passed / gate failed / exemption applied]
Named Exemption: [CRISIS_PREFERRED / INFRA_EXEMPTION / GROWTH_EXCEPTION / none]
Moat Type: [brand / network / switching cost / cost advantage / none]
Safety Margin: [owner's earnings, value range, required return, implied discount]
Key Conviction: [one sentence]
Key Risk: [one sentence]
Control Group: [Company A — PASS (gate N) | Company B — PASS (gate N)]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
Then reveal:
- what Buffett actually did
- what happened afterward
- whether the framework and Buffett agreed
---
## What This Product Includes
- Framework version: `v1.2`
- Benchmark archive: `29 / 29` curated cases completed
- Expansion archive: `29 / 29` separate-track cases completed
- Cached company cards: `58`
Those numbers are evidence of archive completeness, not a promise of future hit rate.
This is a disciplined research process, not investment advice.
FILE:coverage_scope.md
# Buffett Oracle — Coverage Scope
*Last updated: 2026-03-25*
## Core Scope
The current repo is **not** a full history of Buffett/Berkshire investments.
It is a **curated 29-case benchmark set** chosen to stress-test the framework across:
- common-stock wins
- common-stock mistakes
- crisis preferred deals
- private-company acquisitions
- early Berkshire capital-allocation turning points
The purpose of this set is methodological:
- force point-in-time underwriting
- compare BUY vs PASS logic across different deal types
- expose where the framework overfits, hedges, or cheats
## What The 29 Cases Are Not
The benchmark set does **not** claim to include:
- every Berkshire public-equity position
- every addition or trim to an existing position
- every wholly owned acquisition
- every preferred, warrant, arbitrage, or financing deal
- every non-U.S. holding
- every short-lived or small historical position
So `29 / 29` means:
- `29 / 29 benchmark cases completed`
It does **not** mean:
- `29 / 29 of Buffett's real investment history`
## Expansion Tracks
If the project grows beyond the benchmark set, new coverage should be added as separate layers:
1. **Public equity universe**
Add major Berkshire common-stock positions not yet benchmarked.
Current file: `universe_expansion.md`
Working broader name registry:
`buffett_investment_universe.md`
2. **Wholly owned acquisitions**
Add major private-company deals with source-backed point-in-time memos.
3. **Structured / special situations**
Preferreds, warrants, rescue financings, arbitrage, and hybrid deals.
4. **Position management history**
Adds, trims, exits, and re-entries should be tracked separately from the original buy memo.
## Guardrail
Never present the benchmark set as if it were the total Buffett/Berkshire universe.
If a user asks "how many investments did Buffett make?", the honest answer is:
- far more than 29
- this repo currently audits only a selected benchmark subset
- the broader company/entity registry now starts in `buffett_investment_universe.md`
FILE:oracle.py
#!/usr/bin/env python3
"""
Buffett Oracle — Repo Helper
Usage:
python3 oracle.py # 显示项目状态
python3 oracle.py status # 显示项目状态
python3 oracle.py validate # 校验 company_cards / README / backtest 一致性
python3 oracle.py backtest # 重新汇总并输出当前回测结果
python3 oracle.py site # 生成可静态部署的网站到 docs/
python3 oracle.py serve-site # 本地预览网页版本
python3 oracle.py marketplace-bundle # 生成 Claw Mart / marketplace 销售包
python3 oracle.py cards # 列出已缓存 company cards
python3 oracle.py pending # 列出待分析案例
python3 oracle.py methodology # 审计方法论质量与高胜率成因
python3 oracle.py gate-review # 审计 7 个 hard gates 在回测中的误伤与有效性
python3 oracle.py show <query> # 查看某张 company card
python3 oracle.py brain # 查看大脑内容
python3 oracle.py corpus # 浏览可用语料
python3 oracle.py learn <file> # 从语料文件提炼新知识(生成提示词)
python3 oracle.py evolve # 手动添加一条新原则
"""
from __future__ import annotations
import argparse
import datetime
import functools
import http.server
import json
import os
import re
import shutil
import socketserver
import sys
import zipfile
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
BASE_DIR = Path(__file__).resolve().parent
BRAIN_FILE = BASE_DIR / "buffett_brain.md"
BACKTEST_FILE = BASE_DIR / "backtest_results.md"
README_FILE = BASE_DIR / "README.md"
ANALYSIS_INDEX_FILE = BASE_DIR / "analysis_index.json"
EXPANSION_FILE = BASE_DIR / "universe_expansion.md"
EXPANSION_INDEX_FILE = BASE_DIR / "universe_expansion_index.json"
GATE_REVIEW_FILE = BASE_DIR / "gate_review.md"
CARDS_DIR = BASE_DIR / "company_cards"
SITE_SRC_DIR = BASE_DIR / "site"
SITE_OUTPUT_DIR = BASE_DIR / "docs"
DIST_DIR = BASE_DIR / "dist"
MARKETPLACE_OUTPUT_DIR = DIST_DIR / "clawmart"
CORPUS_DIR = Path(os.environ.get("BUFFETT_CORPUS_DIR", Path.home() / "Documents/warren-buffet"))
SITE_TEMPLATE_SUFFIXES = {".html", ".txt", ".xml", ".svg", ".webmanifest"}
MARKETPLACE_PACKAGE_SLUG = "buffett-oracle"
MARKETPLACE_HOMEPAGE = "https://github.com/yixiao1032-publish/buffet-oracle"
MARKETPLACE_REPOSITORY = f"{MARKETPLACE_HOMEPAGE}.git"
MARKETPLACE_AUTHOR_NAME = "Buffett Oracle"
MARKETPLACE_PLUGIN_CATALOG_NAME = "buffett-oracle-catalog"
MARKETPLACE_PLUGIN_CATEGORY = "Finance / Research"
MARKETPLACE_PLUGIN_CAPABILITIES = ("Read", "Write")
MARKETPLACE_INCLUDED_PATHS = (
"SKILL.md",
"agents",
"assets",
"buffett-oracle.md",
"CLAUDE.md",
"README.md",
"buffett_brain.md",
"backtest_results.md",
"coverage_scope.md",
"methodology_audit.md",
"gate_review.md",
"analysis_index.json",
"universe_expansion.md",
"universe_expansion_index.json",
"oracle.py",
"company_cards",
)
MARKETPLACE_PREVIEW_ASSETS = ("docs/social-card.svg", "docs/favicon.svg")
MARKETPLACE_WORKS_WITH = ("Codex Plugins", "OpenClaw", "Raw Files", "Claude Projects", "Custom GPTs", "Cursor")
TOP_LEVEL_REQUIRED_KEYS = {
"ticker",
"company",
"analysis_year",
"data_source",
"analyzed_date",
"hard_gates",
"control_groups",
"conclusion",
"buffett_action",
"actual_result",
"verdict",
"key_insight",
}
HARD_GATE_KEYS = {
"g1_roe_roic",
"g2_fcf_to_ni",
"g3_leverage",
"g4_revenue_trend",
"g5_gross_margin_trend",
"g6_earnings_yield",
"g7_moat",
}
ALLOWED_SPECIAL_CHANNELS = {
None,
"CRISIS_PREFERRED",
"INFRA_EXEMPTION",
"GROWTH_EXCEPTION",
}
ALLOWED_MANAGEMENT_VETO_STATUSES = {"clear", "watch", "fail"}
ALLOWED_BUY_FAILURES = {
"CRISIS_PREFERRED": {"g1_roe_roic", "g2_fcf_to_ni", "g3_leverage", "g6_earnings_yield"},
"INFRA_EXEMPTION": {"g6_earnings_yield"},
"GROWTH_EXCEPTION": {"g1_roe_roic", "g2_fcf_to_ni"},
}
BACKTEST_CORRECT_SYMBOLS = {"✅", "⭐"}
BACKTEST_SCORED_SYMBOLS = {"✅", "⭐", "❌"}
GATE_METADATA = [
{
"key": "g1_roe_roic",
"label": "Gate 1",
"title": "Normalized ROE / ROIC",
"rule": "3-year average must be at least 12%, excluding one-time items.",
},
{
"key": "g2_fcf_to_ni",
"label": "Gate 2",
"title": "FCF / Net Income",
"rule": "Cash conversion must be at least 0.8x.",
},
{
"key": "g3_leverage",
"label": "Gate 3",
"title": "Leverage",
"rule": "Net Debt / EBITDA must be at most 4x. Banks use Tier 1 capital instead.",
},
{
"key": "g4_revenue_trend",
"label": "Gate 4",
"title": "Structural Revenue Trend",
"rule": "Cyclical weakness is allowed; structural decline is not.",
},
{
"key": "g5_gross_margin_trend",
"label": "Gate 5",
"title": "Gross Margin Trend",
"rule": "Two or more consecutive years of decline fail the gate.",
},
{
"key": "g6_earnings_yield",
"label": "Gate 6",
"title": "Earnings Yield",
"rule": "Net Income / Enterprise Value must be at least 6%, unless a named exception applies.",
},
{
"key": "g7_moat",
"label": "Gate 7",
"title": "Moat Test",
"rule": "You must be able to explain why competitors cannot replicate the business in 10 years.",
},
]
@dataclass
class ValidationResult:
errors: list[str] = field(default_factory=list)
warnings: list[str] = field(default_factory=list)
@dataclass
class CardRecord:
path: Path
payload: dict[str, Any]
validation: ValidationResult
@property
def ticker(self) -> str:
return str(self.payload.get("ticker", self.path.stem.split("_")[0]))
@property
def company(self) -> str:
return str(self.payload.get("company", self.path.stem))
@property
def analysis_year(self) -> Any:
return self.payload.get("analysis_year")
@property
def conclusion(self) -> str:
return str(self.payload.get("conclusion", "UNKNOWN"))
@property
def special_channel(self) -> Any:
return self.payload.get("special_channel")
@property
def failed_gates(self) -> list[str]:
hard_gates = self.payload.get("hard_gates", {})
if not isinstance(hard_gates, dict):
return []
failed = []
for gate_key, gate_value in hard_gates.items():
if isinstance(gate_value, dict) and gate_value.get("pass") is False:
failed.append(gate_key)
return sorted(failed)
def is_live_analysis_card(record: CardRecord) -> bool:
scope = record.payload.get("analysis_scope")
return record.path.name.startswith("LIVE_") or scope == "live"
@dataclass
class BacktestRow:
index: int
target: str
decision_year: str
framework_conclusion: str
buffett_action: str
actual_result: str
verdict: str
@dataclass
class ReadmeProgress:
completed: int
total: int
version: str
accuracy: str
@dataclass
class BrainMetadata:
version: str
line_count: int
patch_count: int
@dataclass
class AnalysisIndexRow:
id: int
target: str
decision_year: int
status: str
cards: list[str]
card_required: bool
notes: str = ""
@dataclass
class AuditReport:
brain: BrainMetadata
cards: list[CardRecord]
backtest_rows: list[BacktestRow]
analysis_index_rows: list[AnalysisIndexRow]
detailed_sections: set[int]
pending_rows: list[BacktestRow]
expansion_rows: list[BacktestRow]
expansion_index_rows: list[AnalysisIndexRow]
expansion_detailed_sections: set[int]
readme_progress: ReadmeProgress | None
errors: list[str]
warnings: list[str]
@property
def total_cases(self) -> int:
return len(self.backtest_rows)
@property
def completed_cases(self) -> int:
return sum(1 for row in self.backtest_rows if row.verdict in BACKTEST_SCORED_SYMBOLS)
@property
def correct_cases(self) -> int:
return sum(1 for row in self.backtest_rows if row.verdict in BACKTEST_CORRECT_SYMBOLS)
@property
def accuracy(self) -> str:
scored = self.completed_cases
if scored == 0:
return "0/0"
return f"{self.correct_cases}/{scored}"
@property
def expansion_total_cases(self) -> int:
return len(self.expansion_rows)
@property
def expansion_completed_cases(self) -> int:
return sum(1 for row in self.expansion_rows if row.verdict in BACKTEST_SCORED_SYMBOLS)
@property
def expansion_correct_cases(self) -> int:
return sum(1 for row in self.expansion_rows if row.verdict in BACKTEST_CORRECT_SYMBOLS)
@property
def expansion_accuracy(self) -> str:
scored = self.expansion_completed_cases
if scored == 0:
return "0/0"
return f"{self.expansion_correct_cases}/{scored}"
@dataclass
class MethodologyReport:
completed_rows: list[BacktestRow]
ambiguous_rows: list[BacktestRow]
exit_rows: list[BacktestRow]
exception_rows: list[BacktestRow]
core_binary_rows: list[BacktestRow]
cards_with_control_group_issues: list[CardRecord]
buy_cards_with_control_group_issues: list[CardRecord]
cards_with_scope_drift: list[CardRecord]
retrospective_consistency: str
@dataclass
class GateReviewEntry:
key: str
label: str
title: str
rule: str
total_failures: int
wrong_case_failures: int
wrong_case_files: list[str]
assessment: str
note: str
@dataclass
class GateReviewReport:
archived_case_count: int
wrong_case_count: int
wrong_case_files: list[str]
entries: list[GateReviewEntry]
@dataclass
class MarketplaceBundle:
output_dir: Path
package_dir: Path
skill_dir: Path
preview_dir: Path
plugin_catalog_dir: Path
plugin_dir: Path
plugin_manifest_path: Path
plugin_catalog_path: Path
manifest_path: Path
listing_copy_path: Path
publish_checklist_path: Path
zip_path: Path | None
skill_zip_path: Path | None
plugin_zip_path: Path | None
def load_text(path: Path) -> str:
return path.read_text(encoding="utf-8") if path.exists() else ""
def load_brain() -> str:
return load_text(BRAIN_FILE)
def parse_brain_metadata(text: str) -> BrainMetadata:
versions = re.findall(r"\|\s*(v\d+\.\d+)\s*\|", text)
version = versions[-1] if versions else "v1.0"
return BrainMetadata(
version=version,
line_count=text.count("\n") + (1 if text else 0),
patch_count=text.count("## 进化补丁"),
)
def framework_version_to_semver(version: str) -> str:
match = re.search(r"v?(\d+)\.(\d+)(?:\.(\d+))?", version.strip())
if not match:
return "1.0.0"
major, minor, patch = match.groups()
return f"{major}.{minor}.{patch or '0'}"
def parse_markdown_table_row(line: str) -> list[str]:
return [cell.strip() for cell in line.strip().strip("|").split("|")]
def parse_backtest_rows(text: str) -> list[BacktestRow]:
rows: list[BacktestRow] = []
for line in text.splitlines():
stripped = line.strip()
if not stripped.startswith("|"):
continue
cells = parse_markdown_table_row(stripped)
if len(cells) != 7 or not cells[0].isdigit():
continue
rows.append(
BacktestRow(
index=int(cells[0]),
target=cells[1],
decision_year=cells[2],
framework_conclusion=cells[3],
buffett_action=cells[4],
actual_result=cells[5],
verdict=cells[6],
)
)
return rows
def parse_detailed_sections(text: str) -> set[int]:
return {int(match.group(1)) for match in re.finditer(r"^### #(\d+)\b", text, flags=re.MULTILINE)}
def parse_readme_progress(text: str) -> ReadmeProgress | None:
for line in text.splitlines():
cells = parse_markdown_table_row(line) if line.strip().startswith("|") else []
if len(cells) != 3:
continue
match = re.fullmatch(r"(\d+)\s*/\s*(\d+)\s+(?:benchmark\s+)?cases", cells[0])
if not match:
continue
return ReadmeProgress(
completed=int(match.group(1)),
total=int(match.group(2)),
version=cells[1],
accuracy=cells[2],
)
return None
def classify_framework_conclusion(label: str) -> str:
normalized = label.strip()
if "/" in normalized or "可投" in normalized or "谨慎" in normalized:
return "AMBIGUOUS"
if "卖" in normalized:
return "SELL"
if "买" in normalized:
return "BUY"
if "不投" in normalized or normalized.upper() == "PASS":
return "PASS"
return "UNKNOWN"
def load_analysis_index(index_path: Path) -> tuple[list[AnalysisIndexRow], ValidationResult]:
result = ValidationResult()
if not index_path.exists() or not index_path.is_file():
result.errors.append(f"{index_path.name} is missing")
return [], result
try:
payload = json.loads(index_path.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
result.errors.append(f"{index_path.name}: invalid JSON ({exc})")
return [], result
raw_rows = payload.get("rows")
if not isinstance(raw_rows, list):
result.errors.append(f"{index_path.name}: top-level 'rows' must be a list")
return [], result
rows: list[AnalysisIndexRow] = []
for raw in raw_rows:
if not isinstance(raw, dict):
result.errors.append(f"{index_path.name}: each row must be an object")
continue
raw_cards = raw.get("cards", [])
if not isinstance(raw_cards, list):
result.errors.append(f"{index_path.name}: row #{raw.get('id', '?')} cards must be a list")
continue
try:
row = AnalysisIndexRow(
id=int(raw["id"]),
target=str(raw["target"]),
decision_year=int(raw["decision_year"]),
status=str(raw["status"]),
cards=[str(card_name) for card_name in raw_cards],
card_required=bool(raw.get("card_required", True)),
notes=str(raw.get("notes", "")),
)
except (KeyError, TypeError, ValueError) as exc:
result.errors.append(f"{index_path.name}: invalid row payload ({exc})")
continue
if row.status not in {"completed", "pending"}:
result.errors.append(f"{index_path.name}: row #{row.id} has invalid status {row.status!r}")
rows.append(row)
return rows, result
def validate_analysis_index(
index_rows: list[AnalysisIndexRow],
backtest_rows: list[BacktestRow],
cards: list[CardRecord],
*,
index_label: str = "analysis_index.json",
) -> ValidationResult:
result = ValidationResult()
backtest_by_id = {row.index: row for row in backtest_rows}
archived_cards = [card for card in cards if not is_live_analysis_card(card)]
card_names = {card.path.name for card in archived_cards}
index_ids = [row.id for row in index_rows]
duplicate_ids = sorted({row_id for row_id in index_ids if index_ids.count(row_id) > 1})
if duplicate_ids:
result.errors.append(
f"{index_label} has duplicate row ids: " + ", ".join(f"#{row_id}" for row_id in duplicate_ids)
)
missing_ids = sorted(set(backtest_by_id) - set(index_ids))
extra_ids = sorted(set(index_ids) - set(backtest_by_id))
if missing_ids:
result.errors.append(
f"{index_label} is missing backtest rows: " + ", ".join(f"#{row_id}" for row_id in missing_ids)
)
if extra_ids:
result.errors.append(
f"{index_label} references unknown backtest rows: " + ", ".join(f"#{row_id}" for row_id in extra_ids)
)
referenced_cards: list[str] = []
for index_row in index_rows:
backtest_row = backtest_by_id.get(index_row.id)
if backtest_row is None:
continue
if index_row.target != backtest_row.target:
result.errors.append(
f"{index_label} row #{index_row.id} target mismatch: {index_row.target!r} != {backtest_row.target!r}"
)
if str(index_row.decision_year) != backtest_row.decision_year:
result.errors.append(
f"{index_label} row #{index_row.id} year mismatch: {index_row.decision_year} != {backtest_row.decision_year}"
)
expected_status = "completed" if backtest_row.verdict in BACKTEST_SCORED_SYMBOLS else "pending"
if index_row.status != expected_status:
result.errors.append(
f"{index_label} row #{index_row.id} status mismatch: {index_row.status} != {expected_status}"
)
for card_name in index_row.cards:
referenced_cards.append(card_name)
if card_name not in card_names:
result.errors.append(
f"{index_label} row #{index_row.id} references missing card {card_name}"
)
if index_row.status == "completed" and index_row.card_required and not index_row.cards:
result.errors.append(
f"{index_label} row #{index_row.id} is completed but has no linked card"
)
if index_row.status == "pending" and index_row.cards:
result.warnings.append(
f"{index_label} row #{index_row.id} is still pending but already has linked cards"
)
duplicate_cards = sorted({card_name for card_name in referenced_cards if referenced_cards.count(card_name) > 1})
if duplicate_cards:
result.warnings.append(
f"{index_label} reuses card links across rows: " + ", ".join(duplicate_cards)
)
return result
def validate_card_index_coverage(
cards: list[CardRecord],
index_groups: list[list[AnalysisIndexRow]],
) -> ValidationResult:
result = ValidationResult()
archived_cards = [card for card in cards if not is_live_analysis_card(card)]
card_names = {card.path.name for card in archived_cards}
referenced_cards = [card_name for index_rows in index_groups for row in index_rows for card_name in row.cards]
duplicate_cards = sorted({card_name for card_name in referenced_cards if referenced_cards.count(card_name) > 1})
if duplicate_cards:
result.warnings.append(
"analysis indexes reuse card links across tracks: " + ", ".join(duplicate_cards)
)
unreferenced_cards = sorted(card_names - set(referenced_cards))
if unreferenced_cards:
result.errors.append(
"company_cards contains files not linked from any analysis index: "
+ ", ".join(unreferenced_cards)
)
return result
def card_matches_query(record: CardRecord, query: str) -> bool:
query_upper = query.upper()
haystacks = {
record.path.stem.upper(),
record.ticker.upper(),
record.company.upper(),
}
return any(query_upper in haystack for haystack in haystacks)
def load_company_cards(cards_dir: Path = CARDS_DIR) -> list[CardRecord]:
records: list[CardRecord] = []
if not cards_dir.exists():
return records
for path in sorted(cards_dir.glob("*.json")):
if path.name == "_schema.json":
continue
try:
payload = json.loads(path.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
records.append(
CardRecord(
path=path,
payload={},
validation=ValidationResult(errors=[f"{path.name}: invalid JSON ({exc})"]),
)
)
continue
records.append(CardRecord(path=path, payload=payload, validation=validate_card_payload(path.name, payload)))
return records
def validate_card_payload(filename: str, payload: dict[str, Any]) -> ValidationResult:
result = ValidationResult()
missing_keys = sorted(TOP_LEVEL_REQUIRED_KEYS - payload.keys())
if missing_keys:
result.errors.append(f"{filename}: missing top-level keys: {', '.join(missing_keys)}")
hard_gates = payload.get("hard_gates")
if not isinstance(hard_gates, dict):
result.errors.append(f"{filename}: hard_gates must be an object")
return result
missing_gates = sorted(HARD_GATE_KEYS - hard_gates.keys())
if missing_gates:
result.errors.append(f"{filename}: missing hard gates: {', '.join(missing_gates)}")
conclusion = payload.get("conclusion")
if conclusion not in {"BUY", "PASS"}:
result.errors.append(f"{filename}: conclusion must be BUY or PASS")
special_channel = payload.get("special_channel")
if special_channel not in ALLOWED_SPECIAL_CHANNELS:
result.errors.append(f"{filename}: invalid special_channel {special_channel!r}")
control_groups = payload.get("control_groups")
if not isinstance(control_groups, list) or len(control_groups) < 2:
result.errors.append(f"{filename}: control_groups must contain at least 2 entries")
review_notes = payload.get("review_notes", {})
if review_notes is None:
review_notes = {}
if not isinstance(review_notes, dict):
result.errors.append(f"{filename}: review_notes must be an object when present")
review_notes = {}
g6 = hard_gates.get("g6_earnings_yield", {})
if isinstance(g6, dict):
exemption = g6.get("exemption")
if exemption is not None and exemption != special_channel:
result.errors.append(
f"{filename}: g6_earnings_yield.exemption ({exemption}) must match special_channel ({special_channel})"
)
failed_gates = [
gate_key
for gate_key, gate_value in hard_gates.items()
if isinstance(gate_value, dict) and gate_value.get("pass") is False
]
if conclusion == "PASS" and not failed_gates:
result.warnings.append(f"{filename}: PASS card has no failed hard gate; verify quick rejection rationale")
if conclusion == "BUY" and failed_gates:
if special_channel is None:
result.errors.append(
f"{filename}: BUY card has failed gates without a named exemption ({', '.join(sorted(failed_gates))})"
)
else:
allowed_failures = ALLOWED_BUY_FAILURES.get(special_channel, set())
unexpected = sorted(set(failed_gates) - allowed_failures)
if unexpected:
result.errors.append(
f"{filename}: {special_channel} does not allow failed gates: {', '.join(unexpected)}"
)
if special_channel == "GROWTH_EXCEPTION":
g6_pass = isinstance(g6, dict) and g6.get("pass") is True
if not g6_pass:
result.errors.append(f"{filename}: GROWTH_EXCEPTION requires g6_earnings_yield.pass = true")
if special_channel == "INFRA_EXEMPTION":
moat = hard_gates.get("g7_moat", {})
moat_type = moat.get("moat_type") if isinstance(moat, dict) else None
if moat_type not in {"monopoly", "cost_advantage"}:
result.warnings.append(
f"{filename}: INFRA_EXEMPTION is usually paired with monopoly/cost_advantage moat"
)
g2 = hard_gates.get("g2_fcf_to_ni", {})
g7 = hard_gates.get("g7_moat", {})
moat_pass = isinstance(g7, dict) and g7.get("pass") is True
requires_owner_earnings_note = isinstance(g2, dict) and g2.get("pass") is False and moat_pass
requires_quality_multiple_note = isinstance(g6, dict) and g6.get("pass") is False and moat_pass
owner_note = review_notes.get("owner_earnings_note")
quality_note = review_notes.get("quality_multiple_note")
management_veto = review_notes.get("management_veto")
if requires_owner_earnings_note:
if not isinstance(owner_note, dict):
result.errors.append(f"{filename}: g2 fail with passing moat requires review_notes.owner_earnings_note")
else:
missing_owner_fields = [
field_name
for field_name in ("summary", "maintenance_vs_growth_view", "decision_impact")
if not str(owner_note.get(field_name, "")).strip()
]
if missing_owner_fields:
result.errors.append(
f"{filename}: owner_earnings_note is missing fields: {', '.join(missing_owner_fields)}"
)
if requires_quality_multiple_note:
if not isinstance(quality_note, dict):
result.errors.append(f"{filename}: g6 fail with passing moat requires review_notes.quality_multiple_note")
else:
missing_quality_fields = [
field_name
for field_name in ("summary", "reason_for_low_yield", "decision_impact")
if not str(quality_note.get(field_name, "")).strip()
]
if missing_quality_fields:
result.errors.append(
f"{filename}: quality_multiple_note is missing fields: {', '.join(missing_quality_fields)}"
)
if any((requires_owner_earnings_note, requires_quality_multiple_note, bool(review_notes))):
if not isinstance(management_veto, dict):
result.errors.append(f"{filename}: review_notes.management_veto is required when review_notes are used")
else:
status = management_veto.get("status")
if status not in ALLOWED_MANAGEMENT_VETO_STATUSES:
result.errors.append(
f"{filename}: management_veto.status must be one of {sorted(ALLOWED_MANAGEMENT_VETO_STATUSES)}"
)
if not str(management_veto.get("summary", "")).strip():
result.errors.append(f"{filename}: management_veto.summary must be non-empty")
if status == "fail" and conclusion == "BUY":
result.errors.append(f"{filename}: management_veto=fail cannot coexist with conclusion=BUY")
analyzed_date = payload.get("analyzed_date")
if analyzed_date:
try:
datetime.date.fromisoformat(str(analyzed_date))
except ValueError:
result.errors.append(f"{filename}: analyzed_date must be ISO format YYYY-MM-DD")
return result
def build_audit_report(base_dir: Path = BASE_DIR) -> AuditReport:
brain_text = load_text(base_dir / "buffett_brain.md")
backtest_text = load_text(base_dir / "backtest_results.md")
expansion_text = load_text(base_dir / "universe_expansion.md")
readme_text = load_text(base_dir / "README.md")
brain = parse_brain_metadata(brain_text)
cards = load_company_cards(base_dir / "company_cards")
analysis_index_rows, index_load_result = load_analysis_index(base_dir / "analysis_index.json")
backtest_rows = parse_backtest_rows(backtest_text)
detailed_sections = parse_detailed_sections(backtest_text)
pending_rows = [row for row in backtest_rows if row.verdict == "—"]
expansion_rows: list[BacktestRow] = []
expansion_detailed_sections: set[int] = set()
expansion_index_rows: list[AnalysisIndexRow] = []
expansion_index_load_result = ValidationResult()
expansion_file = base_dir / "universe_expansion.md"
expansion_index_file = base_dir / "universe_expansion_index.json"
if expansion_file.exists() or expansion_index_file.exists():
expansion_rows = parse_backtest_rows(expansion_text)
expansion_detailed_sections = parse_detailed_sections(expansion_text)
expansion_index_rows, expansion_index_load_result = load_analysis_index(expansion_index_file)
readme_progress = parse_readme_progress(readme_text)
errors: list[str] = list(index_load_result.errors)
warnings: list[str] = list(index_load_result.warnings)
errors.extend(expansion_index_load_result.errors)
warnings.extend(expansion_index_load_result.warnings)
for card in cards:
errors.extend(card.validation.errors)
warnings.extend(card.validation.warnings)
index_validation = validate_analysis_index(
analysis_index_rows,
backtest_rows,
cards,
index_label="analysis_index.json",
)
errors.extend(index_validation.errors)
warnings.extend(index_validation.warnings)
if expansion_file.exists() or expansion_index_file.exists():
expansion_validation = validate_analysis_index(
expansion_index_rows,
expansion_rows,
cards,
index_label="universe_expansion_index.json",
)
errors.extend(expansion_validation.errors)
warnings.extend(expansion_validation.warnings)
coverage_validation = validate_card_index_coverage(cards, [analysis_index_rows, expansion_index_rows])
errors.extend(coverage_validation.errors)
warnings.extend(coverage_validation.warnings)
completed_indices = {row.index for row in backtest_rows if row.verdict in BACKTEST_SCORED_SYMBOLS}
missing_sections = sorted(completed_indices - detailed_sections)
extra_sections = sorted(detailed_sections - completed_indices)
if missing_sections:
warnings.append(
"backtest_results.md is missing detailed sections for completed cases: "
+ ", ".join(f"#{index}" for index in missing_sections)
)
if extra_sections:
warnings.append(
"backtest_results.md has detailed sections without scored summary rows: "
+ ", ".join(f"#{index}" for index in extra_sections)
)
completed_expansion_indices = {row.index for row in expansion_rows if row.verdict in BACKTEST_SCORED_SYMBOLS}
missing_expansion_sections = sorted(completed_expansion_indices - expansion_detailed_sections)
extra_expansion_sections = sorted(expansion_detailed_sections - completed_expansion_indices)
if missing_expansion_sections:
warnings.append(
"universe_expansion.md is missing detailed sections for completed cases: "
+ ", ".join(f"#{index}" for index in missing_expansion_sections)
)
if extra_expansion_sections:
warnings.append(
"universe_expansion.md has detailed sections without scored summary rows: "
+ ", ".join(f"#{index}" for index in extra_expansion_sections)
)
report = AuditReport(
brain=brain,
cards=cards,
backtest_rows=backtest_rows,
analysis_index_rows=analysis_index_rows,
detailed_sections=detailed_sections,
pending_rows=pending_rows,
expansion_rows=expansion_rows,
expansion_index_rows=expansion_index_rows,
expansion_detailed_sections=expansion_detailed_sections,
readme_progress=readme_progress,
errors=errors,
warnings=warnings,
)
if readme_progress is None:
report.errors.append("README.md is missing the Current Progress summary row")
else:
if readme_progress.completed != report.completed_cases:
report.warnings.append(
f"README.md completed cases says {readme_progress.completed}, but backtest_results.md shows {report.completed_cases}"
)
if readme_progress.total != report.total_cases:
report.warnings.append(
f"README.md total cases says {readme_progress.total}, but backtest_results.md shows {report.total_cases}"
)
if readme_progress.version != report.brain.version:
report.warnings.append(
f"README.md framework version says {readme_progress.version}, but buffett_brain.md is {report.brain.version}"
)
if not readme_progress.accuracy.startswith(report.accuracy):
report.warnings.append(
f"README.md accuracy says {readme_progress.accuracy}, but backtest_results.md computes to {report.accuracy}"
)
return report
def card_has_control_group_issue(card: CardRecord) -> bool:
control_groups = card.payload.get("control_groups", [])
if not isinstance(control_groups, list):
return False
for control_group in control_groups:
conclusion = str(control_group.get("conclusion", ""))
failed_gates = control_group.get("gates_failed", [])
if "BUY" in conclusion or failed_gates == []:
return True
return False
def build_methodology_report(base_dir: Path = BASE_DIR) -> MethodologyReport:
audit_report = build_audit_report(base_dir)
index_by_id = {row.id: row for row in audit_report.analysis_index_rows}
benchmark_card_names = {card_name for row in audit_report.analysis_index_rows for card_name in row.cards}
benchmark_cards = [card for card in audit_report.cards if card.path.name in benchmark_card_names]
cards_by_name = {card.path.name: card for card in benchmark_cards}
completed_rows = [row for row in audit_report.backtest_rows if row.verdict in BACKTEST_SCORED_SYMBOLS]
ambiguous_rows: list[BacktestRow] = []
exit_rows: list[BacktestRow] = []
exception_rows: list[BacktestRow] = []
core_binary_rows: list[BacktestRow] = []
for row in completed_rows:
decision_class = classify_framework_conclusion(row.framework_conclusion)
index_row = index_by_id.get(row.index)
linked_cards = [cards_by_name[card_name] for card_name in index_row.cards if card_name in cards_by_name] if index_row else []
is_exception = any(card.special_channel for card in linked_cards) or any(
token in row.framework_conclusion for token in ("优先股", "成长例外")
)
if decision_class == "AMBIGUOUS":
ambiguous_rows.append(row)
if decision_class == "SELL":
exit_rows.append(row)
if is_exception:
exception_rows.append(row)
if decision_class in {"BUY", "PASS"} and decision_class != "AMBIGUOUS" and not is_exception:
core_binary_rows.append(row)
cards_with_control_group_issues = [card for card in benchmark_cards if card_has_control_group_issue(card)]
buy_cards_with_control_group_issues = [
card for card in cards_with_control_group_issues if card.conclusion == "BUY"
]
cards_with_scope_drift = [
card
for card in audit_report.cards
if "not classic Buffett" in str(card.payload.get("key_insight", ""))
or "Munger" in str(card.payload.get("key_insight", ""))
]
return MethodologyReport(
completed_rows=completed_rows,
ambiguous_rows=ambiguous_rows,
exit_rows=exit_rows,
exception_rows=exception_rows,
core_binary_rows=core_binary_rows,
cards_with_control_group_issues=cards_with_control_group_issues,
buy_cards_with_control_group_issues=buy_cards_with_control_group_issues,
cards_with_scope_drift=cards_with_scope_drift,
retrospective_consistency=audit_report.accuracy,
)
def build_gate_review_report(base_dir: Path = BASE_DIR) -> GateReviewReport:
audit_report = build_audit_report(base_dir)
archived_card_names = {
card_name
for row in [*audit_report.analysis_index_rows, *audit_report.expansion_index_rows]
for card_name in row.cards
}
archived_cards = [card for card in audit_report.cards if card.path.name in archived_card_names]
wrong_cards = [card for card in archived_cards if card.payload.get("verdict") == "❌ framework_wrong"]
gate_notes = {
"g1_roe_roic": "So far there is no evidence that the 12% normalized return hurdle is the source of false negatives. Keep it strict.",
"g2_fcf_to_ni": "Raw FCF / NI is catching real capital intensity, but it also punishes reinvestment-heavy compounders. Future memos should separate maintenance capex from expansion capex before treating this fail as decisive.",
"g3_leverage": "Leverage has not yet produced false negatives in the archived set. Keep the balance-sheet discipline hard.",
"g4_revenue_trend": "Structural-decline screening is still behaving sensibly. No archived false negatives are driven by this gate yet.",
"g5_gross_margin_trend": "This gate is low-signal but not obviously broken. Keep it as a deterioration check, not as a primary stock picker.",
"g6_earnings_yield": "A flat 6% earnings-yield floor is missing some elite asset-light or brand-heavy compounders. Future memos should add a quality-multiple note before treating this fail as decisive.",
"g7_moat": "Moat remains the strongest qualitative filter in the current archive. It rejects weak businesses and has not yet shown up as a source of false negatives.",
}
entries: list[GateReviewEntry] = []
for gate in GATE_METADATA:
wrong_case_files = [card.path.name for card in wrong_cards if gate["key"] in card.failed_gates]
total_failures = sum(1 for card in archived_cards if gate["key"] in card.failed_gates)
wrong_case_failures = len(wrong_case_files)
if wrong_case_failures == 0 and total_failures == 0:
assessment = "low-signal"
elif wrong_case_failures == 0:
assessment = "holding-up"
elif gate["key"] in {"g2_fcf_to_ni", "g6_earnings_yield"}:
assessment = "under-review"
else:
assessment = "review"
entries.append(
GateReviewEntry(
key=gate["key"],
label=gate["label"],
title=gate["title"],
rule=gate["rule"],
total_failures=total_failures,
wrong_case_failures=wrong_case_failures,
wrong_case_files=wrong_case_files,
assessment=assessment,
note=gate_notes[gate["key"]],
)
)
return GateReviewReport(
archived_case_count=len(archived_cards),
wrong_case_count=len(wrong_cards),
wrong_case_files=[card.path.name for card in wrong_cards],
entries=entries,
)
def serialize_card(record: CardRecord) -> dict[str, Any]:
hard_gates = record.payload.get("hard_gates", {})
gate_summary = []
if isinstance(hard_gates, dict):
for gate in GATE_METADATA:
gate_payload = hard_gates.get(gate["key"], {})
if isinstance(gate_payload, dict):
gate_summary.append(
{
"key": gate["key"],
"label": gate["label"],
"title": gate["title"],
"pass": gate_payload.get("pass"),
"details": gate_payload,
}
)
return {
"file": record.path.name,
"ticker": record.ticker,
"company": record.company,
"analysis_year": record.analysis_year,
"conclusion": record.conclusion,
"special_channel": record.special_channel,
"failed_gates": record.failed_gates,
"validation": {
"errors": record.validation.errors,
"warnings": record.validation.warnings,
},
"payload": record.payload,
"gate_summary": gate_summary,
}
def serialize_backtest_row(row: BacktestRow) -> dict[str, Any]:
return {
"index": row.index,
"target": row.target,
"decision_year": row.decision_year,
"framework_conclusion": row.framework_conclusion,
"framework_class": classify_framework_conclusion(row.framework_conclusion),
"buffett_action": row.buffett_action,
"actual_result": row.actual_result,
"verdict": row.verdict,
}
def build_site_payload(base_dir: Path = BASE_DIR) -> dict[str, Any]:
audit_report = build_audit_report(base_dir)
methodology_report = build_methodology_report(base_dir)
cards_by_name = {card.path.name: card for card in audit_report.cards}
linked_rows = []
for index_row in audit_report.analysis_index_rows:
linked_cards = [serialize_card(cards_by_name[name]) for name in index_row.cards if name in cards_by_name]
linked_rows.append(
{
"id": index_row.id,
"track": "benchmark",
"site_key": f"benchmark-{index_row.id}",
"target": index_row.target,
"decision_year": index_row.decision_year,
"status": index_row.status,
"card_required": index_row.card_required,
"notes": index_row.notes,
"cards": linked_cards,
"backtest": serialize_backtest_row(
next(row for row in audit_report.backtest_rows if row.index == index_row.id)
),
}
)
expansion_linked_rows = []
for index_row in audit_report.expansion_index_rows:
linked_cards = [serialize_card(cards_by_name[name]) for name in index_row.cards if name in cards_by_name]
expansion_linked_rows.append(
{
"id": index_row.id,
"track": "expansion",
"site_key": f"expansion-{index_row.id}",
"target": index_row.target,
"decision_year": index_row.decision_year,
"status": index_row.status,
"card_required": index_row.card_required,
"notes": index_row.notes,
"cards": linked_cards,
"backtest": serialize_backtest_row(
next(row for row in audit_report.expansion_rows if row.index == index_row.id)
),
}
)
return {
"generated_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
"project": {
"name": "Buffett Oracle",
"scope_label": "Curated benchmark set",
"scope_note": "The 29 indexed rows are a selected benchmark set, not the full Buffett/Berkshire investment universe.",
"framework_version": audit_report.brain.version,
"framework_size": audit_report.brain.line_count,
"completed_cases": audit_report.completed_cases,
"total_cases": audit_report.total_cases,
"expansion_completed_cases": audit_report.expansion_completed_cases,
"expansion_total_cases": audit_report.expansion_total_cases,
"retrospective_consistency": audit_report.accuracy,
"expansion_consistency": audit_report.expansion_accuracy,
"cached_cards": len(audit_report.cards),
},
"rules": {
"point_in_time": "Use only information publicly available on or before the decision date.",
"named_exceptions": sorted(channel for channel in ALLOWED_SPECIAL_CHANNELS if channel),
"gates": GATE_METADATA,
},
"methodology": {
"retrospective_consistency": methodology_report.retrospective_consistency,
"ambiguous_case_ids": [row.index for row in methodology_report.ambiguous_rows],
"exception_case_ids": [row.index for row in methodology_report.exception_rows],
"exit_case_ids": [row.index for row in methodology_report.exit_rows],
"core_case_ids": [row.index for row in methodology_report.core_binary_rows],
"buy_control_issue_files": [card.path.name for card in methodology_report.buy_cards_with_control_group_issues],
"scope_drift_files": [card.path.name for card in methodology_report.cards_with_scope_drift],
},
"documents": {
"brain_markdown": load_text(base_dir / "buffett_brain.md"),
"methodology_markdown": load_text(base_dir / "methodology_audit.md"),
"readme_markdown": load_text(base_dir / "README.md"),
"expansion_markdown": load_text(base_dir / "universe_expansion.md"),
},
"rows": linked_rows,
"expansion_rows": expansion_linked_rows,
"cards": [serialize_card(card) for card in audit_report.cards],
}
def normalize_site_url(site_url: str | None) -> str:
if not site_url:
return ""
normalized = site_url.strip()
if not normalized:
return ""
return normalized.rstrip("/")
def render_site_template(template: str, context: dict[str, str]) -> str:
rendered = template
for key, value in context.items():
rendered = rendered.replace(f"{{{{{key}}}}}", value)
return rendered
def build_site_template_context(site_url: str) -> dict[str, str]:
canonical_url = f"{site_url}/" if site_url else "./"
og_image_url = f"{site_url}/social-card.svg" if site_url else "./social-card.svg"
return {
"SITE_URL": site_url,
"CANONICAL_URL": canonical_url,
"OG_IMAGE_URL": og_image_url,
"SITE_NAME": "Buffett Oracle",
"SITE_DESCRIPTION": (
"A public Buffett-style decision engine: framework, backtests, methodology audit, "
"and a live 7-gate decision lab."
),
"THEME_COLOR": "#f6f1e7",
"GENERATED_DATE": datetime.date.today().isoformat(),
}
def build_static_site(
output_dir: Path = SITE_OUTPUT_DIR,
base_dir: Path = BASE_DIR,
site_url: str | None = None,
) -> Path:
if not SITE_SRC_DIR.exists():
raise FileNotFoundError(f"Missing site source directory: {SITE_SRC_DIR}")
assets_dir = output_dir / "assets"
normalized_site_url = normalize_site_url(site_url)
template_context = build_site_template_context(normalized_site_url)
output_dir.mkdir(parents=True, exist_ok=True)
assets_dir.mkdir(parents=True, exist_ok=True)
for source_path in SITE_SRC_DIR.rglob("*"):
relative_path = source_path.relative_to(SITE_SRC_DIR)
target_path = output_dir / relative_path
if source_path.is_dir():
target_path.mkdir(parents=True, exist_ok=True)
continue
target_path.parent.mkdir(parents=True, exist_ok=True)
if source_path.suffix in SITE_TEMPLATE_SUFFIXES:
rendered = render_site_template(source_path.read_text(encoding="utf-8"), template_context)
target_path.write_text(rendered, encoding="utf-8")
else:
shutil.copy2(source_path, target_path)
payload = build_site_payload(base_dir)
(assets_dir / "site-data.json").write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
(output_dir / ".nojekyll").write_text("", encoding="utf-8")
return output_dir
def copy_path(source_path: Path, target_path: Path) -> None:
if source_path.is_dir():
shutil.copytree(source_path, target_path, dirs_exist_ok=True)
return
target_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source_path, target_path)
def copy_marketplace_payload(target_dir: Path, base_dir: Path) -> None:
for relative_path in MARKETPLACE_INCLUDED_PATHS:
source_path = base_dir / relative_path
if not source_path.exists():
continue
copy_path(source_path, target_dir / relative_path)
def build_zip_archive(source_dir: Path, archive_base: Path, zip_path: Path) -> Path:
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as archive:
for path in sorted(source_dir.rglob("*")):
if path.is_file():
archive.write(path, path.relative_to(archive_base))
return zip_path
def build_marketplace_manifest(
audit_report: AuditReport,
methodology_report: MethodologyReport,
) -> dict[str, Any]:
return {
"product_name": "Buffett Oracle",
"slug": MARKETPLACE_PACKAGE_SLUG,
"type": "skill",
"suggested_category": "Finance / Research",
"version": audit_report.brain.version,
"generated_date": datetime.date.today().isoformat(),
"works_with": list(MARKETPLACE_WORKS_WITH),
"delivery_formats": ["raw_files", "standalone_skill", "codex_plugin"],
"scope_note": (
"The benchmark archive covers a curated 29-case set, not Buffett or Berkshire's full investment history."
),
"stats": {
"benchmark_cases_completed": audit_report.completed_cases,
"benchmark_cases_total": audit_report.total_cases,
"benchmark_consistency": audit_report.accuracy,
"expansion_cases_completed": audit_report.expansion_completed_cases,
"expansion_cases_total": audit_report.expansion_total_cases,
"cached_company_cards": len(audit_report.cards),
"buy_cards": sum(1 for card in audit_report.cards if card.conclusion == "BUY"),
"pass_cards": sum(1 for card in audit_report.cards if card.conclusion == "PASS"),
"ambiguous_cases": len(methodology_report.ambiguous_rows),
"exception_cases": len(methodology_report.exception_rows),
"buy_control_misses": len(methodology_report.buy_cards_with_control_group_issues),
},
"bundle_contents": list(MARKETPLACE_INCLUDED_PATHS),
}
def build_plugin_manifest(manifest: dict[str, Any]) -> dict[str, Any]:
stats = manifest["stats"]
return {
"name": MARKETPLACE_PACKAGE_SLUG,
"version": framework_version_to_semver(str(manifest["version"])),
"description": "Buffett-style point-in-time investment analysis with BUY/PASS verdicts and cached company cards.",
"author": {
"name": MARKETPLACE_AUTHOR_NAME,
"url": MARKETPLACE_HOMEPAGE,
},
"homepage": MARKETPLACE_HOMEPAGE,
"repository": MARKETPLACE_REPOSITORY,
"license": "MIT",
"keywords": ["buffett", "investing", "valuation", "research", "finance"],
"skills": "./skills/",
"interface": {
"displayName": "Buffett Oracle",
"shortDescription": "Point-in-time Buffett investment skill",
"longDescription": (
"Buffett Oracle packages a strict Buffett + Graham research workflow with "
f"{stats['benchmark_cases_completed']}/{stats['benchmark_cases_total']} benchmark cases, "
f"{stats['expansion_cases_completed']}/{stats['expansion_cases_total']} expansion cases, and "
f"{stats['cached_company_cards']} cached company cards."
),
"developerName": MARKETPLACE_AUTHOR_NAME,
"category": MARKETPLACE_PLUGIN_CATEGORY,
"capabilities": list(MARKETPLACE_PLUGIN_CAPABILITIES),
"websiteURL": MARKETPLACE_HOMEPAGE,
"privacyPolicyURL": MARKETPLACE_HOMEPAGE,
"termsOfServiceURL": MARKETPLACE_HOMEPAGE,
"defaultPrompt": [
"Analyze Apple 2016 with Buffett Oracle.",
"Run Buffett Oracle on Tencent 2023.",
"Explain whether Mastercard 2020 is BUY or PASS.",
],
"brandColor": "#8B5E3C",
"composerIcon": "./assets/icon.svg",
"logo": "./assets/logo.svg",
},
}
def build_plugin_marketplace_catalog() -> dict[str, Any]:
return {
"name": MARKETPLACE_PLUGIN_CATALOG_NAME,
"interface": {
"displayName": "Buffett Oracle Catalog",
},
"plugins": [
{
"name": MARKETPLACE_PACKAGE_SLUG,
"source": {
"source": "local",
"path": f"./plugins/{MARKETPLACE_PACKAGE_SLUG}",
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL",
},
"category": MARKETPLACE_PLUGIN_CATEGORY,
}
],
}
def build_marketplace_start_here(manifest: dict[str, Any]) -> str:
stats = manifest["stats"]
return f"""# Buffett Oracle — Start Here
Buffett Oracle is a point-in-time investing framework and research archive. It is not personalized investment advice.
## What you received
- `SKILL.md`: skill/package entry point for OpenClaw and other instruction-friendly tools
- `agents/openai.yaml`: optional UI metadata so the package behaves like a polished skill instead of plain raw files
- `buffett-oracle.md`: portable persona/system prompt for Claude Projects and Custom GPTs
- `buffett_brain.md`: the full Buffett + Graham framework, including the 7 hard gates
- `backtest_results.md`, `coverage_scope.md`, `methodology_audit.md`, `gate_review.md`: evidence, scope boundaries, and caveats
- `company_cards/`: {stats['cached_company_cards']} cached cards so repeated analyses do not require re-fetching source filings
- `oracle.py`: helper CLI for validation, listing cards, and static-site generation
- Seller-kit siblings: the build output also includes a standalone skill zip and a Codex plugin catalog zip
## Quick install
### Standalone skill / raw files
1. Use `buffett-oracle.md` as the base system prompt.
2. Keep `SKILL.md`, `agents/openai.yaml`, and the supporting research files in the same folder.
3. Ask for a company analysis with a year, for example: `Apple 2016` or `Tencent 2023`.
### OpenClaw / Cursor
1. Upload or open this entire folder.
2. Keep `SKILL.md` and `agents/openai.yaml` in the package root.
3. Point the assistant at the repo files and ask it to analyze a company using the Buffett Oracle framework.
### Codex plugin
1. Use the seller kit's `*-codex-plugin-*.zip` artifact instead of this raw folder.
2. Install the included `plugins/buffett-oracle/` plus `.agents/plugins/marketplace.json` into your Codex plugin catalog.
3. Invoke the plugin and start with prompts like `Analyze Coca-Cola 1988`.
### Codex / Claude Code
1. Open this folder as a workspace.
2. Run `python3 oracle.py status` and `python3 oracle.py validate`.
3. Ask the assistant to analyze a company while following `CLAUDE.md`.
## Guardrails you should preserve
- Use only information available on or before the decision date.
- Keep the benchmark-scope caveat visible: this repo audits a curated 29-case benchmark, not the full Berkshire universe.
- Do not market the framework as guaranteed predictive accuracy. The methodology caveats are part of the product.
"""
def build_marketplace_listing_copy(manifest: dict[str, Any]) -> str:
stats = manifest["stats"]
works_with = ", ".join(manifest["works_with"])
return f"""# Buffett Oracle — Listing Copy
## Suggested Listing Setup
- Name: Buffett Oracle
- Type: Skill
- Category: Finance / Research
- Works With: {works_with}
- Delivery formats: raw files, standalone skill folder, Codex plugin catalog
- Suggested launch price: $29
- Suggested standard price after first reviews: $49
## Short Description
Buffett-style investment decision engine with a documented 7-gate framework, audited backtests, control groups, cached company cards, and explicit methodology caveats.
## Long Description
Buffett Oracle turns Warren Buffett's investment logic into a usable, inspectable operating system for stock research.
This package gives buyers:
- A full Buffett + Graham framework with 7 hard gates, moat analysis, named exemptions, and lock-the-conclusion discipline
- A public evidence archive with {stats['benchmark_cases_completed']}/{stats['benchmark_cases_total']} completed benchmark cases and a separate {stats['expansion_cases_completed']}/{stats['expansion_cases_total']} expansion track
- {stats['cached_company_cards']} cached company cards so repeated analyses reuse existing work instead of re-reading filings every time
- A portable prompt file for Claude Projects / Custom GPTs plus a skill file for OpenClaw-style tools
- A Codex plugin wrapper so teams can install the same research system through a plugin catalog instead of raw files
- Methodology audit files that show ambiguity, exceptions, and where the framework can still mislead you
## Core Capabilities
- Classify a thesis as INVESTMENT, SPECULATION, or TOO_HARD before doing the work
- Run 7 hard gates and auto-reject fragile businesses
- Force BUY vs PASS conclusions instead of vague hedging
- Require two control-group comparisons for every BUY
- Keep point-in-time discipline so later facts do not leak into the decision
- Reuse archived company cards instead of re-fetching known cases
## Proof Points You Can Safely Claim
- Framework version: {manifest['version']}
- Benchmark archive: {stats['benchmark_cases_completed']}/{stats['benchmark_cases_total']} completed
- Expansion archive: {stats['expansion_cases_completed']}/{stats['expansion_cases_total']} completed
- Cached company cards: {stats['cached_company_cards']}
- Methodology flags currently tracked: {stats['ambiguous_cases']} ambiguous, {stats['exception_cases']} exception-assisted, {stats['buy_control_misses']} BUY-control misses
## Scope Note
Use this exact caveat in the listing:
> The benchmark archive is a curated 29-case set. It is not Buffett or Berkshire's full investment history.
## Positioning Notes
- Best sold as a premium research skill or persona bundle, not as a trading bot
- The Codex plugin wrapper is best framed as a packaging convenience, not a new analytic engine
- Strongest buyer promise: disciplined decision process, evidence archive, and reusable research memory
- Weakest promise: "beats the market" or "predicts Buffett perfectly" - do not sell it that way
"""
def build_marketplace_publish_checklist(manifest: dict[str, Any], bundle: MarketplaceBundle) -> str:
raw_zip_name = bundle.zip_path.name if bundle.zip_path else f"{manifest['slug']}.zip"
skill_zip_name = bundle.skill_zip_path.name if bundle.skill_zip_path else f"{manifest['slug']}-skill.zip"
plugin_zip_name = (
bundle.plugin_zip_path.name if bundle.plugin_zip_path else f"{manifest['slug']}-codex-plugin.zip"
)
return f"""# Publish Checklist
1. Use `preview/social-card.svg` as your initial listing art.
2. Upload `{raw_zip_name}` to raw-files storefronts.
3. Upload `{skill_zip_name}` when a storefront wants a pure skill folder.
4. Upload `{plugin_zip_name}` when distributing through a Codex plugin catalog.
5. Paste the copy from `listing-copy.md` into the marketplace listing.
6. Set the product type to `Skill`.
7. Set works-with tags to: {", ".join(manifest['works_with'])}.
8. Keep the benchmark-scope caveat in the public description.
9. Keep the non-advice disclaimer in the package and listing.
10. After publishing, test one fresh install in both a raw-files flow and a plugin-catalog flow.
"""
def build_marketplace_bundle(
output_dir: Path = MARKETPLACE_OUTPUT_DIR,
base_dir: Path = BASE_DIR,
create_zip: bool = True,
) -> MarketplaceBundle:
audit_report = build_audit_report(base_dir)
methodology_report = build_methodology_report(base_dir)
output_dir.mkdir(parents=True, exist_ok=True)
package_dir = output_dir / "package" / MARKETPLACE_PACKAGE_SLUG
skill_dir = output_dir / "skill" / MARKETPLACE_PACKAGE_SLUG
preview_dir = output_dir / "preview"
plugin_catalog_dir = output_dir / "plugin-catalog"
plugin_dir = plugin_catalog_dir / "plugins" / MARKETPLACE_PACKAGE_SLUG
plugin_manifest_path = plugin_dir / ".codex-plugin" / "plugin.json"
plugin_catalog_path = plugin_catalog_dir / ".agents" / "plugins" / "marketplace.json"
package_dir.mkdir(parents=True, exist_ok=True)
skill_dir.mkdir(parents=True, exist_ok=True)
preview_dir.mkdir(parents=True, exist_ok=True)
plugin_manifest_path.parent.mkdir(parents=True, exist_ok=True)
plugin_catalog_path.parent.mkdir(parents=True, exist_ok=True)
copy_marketplace_payload(package_dir, base_dir)
copy_marketplace_payload(skill_dir, base_dir)
manifest = build_marketplace_manifest(audit_report, methodology_report)
manifest_path = package_dir / "manifest.json"
manifest_path.write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
(package_dir / "START_HERE.md").write_text(build_marketplace_start_here(manifest), encoding="utf-8")
listing_copy_path = output_dir / "listing-copy.md"
listing_copy_path.write_text(build_marketplace_listing_copy(manifest), encoding="utf-8")
bundle = MarketplaceBundle(
output_dir=output_dir,
package_dir=package_dir,
skill_dir=skill_dir,
preview_dir=preview_dir,
plugin_catalog_dir=plugin_catalog_dir,
plugin_dir=plugin_dir,
plugin_manifest_path=plugin_manifest_path,
plugin_catalog_path=plugin_catalog_path,
manifest_path=manifest_path,
listing_copy_path=listing_copy_path,
publish_checklist_path=output_dir / "publish-checklist.md",
zip_path=None,
skill_zip_path=None,
plugin_zip_path=None,
)
for relative_path in MARKETPLACE_PREVIEW_ASSETS:
source_path = base_dir / relative_path
if source_path.exists():
copy_path(source_path, preview_dir / source_path.name)
for asset_name in ("icon.svg", "logo.svg"):
source_path = base_dir / "assets" / asset_name
if source_path.exists():
copy_path(source_path, plugin_dir / "assets" / asset_name)
copy_path(skill_dir, plugin_dir / "skills" / MARKETPLACE_PACKAGE_SLUG)
plugin_manifest_path.write_text(
json.dumps(build_plugin_manifest(manifest), ensure_ascii=False, indent=2),
encoding="utf-8",
)
plugin_catalog_path.write_text(
json.dumps(build_plugin_marketplace_catalog(), ensure_ascii=False, indent=2),
encoding="utf-8",
)
bundle.publish_checklist_path.write_text(build_marketplace_publish_checklist(manifest, bundle), encoding="utf-8")
if create_zip:
zip_path = output_dir / f"{MARKETPLACE_PACKAGE_SLUG}-clawmart-{manifest['version'].lower()}.zip"
build_zip_archive(package_dir, package_dir.parent, zip_path)
bundle.zip_path = zip_path
skill_zip_path = output_dir / f"{MARKETPLACE_PACKAGE_SLUG}-skill-{manifest['version'].lower()}.zip"
build_zip_archive(skill_dir, skill_dir.parent, skill_zip_path)
bundle.skill_zip_path = skill_zip_path
plugin_zip_path = output_dir / f"{MARKETPLACE_PACKAGE_SLUG}-codex-plugin-{manifest['version'].lower()}.zip"
build_zip_archive(plugin_catalog_dir, plugin_catalog_dir, plugin_zip_path)
bundle.plugin_zip_path = plugin_zip_path
bundle.publish_checklist_path.write_text(build_marketplace_publish_checklist(manifest, bundle), encoding="utf-8")
return bundle
def format_card_line(record: CardRecord) -> str:
failed = ", ".join(record.failed_gates) if record.failed_gates else "none"
channel = record.special_channel or "-"
return (
f"{record.path.name:<16} "
f"{str(record.analysis_year):<4} "
f"{record.conclusion:<4} "
f"channel={channel:<17} "
f"failed={failed}"
)
def print_validation_messages(report: AuditReport) -> None:
if report.errors:
print("Errors:")
for error in report.errors:
print(f" - {error}")
if report.warnings:
print("Warnings:")
for warning in report.warnings:
print(f" - {warning}")
def cmd_status(_: argparse.Namespace) -> int:
report = build_audit_report()
methodology_report = build_methodology_report()
pending_preview = ", ".join(f"#{row.index} {row.target}" for row in report.pending_rows[:5]) or "none"
if len(report.pending_rows) > 5:
pending_preview += ", ..."
buy_count = sum(1 for card in report.cards if card.conclusion == "BUY")
pass_count = sum(1 for card in report.cards if card.conclusion == "PASS")
print(
f"""
Buffett Oracle — Repo Status
─────────────────────────────────
Framework version : {report.brain.version}
Framework size : {report.brain.line_count} lines
Evolution patches : {report.brain.patch_count}
Benchmark set : {report.completed_cases}/{report.total_cases} completed
Consistency : {report.accuracy}
Detailed writeups : {len(report.detailed_sections)}
Pending : {len(report.pending_rows)}
Indexed rows : {len(report.analysis_index_rows)}
Expansion track : {report.expansion_completed_cases}/{report.expansion_total_cases} completed
Expansion index : {len(report.expansion_index_rows)}
Company cards : {len(report.cards)} cached
BUY / PASS : {buy_count} / {pass_count}
Method flags : {len(methodology_report.ambiguous_rows)} ambiguous, {len(methodology_report.exception_rows)} exceptions, {len(methodology_report.buy_cards_with_control_group_issues)} BUY-control misses
Next pending : {pending_preview}
Coverage scope : benchmark set + separate universe expansion track
""".strip()
)
if report.errors or report.warnings:
print()
print_validation_messages(report)
else:
print()
print("Validation: clean")
return 1 if report.errors else 0
def cmd_validate(args: argparse.Namespace) -> int:
report = build_audit_report()
if report.errors or report.warnings:
print_validation_messages(report)
else:
print("Validation passed: repository state is internally consistent.")
if report.errors:
return 1
if args.strict and report.warnings:
return 1
return 0
def cmd_site(args: argparse.Namespace) -> int:
output_dir = build_static_site(Path(args.output).resolve(), site_url=args.site_url)
print(f"Static site built at: {output_dir}")
print(f"Open: {output_dir / 'index.html'}")
if args.site_url:
print(f"Canonical URL: {normalize_site_url(args.site_url)}/")
return 0
def cmd_marketplace_bundle(args: argparse.Namespace) -> int:
bundle = build_marketplace_bundle(Path(args.output).resolve(), create_zip=not args.no_zip)
manifest = json.loads(bundle.manifest_path.read_text(encoding="utf-8"))
print(f"Marketplace seller kit built at: {bundle.output_dir}")
print(f"Package folder: {bundle.package_dir}")
print(f"Standalone skill: {bundle.skill_dir}")
print(f"Codex plugin catalog: {bundle.plugin_catalog_dir}")
print(f"Plugin manifest: {bundle.plugin_manifest_path}")
print(f"Listing copy: {bundle.listing_copy_path}")
print(f"Publish checklist: {bundle.publish_checklist_path}")
print(f"Preview assets: {bundle.preview_dir}")
if bundle.zip_path:
print(f"Raw-files zip: {bundle.zip_path}")
if bundle.skill_zip_path:
print(f"Skill zip: {bundle.skill_zip_path}")
if bundle.plugin_zip_path:
print(f"Plugin zip: {bundle.plugin_zip_path}")
print(f"Suggested type/category: {manifest['type']} / {manifest['suggested_category']}")
print("Suggested launch price: $29")
return 0
def cmd_serve_site(args: argparse.Namespace) -> int:
output_dir = build_static_site(Path(args.output).resolve(), site_url=args.site_url)
handler = functools.partial(http.server.SimpleHTTPRequestHandler, directory=str(output_dir))
class ThreadingTCPServer(socketserver.ThreadingTCPServer):
allow_reuse_address = True
with ThreadingTCPServer(("", args.port), handler) as httpd:
print(f"Serving Buffett Oracle site at http://127.0.0.1:{args.port}")
print(f"Root: {output_dir}")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\nStopped.")
return 0
def cmd_backtest(_: argparse.Namespace) -> int:
audit_report = build_audit_report()
methodology_report = build_methodology_report()
def bucket_consistency(rows: list[BacktestRow]) -> str:
if not rows:
return "0/0"
correct = sum(1 for row in rows if row.verdict in BACKTEST_CORRECT_SYMBOLS)
return f"{correct}/{len(rows)}"
def row_list(rows: list[BacktestRow]) -> str:
return ", ".join(f"#{row.index} {row.target}" for row in rows) or "none"
print(
f"""
Buffett Oracle — Backtest Rerun
─────────────────────────────────
Completed benchmark cases : {audit_report.completed_cases}/{audit_report.total_cases}
Headline retrospective consistency : {audit_report.accuracy}
Expansion track completed : {audit_report.expansion_completed_cases}/{audit_report.expansion_total_cases}
Expansion consistency : {audit_report.expansion_accuracy}
Core binary non-exception set : {bucket_consistency(methodology_report.core_binary_rows)}
Ambiguous scored cases : {bucket_consistency(methodology_report.ambiguous_rows)}
Exception-assisted cases : {bucket_consistency(methodology_report.exception_rows)}
Exit / non-binary cases : {bucket_consistency(methodology_report.exit_rows)}
Current bucket members:
Core : {row_list(methodology_report.core_binary_rows)}
Ambiguous : {row_list(methodology_report.ambiguous_rows)}
Exceptions : {row_list(methodology_report.exception_rows)}
Exit : {row_list(methodology_report.exit_rows)}
Selection quality checks:
BUY cards with BUY controls : {len(methodology_report.buy_cards_with_control_group_issues)}
Scope-drift cards : {len(methodology_report.cards_with_scope_drift)}
Point-in-time rule:
Decision logic must use only information available on or before the decision date.
Coverage note:
Methodology buckets cover the curated benchmark set only.
Universe expansion is tracked separately and does not change the benchmark hit-rate math.
""".strip()
)
return 0
def cmd_methodology(_: argparse.Namespace) -> int:
report = build_methodology_report()
def row_list(rows: list[BacktestRow]) -> str:
return ", ".join(f"#{row.index} {row.target}" for row in rows) or "none"
buy_control_issue_list = ", ".join(card.path.name for card in report.buy_cards_with_control_group_issues) or "none"
scope_drift_list = ", ".join(card.path.name for card in report.cards_with_scope_drift) or "none"
print(
f"""
Buffett Oracle — Methodology Audit
─────────────────────────────────
Completed benchmark cases : {len(report.completed_rows)}
Retrospective consistency : {report.retrospective_consistency}
Ambiguous scored cases : {len(report.ambiguous_rows)} ({row_list(report.ambiguous_rows)})
Exception-assisted cases : {len(report.exception_rows)} ({row_list(report.exception_rows)})
Exit / non-binary cases : {len(report.exit_rows)} ({row_list(report.exit_rows)})
Core binary non-exception set : {len(report.core_binary_rows)} ({row_list(report.core_binary_rows)})
BUY cards with BUY controls : {len(report.buy_cards_with_control_group_issues)} ({buy_control_issue_list})
Scope-drift cards : {len(report.cards_with_scope_drift)} ({scope_drift_list})
Notes:
- This audit covers the curated benchmark set, not the full Buffett/Berkshire investment universe.
- "Retrospective consistency" is not predictive accuracy.
- Ambiguous conclusions, exception channels, and non-failing control groups all make the headline win rate look cleaner than it really is.
- Decision memos must stay point-in-time; later facts belong only in the reveal.
- oracle.py evolve now requires affected-case metadata, but it still does not automatically verify reruns.
""".strip()
)
return 0
def cmd_gate_review(_: argparse.Namespace) -> int:
report = build_gate_review_report()
wrong_case_list = ", ".join(report.wrong_case_files) or "none"
flagged_entries = [entry for entry in report.entries if entry.wrong_case_failures]
print(
f"""
Buffett Oracle — Gate Review
─────────────────────────────────
Archived scored cases : {report.archived_case_count}
Framework-wrong cases : {report.wrong_case_count} ({wrong_case_list})
False-negative gate triggers:
""".strip()
)
if flagged_entries:
for entry in flagged_entries:
files = ", ".join(entry.wrong_case_files)
print(f" {entry.label} {entry.title}: {entry.wrong_case_failures} wrong-case hits ({files})")
else:
print(" none")
print("\nGate-by-gate assessment:")
for entry in report.entries:
files = ", ".join(entry.wrong_case_files) or "none"
print(
f" {entry.label} {entry.title}\n"
f" Rule : {entry.rule}\n"
f" Total fails : {entry.total_failures}\n"
f" Wrong-case fails: {entry.wrong_case_failures} ({files})\n"
f" Assessment : {entry.assessment}\n"
f" Note : {entry.note}"
)
print(
"\nCurrent implication:\n"
" Keep the 7 gates intact for benchmark comparability, but require an owner-earnings note for Gate 2 failures\n"
" and a quality-multiple note for Gate 6 failures in new live or expansion memos."
)
return 0
def cmd_cards(_: argparse.Namespace) -> int:
cards = load_company_cards()
if not cards:
print("No company cards found.")
return 0
print("Cached company cards:")
for card in cards:
print(f" {format_card_line(card)}")
return 0
def cmd_pending(_: argparse.Namespace) -> int:
rows = parse_backtest_rows(load_text(BACKTEST_FILE))
pending = [row for row in rows if row.verdict == "—"]
if not pending:
expansion_rows = parse_backtest_rows(load_text(EXPANSION_FILE))
if expansion_rows:
print(
"No pending benchmark cases. "
f"Universe expansion currently tracks {len(expansion_rows)} additional completed cases."
)
else:
print("No pending benchmark cases. Broader Buffett/Berkshire universe expansion remains open.")
return 0
print("Pending backtest cases:")
for row in pending:
print(f" #{row.index:<2} {row.target} ({row.decision_year})")
return 0
def cmd_show(args: argparse.Namespace) -> int:
matches = [card for card in load_company_cards() if card_matches_query(card, args.query)]
if not matches:
print(f"No company card matched: {args.query}")
return 1
for index, record in enumerate(matches, start=1):
if len(matches) > 1:
print(f"[{index}] {record.path.name}")
print(json.dumps(record.payload, ensure_ascii=False, indent=2))
return 0
def cmd_brain(_: argparse.Namespace) -> int:
brain = load_brain()
if not brain:
print("大脑文件不存在:", BRAIN_FILE)
return 1
print(brain)
return 0
def cmd_corpus(_: argparse.Namespace) -> int:
print("\n📚 可用语料:\n")
qa_dir = CORPUS_DIR / "2019/巴菲特股东大会1994-2025"
if qa_dir.exists():
print(f"[股东大会 Q&A] — {qa_dir}")
for item in sorted(qa_dir.iterdir()):
if item.is_dir():
files = list(item.glob("*.txt"))
print(f" {item.name}/ ({len(files)} 个文件)")
else:
print(f" {item.name}")
print()
letter_dir = CORPUS_DIR / "2019/巴菲特致股东信1957-2025/中文翻译"
if letter_dir.exists():
files = sorted(letter_dir.glob("*.docx"))
if files:
print(f"[股东信中文翻译] — {letter_dir}")
print(f" 共 {len(files)} 封,从 {files[0].stem} 到 {files[-1].stem}")
print()
en_dir = CORPUS_DIR / "2019/巴菲特致股东信1957-2025/英文原文"
if en_dir.exists():
files = sorted(en_dir.glob("*.pdf"))
if files:
print(f"[股东信英文原文] — {en_dir}")
print(f" 共 {len(files)} 封 PDF")
return 0
def cmd_learn(args: argparse.Namespace) -> int:
path = Path(args.filepath)
if not path.exists():
print(f"文件不存在:{path}")
return 1
content = path.read_text(encoding="utf-8", errors="ignore")
if len(content) > 15000:
content = content[:15000] + "\n...[截断,仅取前15000字]"
prompt = f"""你现在扮演「巴菲特神谕」的大脑进化模块。
当前大脑内容(buffett_brain.md)已在你脑中。
以下是新的语料(来源:{path.name}):
---
{content}
---
请:
1. 提炼这段语料中有价值的新投资原则、判断逻辑、或具体案例
2. 指出与现有大脑内容的关联或补充(不要重复已有内容)
3. 给出一段可以直接追加到 buffett_brain.md 的 Markdown 内容
格式要求:
- 用 ## 进化补丁 — {datetime.date.today()} (来源: {path.name}) 作为标题
- 内容简洁,只写真正有增量价值的部分
- 附一行版本更新日志,格式:版本升级建议:v1.x"""
print("\n" + "=" * 60)
print("📋 已生成语料提炼提示词,请复制以下内容粘贴到 Claude Code:")
print("=" * 60 + "\n")
print(prompt)
print("\n" + "=" * 60)
print("📌 Claude Code 回复后,用以下命令把内容追加到大脑:")
print(" python3 oracle.py evolve")
print("=" * 60)
try:
import subprocess
subprocess.run("pbcopy", input=prompt.encode(), check=True)
print("\n✅ 已自动复制到剪贴板,直接 Cmd+V 粘贴即可。")
except Exception:
pass
return 0
def cmd_evolve(_: argparse.Namespace) -> int:
print("\n先记录这次方法学修改影响哪些案例。")
affected_cases = input("受影响案例编号(例如 #7,#9,#13):").strip()
if not affected_cases:
print("必须提供受影响案例编号,退出。")
return 1
rerun_summary = input("重跑/回归摘要:").strip()
if not rerun_summary:
print("必须提供重跑/回归摘要,退出。")
return 1
print("\n输入要添加到 buffett_brain.md 的内容(Markdown 格式)。")
print("输入完成后,单独一行输入 END 结束:\n")
lines = []
while True:
try:
line = input()
except EOFError:
break
if line.strip() == "END":
break
lines.append(line)
if not lines:
print("没有输入内容,退出。")
return 1
new_content = "\n".join(lines)
brain_content = load_brain()
today = datetime.date.today().isoformat()
versions = re.findall(r"\|\s*v(\d+)\.(\d+)\s*\|", brain_content)
if versions:
major, minor = versions[-1]
next_version = f"v{major}.{int(minor) + 1}"
else:
next_version = "v1.1"
version_row = f"| {next_version} | {today} | 手动进化 | evolve 命令;影响案例 {affected_cases} |"
if "## 原始语料索引" in brain_content:
brain_content = brain_content.replace("## 原始语料索引", f"{version_row}\n\n## 原始语料索引", 1)
else:
brain_content += f"\n\n## 自我进化记录\n\n| 版本 | 日期 | 更新内容 | 触发原因 |\n|---|---|---|---|\n{version_row}\n"
metadata_block = f"> 影响案例:{affected_cases}\n> 回归摘要:{rerun_summary}"
brain_content += f"\n\n---\n\n{metadata_block}\n\n{new_content}\n"
BRAIN_FILE.write_text(brain_content, encoding="utf-8")
print(f"\n✅ 大脑已更新至 {next_version}。")
return 0
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Buffett Oracle repository helper")
subparsers = parser.add_subparsers(dest="command")
subparsers.add_parser("status", help="Show repository status")
validate_parser = subparsers.add_parser("validate", help="Validate cards, README, and backtest consistency")
validate_parser.add_argument("--strict", action="store_true", help="Exit non-zero on warnings too")
subparsers.add_parser("backtest", help="Re-run current backtest summary with methodology buckets")
site_parser = subparsers.add_parser("site", help="Build the static website into docs/")
site_parser.add_argument("--output", default=str(SITE_OUTPUT_DIR), help="Output directory for the built site")
site_parser.add_argument("--site-url", default="", help="Public site URL for canonical and social metadata")
bundle_parser = subparsers.add_parser(
"marketplace-bundle",
help="Build seller-kit outputs for raw files, standalone skill installs, and Codex plugins",
)
bundle_parser.add_argument("--output", default=str(MARKETPLACE_OUTPUT_DIR), help="Output directory for bundle files")
bundle_parser.add_argument("--no-zip", action="store_true", help="Skip generating the buyer .zip archive")
serve_parser = subparsers.add_parser("serve-site", help="Build and preview the static website locally")
serve_parser.add_argument("--output", default=str(SITE_OUTPUT_DIR), help="Output directory for the built site")
serve_parser.add_argument("--site-url", default="", help="Public site URL for canonical and social metadata")
serve_parser.add_argument("--port", type=int, default=8000, help="Port to bind the local preview server")
subparsers.add_parser("cards", help="List cached company cards")
subparsers.add_parser("pending", help="List pending backtest cases")
subparsers.add_parser("methodology", help="Audit methodology quality beyond repo consistency")
subparsers.add_parser("gate-review", help="Audit which hard gates are causing false negatives")
show_parser = subparsers.add_parser("show", help="Display a company card by ticker/company/file query")
show_parser.add_argument("query")
subparsers.add_parser("brain", help="Print buffett_brain.md")
subparsers.add_parser("corpus", help="Browse local Buffett corpus")
learn_parser = subparsers.add_parser("learn", help="Generate a learning prompt from a local file")
learn_parser.add_argument("filepath")
subparsers.add_parser("evolve", help="Append an evolution patch to buffett_brain.md")
return parser
def main(argv: list[str] | None = None) -> int:
parser = build_parser()
args = parser.parse_args(argv)
command = args.command or "status"
handlers = {
"status": cmd_status,
"validate": cmd_validate,
"backtest": cmd_backtest,
"site": cmd_site,
"marketplace-bundle": cmd_marketplace_bundle,
"serve-site": cmd_serve_site,
"cards": cmd_cards,
"pending": cmd_pending,
"methodology": cmd_methodology,
"gate-review": cmd_gate_review,
"show": cmd_show,
"brain": cmd_brain,
"corpus": cmd_corpus,
"learn": cmd_learn,
"evolve": cmd_evolve,
}
return handlers[command](args)
if __name__ == "__main__":
sys.exit(main())
FILE:methodology_audit.md
# Buffett Oracle — Methodology Audit
*Last updated: 2026-03-25*
## Why This Exists
The project originally surfaced a single headline number (`14/14`) that looked like an accuracy metric.
That framing is too optimistic.
What the repo currently has is **retrospective consistency** on a curated benchmark set, not validated predictive accuracy and not full Berkshire-history coverage.
## Current Snapshot
- Coverage scope: curated 29-case benchmark set, not the full Buffett/Berkshire universe
- Completed benchmark cases: 29
- Retrospective consistency: 29/29
- Ambiguous scored cases: 3
- Exception-assisted cases: 6
- Exit / non-binary cases: 1
- Core binary non-exception set: 19
- BUY cards with BUY control groups: 4
- Scope-drift cards: 1
- Gate-by-gate review now lives in `gate_review.md` and `python3 oracle.py gate-review`
Generate the live version with:
```bash
python3 oracle.py methodology
```
## Main Methodology Risks
1. Ambiguous conclusions inflate the headline win rate.
Examples: `可投/非高确信`, `不投/谨慎`.
2. A finished benchmark can create false completeness.
`29 / 29` sounds like total coverage unless the scope is stated explicitly.
3. Named exceptions can become post-hoc escape hatches.
This is especially dangerous when the supporting evidence is not encoded in the card schema.
4. Control groups often identify the same quality tier instead of rejecting alternatives.
A framework that says both target and comparable are BUY is not selecting, only describing.
5. Framework evolution can overfit history.
Any new principle added after seeing outcomes must be treated as suspect until affected cases are re-run.
6. Point-in-time discipline can silently break.
If a thesis uses facts that became knowable only after the decision date, the backtest is contaminated even if the final call was directionally right.
7. A framework that does not separate investment from speculation will overstate its own certainty.
Graham's definition is stricter than "I have a thesis"; anything without analysis, principal safety, and adequate return is not core investment work.
8. Public/default guidance can drift too aggressive if investor type is left implicit.
Graham's defensive-vs-enterprising split should be explicit, with the public build defaulting to defensive logic unless deeper work is justified.
## Rules Going Forward
1. Do not call the headline number "accuracy". Call it "retrospective consistency".
2. Never present the 29 rows as if they were the full Buffett/Berkshire universe.
3. Report ambiguous, exception-assisted, and non-binary cases separately.
4. Treat the core binary non-exception subset as the cleanest methodology sample.
5. Any framework update must list affected cases and re-run them before claiming improvement.
6. Any named exception must carry explicit structured evidence in the company card.
7. Every decision memo must be point-in-time. Later facts may appear only in the outcome reveal.
8. Every decision memo should explicitly classify itself as investment, speculation, or too hard.
9. Timing guesses must not be presented as if they were underwriting conclusions.
FILE:CLAUDE.md
# Buffett Oracle — Claude Code Instructions
When working in this project, always follow these rules.
---
## Startup Checklist
At the start of every session:
1. Read `buffett_brain.md` — this is the investment framework
2. Read `backtest_results.md` — this is the accumulated analysis history
3. Check `company_cards/` — pre-extracted data for analyzed companies
4. Never re-fetch data for a company that already has a card in `company_cards/`
### Scope Rule
The current repo is a **curated benchmark set**, not the full Buffett/Berkshire investment universe.
- Do not imply that the 29 indexed rows are exhaustive
- If you add new historical cases beyond the current set, treat that as benchmark expansion and update `coverage_scope.md`
- If a user asks about total Buffett history, answer explicitly that Berkshire invested in far more than these benchmark rows
---
## Running an Analysis
### Point-in-Time Rule
Use only information that was publicly available **on or before** Buffett's decision date.
- Do not use later earnings, later management commentary, later market structure changes, or later outcomes to justify the decision
- Post-decision facts belong only in the final "what actually happened" reveal
- If a later fact materially changes your thesis, it is evidence that the original thesis was fragile, not evidence you were allowed to know it then
### Step 1: Check if card exists
```
Does company_cards/<TICKER>_<YEAR>.json exist?
YES → load it, skip to Step 3
NO → fetch 10-K from SEC EDGAR (or equivalent), extract hard gate numbers, create card
```
### Step 2: Create company card
After fetching data, immediately save to `company_cards/<TICKER>_<YEAR>.json` using the schema in `company_cards/_schema.json`. This prevents re-fetching in future sessions.
### Step 3: Run 7 hard gates
Apply all 7 gates from `buffett_brain.md`. If ANY gate triggers → output PASS immediately. Only continue to Step 4 if all gates pass (or a named exemption applies).
**Named exemptions (must state explicitly):**
- `CRISIS_PREFERRED`: Goldman 2008, BAC 2011, GE 2008 type deals — use crisis preferred channel
- `INFRA_EXEMPTION`: Rail/utility monopolies — earnings yield gate ⑥ waived if EV/EBITDA < 15x + monopoly confirmed
- `GROWTH_EXCEPTION`: ROE/FCF gates may be waived for high-growth companies if ROIC > 20% and earnings yield passes — must justify explicitly
**Gate review overlays (required when triggered):**
- If `g2` fails but `g7` still passes, add `review_notes.owner_earnings_note`
- If `g6` fails but `g7` still passes, add `review_notes.quality_multiple_note`
- For new live / expansion memos, include `review_notes.management_veto` with `clear`, `watch`, or `fail`
### Step 4: Moat analysis (gate ⑦)
Answer: "Can I describe in one paragraph why competitors cannot replicate this business in 10 years?"
- YES with confidence → continue
- NO or UNCERTAIN → PASS
### Step 5: Control group
Pick 2 comparable companies from same industry/era that Buffett did NOT buy. Apply hard gates to them. They should fail — if they pass, explain the differentiator.
### Step 6: Lock conclusion
Write BUY or PASS **before** revealing Buffett's actual decision. No changing conclusion after reveal.
### Step 7: Save results
Append to `backtest_results.md` using existing format, then update `analysis_index.json` so the backtest row and `company_cards/` cache stay linked.
---
## Hard Gates Reference
```
① Normalized ROE/ROIC < 12% (3-yr avg, ex one-time items)
② FCF / Net Income < 0.8
③ Net Debt / EBITDA > 4x [Banks: Tier 1 Capital < 8%]
④ Structural revenue decline (cyclical OK, structural not OK)
⑤ Gross margin declining 2+ consecutive years
⑥ Earnings yield (Net Income / EV) < 6% [infra exemption available]
⑦ Moat test fails — no describable structural competitive advantage
```
---
## Company Card Format
See `company_cards/_schema.json`. Always create a card after fetching new data, even for PASS results.
If the gate-review overlays above are triggered, the corresponding `review_notes` fields are part of a complete memo, not optional commentary.
---
## Contribution Rules
- Do not modify `buffett_brain.md` without documenting the change in its version table
- Do not change a concluded analysis — if you disagree, open a new entry labeled `[REVISION]`
- Always include control groups — analyses without control groups are incomplete
- Always update `analysis_index.json` when adding or changing a backtest row
- Raw 10-K files go in `raw_data/` (gitignored) — only the card gets committed
---
## Cost Management
- `company_cards/` is the cache — always check before fetching
- For 10-K fetching: use SEC EDGAR press release pages first (shorter), fall back to full 10-K only if needed
- If a company appears in `backtest_results.md`, its key numbers are in memory — no fetch needed
FILE:assets/icon.svg
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="128" height="128" rx="28" fill="#F4E6D3"/>
<rect x="18" y="18" width="92" height="92" rx="22" fill="#1F2937"/>
<path d="M37 90V38H66C80.9117 38 90 45.3762 90 56.8C90 65.3328 84.8208 71.4256 76.4 73.2L92 90H75.8L62.2 74.8H51.6V90H37ZM51.6 63.6H64.8C72.3632 63.6 76.2 61.0256 76.2 56.2C76.2 51.4752 72.3632 48.8 64.8 48.8H51.6V63.6Z" fill="#E5B96B"/>
<circle cx="92" cy="34" r="9" fill="#E5B96B"/>
</svg>
FILE:assets/logo.svg
<svg width="512" height="240" viewBox="0 0 512 240" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="512" height="240" rx="32" fill="#F7F0E7"/>
<rect x="28" y="28" width="184" height="184" rx="28" fill="#1F2937"/>
<path d="M68 171V69H123.2C152.428 69 170 83.6338 170 106.4C170 122.944 160.438 134.444 144.6 137.8L174 171H142.8L117.8 142.6H95.6V171H68ZM95.6 121H121.6C136.372 121 144.4 115.959 144.4 106C144.4 96.1406 136.372 91 121.6 91H95.6V121Z" fill="#E5B96B"/>
<circle cx="175" cy="61" r="16" fill="#E5B96B"/>
<path d="M249 95H316.2C349.452 95 370 113.853 370 143.6C370 173.347 349.452 192 316.2 192H249V95ZM277.8 168.2H314C331.731 168.2 341.2 159.026 341.2 143.6C341.2 128.174 331.731 118.8 314 118.8H277.8V168.2Z" fill="#1F2937"/>
<path d="M386 95H414.8V192H386V95Z" fill="#1F2937"/>
<path d="M433 143.6C433 114.752 454.94 92 486.2 92C501.332 92 514.446 97.0649 523.6 106.4L506.8 123C501.126 117.216 494.604 114.4 486.8 114.4C470.252 114.4 459.4 126.265 459.4 143.6C459.4 160.935 470.252 172.8 486.8 172.8C494.604 172.8 501.126 169.984 506.8 164.2L523.6 180.8C514.446 190.135 501.332 195.2 486.2 195.2C454.94 195.2 433 172.448 433 143.6Z" fill="#1F2937"/>
</svg>
FILE:company_cards/USB_2006.json
{
"ticker": "USB",
"company": "U.S. Bancorp",
"analysis_year": 2006,
"data_source": "U.S. Bancorp FY2006 10-K, SEC EDGAR; Berkshire 2006 annual report",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.225, "metric_used": "ROE", "years_averaged": "2004-2006", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 4703, "pass": null },
"g3_leverage": { "metric_used": "Tier1", "value": 0.088, "pass": true },
"g4_revenue_trend": { "description": "Net income applicable to common equity rose from $4.17B to $4.49B to $4.70B, and total net revenue continued to advance into 2006 despite some margin pressure.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "For a bank, the analogue is spread discipline plus efficiency. Net interest margin compressed modestly, but ROE remained above 20% and there was no two-year structural profitability breakdown.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.074, "net_income_m": 4703, "ev_m": 63855, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "U.S. Bancorp's moat came from a low-cost deposit base, payments and trust businesses, conservative underwriting, and a long record of superior efficiency. It was not the biggest bank, but it was one of the cleanest and best-managed, which is exactly the kind of banking franchise Buffett repeatedly favored.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"net_income_common_2006_usd_m": 4703,
"market_value_per_share_2006_usd": 36.19,
"common_shares_outstanding_2006_m": 1765,
"tier1_capital_ratio_2006": 0.088,
"roe_2006": 0.236
},
"control_groups": [
{ "ticker": "WM", "company": "Washington Mutual", "year": 2006, "gates_failed": ["g7_moat", "g3_leverage"], "conclusion": "PASS — growth was more aggressive and deposit quality plus underwriting discipline were materially weaker." },
{ "ticker": "WB", "company": "Wachovia", "year": 2006, "gates_failed": ["g7_moat"], "conclusion": "PASS — scale was larger, but credit culture and acquisition discipline were less reliable than U.S. Bancorp's." }
],
"conclusion": "BUY",
"buffett_action": "By year-end 2006 Berkshire held 31.0M U.S. Bancorp shares at a cost of about $969M.",
"actual_result": "U.S. Bancorp remained one of the higher-quality large U.S. banks through the cycle, and Berkshire kept it as a meaningful bank holding for many years before later portfolio-wide retrenchment.",
"verdict": "✅ aligned",
"key_insight": "In banking, Buffett's edge often comes from picking the cleanest culture and deposit franchise, not the flashiest balance sheet."
}
FILE:company_cards/COP_2007.json
{
"ticker": "COP",
"company": "ConocoPhillips",
"analysis_year": 2007,
"data_source": "ConocoPhillips FY2007 10-K, SEC EDGAR; Berkshire 2008 annual report; 2015 Berkshire AGM Q&A",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.207, "metric_used": "ROE", "years_averaged": "2005-2007", "pass": true },
"g2_fcf_to_ni": { "value": 0.66, "fcf": 10226, "net_income": 15550, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 1.2, "pass": true },
"g4_revenue_trend": { "description": "Revenue growth into 2007 was driven by commodity pricing and production, not by a structurally worsening business.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "No clear two-year structural gross-margin collapse before the purchase; the real problem was cyclicality and capital intensity.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.141, "net_income_m": 15550, "ev_m": 110000, "exemption": null, "pass": true },
"g7_moat": { "verdict": "FAIL", "moat_type": "cost_advantage", "description": "ConocoPhillips owned valuable assets, but its economics still depended primarily on oil and gas prices. It could not be described as a business competitors could not replicate in 10 years; the product remained a commodity and the returns were cycle-led rather than moat-led.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"revenue_2007_usd_m": 178558,
"net_income_2007_usd_m": 15550,
"operating_cash_flow_2007_usd_m": 24550,
"capital_expenditure_2007_usd_m": 14324
},
"control_groups": [
{ "ticker": "XOM", "company": "Exxon Mobil", "year": 2008, "gates_failed": ["g7_moat"], "conclusion": "PASS — same commodity exposure and no Buffett-style moat despite better scale." },
{ "ticker": "BP", "company": "BP p.l.c.", "year": 2008, "gates_failed": ["g2_fcf_to_ni", "g7_moat"], "conclusion": "PASS — similarly tied to oil prices and capital intensity, without a durable moat." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire built a roughly $7B ConocoPhillips position around the 2008 period.",
"actual_result": "Buffett later called the timing a mistake made near the oil-price peak; the investment was not a Berkshire-quality win.",
"verdict": "⭐ framework_wins",
"key_insight": "Peak-cycle commodity profits can make a stock look optically cheap while still failing the moat and cash-conversion test."
}
FILE:company_cards/VZ_2019.json
{
"ticker": "VZ",
"company": "Verizon Communications Inc.",
"analysis_year": 2020,
"data_source": "Verizon FY2019 10-K and Berkshire 2020-12-31 / 2021-03-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.431, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": 0.991, "fcf": 19088, "net_income": 19265, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.39, "pass": true },
"g4_revenue_trend": { "description": "Revenue moved from $126.0B in 2017 to $130.9B in 2018 to $131.9B in 2019. The wireless base looked mature, but there was no obvious structural collapse at the decision point.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Wireless and broadband economics moved around with handset mix and accounting presentation, but there was no clean two-year structural margin deterioration visible in the pre-2021 public filings.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.055, "net_income_m": 19265, "ev_m": 348490, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Verizon had real assets in spectrum, towers, brand, and postpaid customer relationships, but the overall business still sat inside a capital-intensive oligopoly where required reinvestment and competition make the moat less pristine than a Buffett tollbooth.", "pass": false }
},
"special_channel": null,
"control_groups": [
{ "ticker": "T", "company": "AT&T Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g5_gross_margin_trend"], "conclusion": "PASS — heavier strategic drift and weaker capital discipline than Verizon." },
{ "ticker": "LUMN", "company": "Lumen Technologies, Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — far more obvious structural decline and franchise erosion." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 146.7M Verizon shares worth about $8.62B at 2020-12-31, then increased the stake to 158.8M shares by 2021-03-31.",
"actual_result": "Berkshire still held 158.8M shares at 2021-12-31, but the position no longer appeared by 2022-12-31. This was large, but not permanent.",
"verdict": "⭐ framework_wins",
"key_insight": "A statistically cheap-looking telecom can still be a pass when the moat is not clean enough and the starting return only barely misses the hurdle."
}
FILE:company_cards/PTR_2003.json
{
"ticker": "PTR",
"company": "PetroChina Company Limited",
"analysis_year": 2003,
"data_source": "PetroChina FY2003 Form 20-F, SEC EDGAR; Berkshire 2003 annual report; 2004 Berkshire AGM Q&A",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.175, "metric_used": "ROE", "years_averaged": "2001-2003", "pass": true },
"g2_fcf_to_ni": { "value": 0.70, "fcf": 5850, "net_income": 8411, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.6, "pass": true },
"g4_revenue_trend": { "description": "Revenue and profit expanded materially into 2003; the issue was commodity cyclicality, not structural decline.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Upstream profitability remained strong and there was no two-year gross-margin collapse in the reported period.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.188, "net_income_m": 8411, "ev_m": 44750, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "PetroChina's moat was not brand or network. It was a huge low-cost reserve base, integrated domestic infrastructure, and state-linked access that made its asset position difficult to replicate. Buffett's own argument in 2004 was that, on reserves, output, and refining capacity, it was far cheaper than Exxon, BP, or Shell.", "pass": true }
},
"special_channel": null,
"review_notes": {
"owner_earnings_note": {
"summary": "PetroChina's weak raw FCF conversion in 2003 reflected very heavy reserve-development and infrastructure spend inside a still-cheap energy giant.",
"maintenance_vs_growth_view": "A large share of capex was sustaining and reserve-replacement spend rather than obviously discretionary growth capex, so owner earnings did not improve enough to rescue the Buffett-style quality case.",
"decision_impact": "The note explains why g2 may be too blunt for some resource bargains, but this memo still keeps PASS because the business remains capital-heavy and commodity-driven."
},
"management_veto": {
"status": "clear",
"summary": "No specific integrity or capital-allocation red flag drove the rejection here; the issue was business type and cash conversion, not management trustworthiness."
}
},
"metrics_snapshot": {
"net_income_2003_usd_m": 8411,
"operating_cash_flow_2003_usd_m": 16543,
"capital_expenditure_2003_usd_m": 10693,
"berkshire_cost_usd_m": 488
},
"control_groups": [
{ "ticker": "XOM", "company": "Exxon Mobil", "year": 2004, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — same commodity exposure, but far less valuation support than PetroChina." },
{ "ticker": "BP", "company": "BP p.l.c.", "year": 2004, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — integrated major with similar macro exposure, but without PetroChina's extreme discount." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire accumulated a PetroChina stake with cost around $488M and publicly discussed it in 2004.",
"actual_result": "Berkshire later exited around 2007 with a multi-billion-dollar gain after the position appreciated dramatically.",
"verdict": "❌ framework_wrong",
"key_insight": "The current framework intentionally leaves some ultra-cheap, capital-heavy resource bargains on the table when cash conversion does not clear the hard gate."
}
FILE:company_cards/KO_1987.json
{
"ticker": "KO",
"company": "The Coca-Cola Company",
"analysis_year": 1988,
"data_source": "FY1987 annual report data as reflected in Coca-Cola's official historical annual report tables, plus Berkshire 1988/1989 shareholder letters",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.239, "metric_used": "ROE", "years_averaged": "1985-1987", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 1049, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/Capital", "value": 0.053, "pass": true },
"g4_revenue_trend": { "description": "Net operating revenues rose from about $4.2B (1985) to $4.7B (1986) to $5.4B (1987), with international volume and concentrate economics driving growth before Buffett began buying in 1988.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross profit stayed near 69% of revenue through 1985-1987, showing stable concentrate economics and strong pricing power rather than margin erosion.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.102, "net_income_m": 1049, "ev_m": 10300, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Coca-Cola had the rare combination of a global consumer brand, a concentrate model with extraordinary economics, and a distribution system embedded in local bottlers worldwide. Consumers asked for Coke by name, retailers had to carry it, and advertising scale reinforced an already dominant habit. Competitors could copy a drink, but not the brand imprint, shelf position, and global bottling footprint.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"revenue_1987_m": 5417,
"gross_profit_1987_m": 3734,
"net_income_1987_m": 1049,
"berkshire_cost_1988_m": 592.54,
"berkshire_shares_1988": 14172500
},
"control_groups": [
{ "ticker": "PEP", "company": "PepsiCo", "year": 1988, "gates_failed": [], "conclusion": "BUY — also a strong business, but less pure than Coca-Cola because snacks and restaurant operations diluted the concentrate-style economics Buffett wanted." },
{ "ticker": "CCE", "company": "Coca-Cola Enterprises", "year": 1988, "gates_failed": ["g2_fcf_to_ni", "g3_leverage", "g7_moat"], "conclusion": "PASS — bottling is far more capital intensive and locally competitive than owning the concentrate brand franchise." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire began buying in 1988; by year-end it owned 14.17M shares costing $592.5M, and by year-end 1989 it had 23.35M shares at a total cost of about $1.02B.",
"actual_result": "One of Berkshire's greatest investments ever — decades of compounding, massive dividends, and a position still held as a core long-term winner.",
"verdict": "✅ aligned",
"key_insight": "The market saw a familiar soda company; Buffett finally saw a global brand-network system with extraordinary returns, low capital needs at the concentrate level, and decades of runway."
}
FILE:company_cards/DIS_1999.json
{
"ticker": "DIS",
"company": "The Walt Disney Company",
"analysis_year": 2000,
"data_source": "Disney FY1999 10-K, SEC EDGAR; Berkshire 2000-03-31 13F-HR/A",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.090, "metric_used": "ROE", "years_averaged": "1997-1999", "pass": false },
"g2_fcf_to_ni": { "value": 2.66, "fcf": 3454.0, "net_income": 1300.0, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.37, "pass": true },
"g4_revenue_trend": { "description": "Revenue was still growing into 1999, rising from $22.5B to $23.0B to $23.4B. The issue was not top-line shrinkage but weakening profitability and a more complex conglomerate mix.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Disney's operating margin deteriorated for two consecutive years, from roughly 19.8% in 1997 to 17.5% in 1998 to 14.7% in 1999, reflecting weaker studio results, Internet losses, and broader integration drag.", "declining_2plus_years": true, "pass": false },
"g6_earnings_yield": { "value": 0.019, "net_income_m": 1300.0, "ev_m": 70079, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Disney unquestionably had a moat: unmatched family IP, parks, media distribution, consumer-products licensing, and a library of characters and franchises that competitors could not duplicate. The question in 2000 was not whether Disney owned great assets, but whether the conglomerate's economics and valuation still left a meaningful margin of safety.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "Disney's sub-2% earnings yield reflected peak late-1990s enthusiasm around media franchises, Internet optionality, and conglomerate prestige.",
"reason_for_low_yield": "Unlike elite tollbooths such as Moody's, this low yield did not sit on top of rising returns on capital; it coincided with declining margins and more complex capital demands.",
"decision_impact": "The note reinforces rather than softens the PASS. Disney had wonderful assets, but the price and return profile did not look like a Buffett-grade bargain."
},
"management_veto": {
"status": "watch",
"summary": "No integrity red flag dominates the file, but the capital-allocation picture was more complicated than at Berkshire's cleanest compounders because the business mix, studio volatility, and Internet ambitions were already muddying the economics."
}
},
"metrics_snapshot": {
"revenue_1999_usd_m": 23402,
"operating_income_1999_usd_m": 3444,
"net_income_1999_usd_m": 1300,
"cash_provided_by_operations_1999_usd_m": 5588,
"capital_expenditures_1999_usd_m": 2134,
"cash_1999_usd_m": 414,
"borrowings_1999_usd_m": 11693,
"berkshire_shares_q1_2000_m": 2.332,
"berkshire_market_value_q1_2000_usd_m": 96.2
},
"control_groups": [
{ "ticker": "TWX", "company": "Time Warner Inc.", "year": 2000, "gates_failed": ["g5_gross_margin_trend", "g6_earnings_yield"], "conclusion": "PASS — another great library-and-distribution asset base, but conglomerate complexity and lofty pricing offered little safety." },
{ "ticker": "VIA", "company": "Viacom Inc.", "year": 2000, "gates_failed": ["g3_leverage", "g6_earnings_yield"], "conclusion": "PASS — strong media assets, but more leverage and no clearer bargain than Disney at the time." }
],
"conclusion": "PASS",
"buffett_action": "By March 31, 2000 Berkshire disclosed 2,331,762 Walt Disney shares valued at about $96.2M.",
"actual_result": "Disney remained a culturally dominant company, but the stock did not deliver the kind of immediate or clean compounding Berkshire's best ideas produced from their entry points; the late-1990s valuation premium had already pulled a lot of future success forward.",
"verdict": "⭐ framework_wins",
"key_insight": "A world-class brand portfolio can still be a pass when returns on capital are softening and the market is already capitalizing perfection."
}
FILE:company_cards/RH_2020.json
{
"ticker": "RH",
"company": "RH",
"analysis_year": 2020,
"data_source": "RH FY2020 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.34, "metric_used": "ROIC", "years_averaged": "2018-2020 (proxy because reported equity was distorted by buybacks and lease accounting)", "pass": true },
"g2_fcf_to_ni": { "value": 1.114, "fcf": 246, "net_income": 220, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.6, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $2.44B in FY2018 to $2.51B in FY2019 to $2.65B in FY2020. The business was cyclical and fashion-sensitive, but not visibly in structural decline.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin improved from about 34.4% in FY2018 to 39.3% in FY2019 to 41.4% in FY2020. Margin quality was getting better, not worse.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.023, "net_income_m": 220, "ev_m": 9406, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "RH had a differentiated luxury-furnishings brand and design ecosystem, but by late 2020 it still depended on fashion relevance, housing wealth effects, and execution in a category that remains replicable enough to fail the Oracle's 10-year moat test.", "pass": false }
},
"special_channel": null,
"control_groups": [
{ "ticker": "BBBY", "company": "Bed Bath & Beyond Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — a much weaker retailer with obvious franchise decay." },
{ "ticker": "WSM", "company": "Williams-Sonoma, Inc.", "year": 2020, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — a better operator than BBBY, but still priced for success and lacking RH's exact positioning." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 787,469 RH shares worth about $352.4M at 2020-12-31 in its 13F-HR.",
"actual_result": "The position increased to 871,468 shares by 2021-12-31 and to 1,163,000 shares by 2022-12-31. Berkshire clearly treated RH as more than a fleeting trade.",
"verdict": "❌ framework_wrong",
"key_insight": "The framework is still likely too strict on some founder-led specialty retailers whose brand and customer economics are stronger than a classic moat screen recognizes."
}
FILE:company_cards/SEES_1972.json
{
"ticker": "SEES",
"company": "See's Candies",
"analysis_year": 1972,
"data_source": "Berkshire Hathaway 2014 special letter 'Berkshire – Past, Present and Future'",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.50, "metric_used": "ROIC", "years_averaged": "1972 purchase economics", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 4, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/Capital", "value": null, "pass": null },
"g4_revenue_trend": { "description": "The business was stable and category demand was recurring; the attraction was not rapid growth but durable repeat purchasing and pricing power.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "See's pricing power and light capital needs implied durable margins rather than erosion. Buffett's own later description was that incremental growth required only minor investment.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.16, "net_income_m": 4, "ev_m": 25, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "See's had a broad and durable competitive advantage rooted in brand, gifting tradition, and pricing power. Customers were not buying generic boxed chocolate; they were buying the See's experience and reputation. That let earnings rise with little incremental capital, the hallmark of a Buffett-quality moat.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"pretax_earnings_1972_m": 4,
"net_tangible_assets_1972_m": 8,
"purchase_price_1972_m": 25
},
"control_groups": [
{ "ticker": "WHTMN", "company": "Whitman's", "year": 1972, "gates_failed": ["g7_moat"], "conclusion": "PASS — respectable confectionery brand, but without the same regional cult following and pricing power economics Buffett observed in See's." },
{ "ticker": "FANNY", "company": "Fanny Farmer", "year": 1972, "gates_failed": ["g6_earnings_yield", "g7_moat"], "conclusion": "PASS — the category was similar, but the business quality and economic moat were weaker than See's." }
],
"conclusion": "BUY",
"buffett_action": "Blue Chip Stamps bought See's Candies in 1972 for $25M; the business later became part of Berkshire.",
"actual_result": "A transformational winner. Buffett later reported that See's had earned about $1.9B pre-tax while requiring only about $40M of additional investment.",
"verdict": "✅ aligned",
"key_insight": "This was the canonical shift from cigar-butts to wonderful businesses: a high-return brand that could gush cash for decades."
}
FILE:company_cards/USAIR_1988.json
{
"ticker": "USAIR",
"company": "USAir Group, Inc.",
"analysis_year": 1989,
"data_source": "USAir 1988 earnings releases as reported contemporaneously in The Washington Post, plus Berkshire 1989 and 1995 shareholder letters",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROE", "years_averaged": "1987-1988", "pass": null },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 165, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": null, "pass": null },
"g4_revenue_trend": { "description": "Reported revenue was growing through acquisitions and merger integration, but that growth did not solve the industry's structurally weak economics.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Margins were unstable and heavily influenced by merger costs, fuel, labor, and fare competition; no durable gross-margin signal existed.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "USAir had routes, gates, and a recognizable brand, but none created a durable moat. Customers still bought on price and schedule, unions captured much of the upside, and any shock in fuel, recession, labor, or competition could wipe out economics. A senior security improved the payoff profile, but it did not fix the business.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"revenue_1988_m": 5700,
"net_income_1988_m": 165,
"revenue_q1_1989_m": 1500,
"operating_income_q1_1989_m": 57.7
},
"control_groups": [
{ "ticker": "EAL", "company": "Eastern Air Lines", "year": 1989, "gates_failed": ["g3_leverage", "g7_moat"], "conclusion": "PASS — financially weaker and exposed to the same commodity-industry economics." },
{ "ticker": "PANAM", "company": "Pan Am Corporation", "year": 1989, "gates_failed": ["g3_leverage", "g4_revenue_trend", "g7_moat"], "conclusion": "PASS — weaker balance sheet and no defensible moat in an already brutal industry." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire bought $358M of 9.25% convertible preferred in 1989, redeemable in ten years and convertible at $60 per share.",
"actual_result": "The preferred dividend was suspended and Buffett later called the deal a case of sloppy analysis. USAir eventually survived and Berkshire exited with a profit, but only after years of near-disaster and poor opportunity cost.",
"verdict": "⭐ framework_wins",
"key_insight": "A strong preferred coupon cannot rescue a deal when the underlying business has no moat and management cannot control industry economics."
}
FILE:company_cards/G_1988.json
{
"ticker": "G",
"company": "The Gillette Company",
"analysis_year": 1989,
"data_source": "Gillette 1988 annual report tables reproduced in archival case materials sourced to company annual reports, plus Berkshire 1989 and 1995 shareholder letters",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.18, "metric_used": "ROIC", "years_averaged": "1987-1988", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 268.5, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.6, "pass": true },
"g4_revenue_trend": { "description": "Sales grew from about $3.17B to $3.58B in 1987-1988, and the new Sensor platform was about to launch. Growth was coming from product strength, not financial engineering.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Operating income rose from $523M to $614M in 1987-1988 and the blades-and-razors segment remained the overwhelming profit engine. No two-year margin deterioration was visible at the business level.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Gillette owned the premium end of a habit-driven category where brand, patents, shelf space, and replacement-blade economics reinforced each other. Consumers repeatedly bought high-margin cartridges, retailers had to stock the category leader, and product innovation such as Sensor deepened rather than reset the moat.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"net_sales_1988_m": 3581.2,
"ebit_1988_m": 651.2,
"net_income_1988_m": 268.5,
"long_term_debt_1988_m": 1675.2,
"berkshire_investment_1989_m": 600
},
"control_groups": [
{ "ticker": "BIC", "company": "BIC Corporation", "year": 1988, "gates_failed": ["g7_moat"], "conclusion": "PASS — strong disposable economics, but not the same premium refill-system moat or innovation flywheel as Gillette." },
{ "ticker": "SCHICK", "company": "Schick / Wilkinson Sword", "year": 1989, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — credible competitor, but lacked Gillette's breadth of brand power, patent cadence, and global installed base." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire bought $600M of Gillette convertible preferred in July 1989 with an 8.75% dividend, mandatory redemption in ten years, and conversion at $50 per share.",
"actual_result": "One of Berkshire's best structured-equity investments. Buffett later said he should probably have bought common stock outright because the economics were even better than the preferred captured.",
"verdict": "✅ aligned",
"key_insight": "When the business is truly exceptional, even a conservative structured security can work very well — but the real lesson is how obvious the underlying moat already was."
}
FILE:company_cards/WPC_1973.json
{
"ticker": "WPC",
"company": "The Washington Post Company",
"analysis_year": 1973,
"data_source": "Berkshire Hathaway 1985 and 1986 shareholder letters",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROE", "years_averaged": "1971-1973", "pass": null },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/Capital", "value": null, "pass": null },
"g4_revenue_trend": { "description": "Buffett wrote that through 1973 and 1974 WPC continued to do fine as a business while intrinsic value kept climbing.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "The newspaper and media franchise was not showing operating deterioration at the time Berkshire bought; the opportunity came from market panic, not business decay.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "PASS", "moat_type": "network_effect", "description": "The Washington Post combined local monopoly economics, brand trust, and scarce media assets in a way that gave it durable pricing power with both readers and advertisers. Buffett's core observation was that the market value had fallen to about $100M even though knowledgeable observers would have valued the business at $400M-$500M.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"market_value_1973_m": 100,
"intrinsic_value_range_low_m": 400,
"intrinsic_value_range_high_m": 500,
"berkshire_cost_1984_m": 10.628
},
"control_groups": [
{ "ticker": "NYT", "company": "The New York Times Company", "year": 1973, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — quality media asset, but not available at anything like the Washington Post discount." },
{ "ticker": "GCI", "company": "Gannett", "year": 1973, "gates_failed": ["g7_moat"], "conclusion": "PASS — a solid operator, but the local-monopoly economics and bargain valuation setup were not comparable." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire built its Washington Post stake in 1973 at no more than about one-fourth of business value.",
"actual_result": "A historic multidecade winner and one of Buffett's clearest Graham-meets-quality triumphs.",
"verdict": "✅ aligned",
"key_insight": "This was a wonderful business available at a Graham discount, a rare combination that Buffett never forgot."
}
FILE:company_cards/PCC_2014.json
{
"ticker": "PCC",
"company": "Precision Castparts Corp.",
"analysis_year": 2015,
"data_source": "FY2014 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.16, "metric_used": "ROE", "years_averaged": "2012-2014", "pass": true },
"g2_fcf_to_ni": { "value": 0.95, "fcf": 1520, "net_income": 1600, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.5, "pass": true },
"g4_revenue_trend": { "description": "Growing with aerospace cycle", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Expanding margins", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.043, "net_income_m": 1600, "ev_m": 37200, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "Aerospace component manufacturer with FAA certifications, 5-10 year qualification cycles. Switching cost is time (years to qualify new supplier) not money.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "Precision Castparts was a real moat business, and part of its low yield reflected genuine aerospace qualification barriers and switching costs.",
"reason_for_low_yield": "The market was paying for quality, but in this case the multiple still required too much optimism about aerospace-cycle durability and future growth.",
"decision_impact": "The quality note is important, but it does not overturn PASS. PCC remains the model case for excellent business, bad price."
},
"management_veto": {
"status": "clear",
"summary": "There was no management veto. The rejection remains a valuation call, not a stewardship or integrity concern."
}
},
"control_groups": [
{ "ticker": "TDG", "company": "TransDigm", "year": 2014, "gates_failed": ["g3_leverage"], "conclusion": "PASS" },
{ "ticker": "HWM", "company": "Arconic (then Alcoa)", "year": 2014, "gates_failed": ["g4_revenue_trend"], "conclusion": "PASS" }
],
"conclusion": "PASS",
"buffett_action": "Acquired entire company for $37.2B ($235/share)",
"actual_result": "$11B goodwill impairment, Buffett admitted overpaying",
"verdict": "⭐ framework_wins",
"key_insight": "Gate ⑥ is the price discipline gate. Earnings yield of 4.3% means you need strong growth assumptions to justify the price — PCC is a quality business bought at a bad price. Quality ≠ good investment."
}
FILE:company_cards/NFM_1983.json
{
"ticker": "NFM",
"company": "Nebraska Furniture Mart",
"analysis_year": 1983,
"data_source": "Berkshire Hathaway 1984, 1985, and 2013 annual reports",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROIC", "years_averaged": "1983-1984", "pass": null },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/Capital", "value": null, "pass": null },
"g4_revenue_trend": { "description": "Even against a terrible farm economy, Buffett reported that NFM easily set new sales records after the acquisition.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "The business was built on extreme low-cost retailing and high turnover rather than fragile margin inflation, and operating earnings rose after acquisition.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "Nebraska Furniture Mart's moat was radical cost advantage. Rose Blumkin built a business able to underprice rivals while still earning acceptable returns because of merchandising intensity, inventory turnover, and an almost fanatical operating culture. Buffett treated the Blumkin family as a managerial group unlike any he had seen.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"operating_earnings_1984_m": 14.511,
"operating_earnings_1985_m": 12.686,
"purchase_price_estimate_m": 60
},
"control_groups": [
{ "ticker": "SEARS", "company": "Sears", "year": 1983, "gates_failed": ["g7_moat"], "conclusion": "PASS — huge retailer, but without NFM's singular low-cost culture." },
{ "ticker": "LEVITZ", "company": "Levitz Furniture", "year": 1983, "gates_failed": ["g7_moat"], "conclusion": "PASS — category exposure was similar, but cost advantage and owner-operator quality were not." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire acquired a majority stake in Nebraska Furniture Mart in 1983 from Rose Blumkin.",
"actual_result": "A major long-term winner and one of Berkshire's purest cost-advantage acquisitions.",
"verdict": "✅ aligned",
"key_insight": "This was retail done the Buffett way: not fashion, not story, just a durable low-cost machine run by extraordinary people."
}
FILE:company_cards/JNJ_2007.json
{
"ticker": "JNJ",
"company": "Johnson & Johnson",
"analysis_year": 2007,
"data_source": "Johnson & Johnson FY2006 annual report, SEC EDGAR; Berkshire 2007 annual report",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.279, "metric_used": "ROE", "years_averaged": "2004-2006", "pass": true },
"g2_fcf_to_ni": { "value": 1.05, "fcf": 11582, "net_income": 11053, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.14, "pass": true },
"g4_revenue_trend": { "description": "Sales and earnings grew steadily across pharmaceuticals, medical devices, and consumer products into 2006.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "No visible two-year structural gross-margin decay; economics remained stable across the diversified healthcare portfolio.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.060, "net_income_m": 11053, "ev_m": 184000, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Johnson & Johnson combined trusted consumer brands, device scale, global distribution, and healthcare relationships across multiple categories. No single rival could easily replicate the portfolio breadth, regulatory infrastructure, and channel presence that made the franchise so resilient.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"sales_2006_usd_m": 53324,
"net_income_2006_usd_m": 11053,
"operating_cash_flow_2006_usd_m": 14248,
"capex_2006_usd_m": 2666,
"berkshire_cost_2007_usd_m": 3943
},
"control_groups": [
{ "ticker": "PFE", "company": "Pfizer", "year": 2007, "gates_failed": ["g4_revenue_trend", "g5_gross_margin_trend"], "conclusion": "PASS — looming patent pressure and weaker quality of growth made the economics less dependable." },
{ "ticker": "MRK", "company": "Merck", "year": 2007, "gates_failed": ["g4_revenue_trend", "g6_earnings_yield"], "conclusion": "PASS — a strong company, but less diversified and still working through post-Vioxx uncertainty." }
],
"conclusion": "BUY",
"buffett_action": "By year-end 2007 Berkshire held 64.3M Johnson & Johnson shares at a cost of about $3.94B.",
"actual_result": "Johnson & Johnson produced the kind of stable defensive performance the underwriting implied, even though Berkshire later redeployed capital elsewhere.",
"verdict": "✅ aligned",
"key_insight": "A diversified healthcare franchise can look plain on the surface and still qualify as a high-quality Buffett-style compounder."
}
FILE:company_cards/WFC_1990.json
{
"ticker": "WFC",
"company": "Wells Fargo & Company",
"analysis_year": 1991,
"data_source": "Berkshire Hathaway 1990 shareholder letter",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.20, "metric_used": "ROE", "years_averaged": "1989-1990", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Tier1 / capital buffer", "value": null, "pass": null },
"g4_revenue_trend": { "description": "The issue in 1990 was credit panic around California real estate, not franchise decline. Buffett described Wells as a superbly managed, high-return banking operation.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Bank margins were under stress from panic and provisioning, but the underlying franchise economics remained intact.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.20, "net_income_m": 580, "ev_m": 2900, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "Wells Fargo combined a low-cost deposit franchise, disciplined management, and entrenched customer relationships in California banking. Buffett's 1990 letter framed it as a rare bank able to earn more than 20% on equity and 1.25% on assets, evidence of a real competitive advantage rather than a commodity lender surviving on leverage.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"berkshire_cost_1990_m": 290,
"assets_1990_b": 56,
"pre_tax_earnings_1990_m": 1000,
"roe_pct_floor": 0.20,
"roa_pct": 0.0125
},
"control_groups": [
{ "ticker": "BAC", "company": "BankAmerica", "year": 1990, "gates_failed": ["g7_moat"], "conclusion": "PASS — larger institution, but without Wells Fargo's management quality and clean economics." },
{ "ticker": "SPC", "company": "Security Pacific", "year": 1990, "gates_failed": ["g7_moat"], "conclusion": "PASS — another California bank exposed to the same fear, but without the same proven earnings power and management edge." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire accumulated just under 10% of Wells Fargo in 1989-1990 for about $290M.",
"actual_result": "A three-decade winner and one of Berkshire's canonical crisis purchases.",
"verdict": "✅ aligned",
"key_insight": "Banking leverage is dangerous, but a panic can still create an extraordinary opportunity when franchise quality and management discipline are exceptional."
}
FILE:company_cards/LZ_2010.json
{
"ticker": "LZ",
"company": "The Lubrizol Corporation",
"analysis_year": 2010,
"data_source": "Lubrizol FY2010 10-K, SEC EDGAR; Berkshire 2011 annual report",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.201, "metric_used": "ROE", "years_averaged": "2008-2010 normalized", "pass": true },
"g2_fcf_to_ni": { "value": 1.00, "fcf": 734, "net_income": 733, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.9, "pass": true },
"g4_revenue_trend": { "description": "2010 revenue and earnings rebounded strongly after the crisis. The underlying additive and specialty-chemical franchises did not show structural decay.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin did not show a two-year structural decline. The 2009 downturn was cyclical, and 2010 gross profit recovered meaningfully.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.077, "net_income_m": 733, "ev_m": 9560, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "Lubrizol's additive packages sat inside mission-critical lubricants and engine formulations that required testing, qualification, and OEM acceptance. Customers could switch, but not casually: reformulation risk, certification cost, and performance liability created real switching friction. That turned an industrial-chemical business into something much harder to dislodge than a plain commodity producer.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"net_sales_2010_usd_m": 5421,
"net_income_2010_usd_m": 733,
"operating_cash_flow_2010_usd_m": 945,
"capital_expenditure_2010_usd_m": 210
},
"control_groups": [
{ "ticker": "ASH", "company": "Ashland Inc.", "year": 2011, "gates_failed": ["g3_leverage", "g5_gross_margin_trend"], "conclusion": "PASS — a less focused specialty portfolio with more balance-sheet strain and weaker economics." },
{ "ticker": "FOE", "company": "Ferro Corporation", "year": 2011, "gates_failed": ["g4_revenue_trend", "g6_earnings_yield"], "conclusion": "PASS — more cyclical materials exposure and no Lubrizol-style qualification moat." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire agreed to acquire Lubrizol for $135 per share in 2011.",
"actual_result": "Lubrizol became a durable wholly owned Berkshire operating asset rather than a headline stock-market home run.",
"verdict": "✅ aligned",
"key_insight": "Industrial businesses can qualify as Buffett-grade when customer qualification costs and formulation risk create real switching friction."
}
FILE:company_cards/DVA_2011.json
{
"ticker": "DVA",
"company": "DaVita Inc.",
"analysis_year": 2012,
"data_source": "DaVita FY2011 10-K, SEC EDGAR; Berkshire/DaVita Schedule 13G filed 2012-10-01",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.209, "metric_used": "ROE", "years_averaged": "2009-2011", "pass": true },
"g2_fcf_to_ni": { "value": 1.63, "fcf": 779.9, "net_income": 478.0, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.94, "pass": true },
"g4_revenue_trend": { "description": "Net operating revenue rose from $6.10B in 2009 to $6.44B in 2010 to $6.98B in 2011, supported by recurring dialysis treatments, steady patient growth, and the DSI acquisition. No structural decline was visible in the business.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "For this service-heavy business, operating margin is the more useful proxy. It improved from about 15.4% in 2009 to 15.5% in 2010 to 16.2% in 2011, so there was no two-year deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.041, "net_income_m": 478.0, "ev_m": 11753, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "DaVita had a real moat by 2012: chronic dialysis is a life-sustaining recurring service, patients return multiple times per week, physician relationships matter, local center density improves economics, and only a handful of scaled operators can handle the reimbursement, clinical, and procurement complexity. Rivals could build centers, but replicating DaVita's network density, care protocols, and operating system across markets was much harder.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "DaVita screened expensive on a blunt earnings-yield basis even though the underlying business had recurring demand, strong local density economics, and oligopoly structure.",
"reason_for_low_yield": "The low yield reflected the market's willingness to pay for predictable chronic-care cash flows and a concentrated dialysis market, not pure hype. But the premium also sat alongside reimbursement risk, legal scrutiny, and non-trivial leverage.",
"decision_impact": "This note softens g6 but does not override it. The archived PASS remains because a 4% earnings yield left limited margin of safety for a regulated healthcare-services operator with active federal inquiries."
},
"management_veto": {
"status": "watch",
"summary": "The 2011 10-K disclosed multiple federal inquiries and subpoenas related to physician relationships and Medicaid matters. No proceedings had been initiated, but the governance and regulatory overhang was material enough to keep the case under watch rather than treating management quality as fully clean."
}
},
"metrics_snapshot": {
"net_operating_revenue_2011_usd_m": 6982.2,
"operating_income_2011_usd_m": 1130.8,
"net_income_attributable_2011_usd_m": 478.0,
"operating_cash_flow_2011_usd_m": 1180.0,
"capital_expenditures_2011_usd_m": 400.2,
"cash_2011_usd_m": 365.3,
"long_term_debt_2011_usd_m": 4417.6,
"weighted_avg_basic_shares_2011_m": 94.658,
"market_value_jan_2012_usd_m": 7700,
"berkshire_shares_2012_m": 10.198,
"berkshire_stake_pct_2012": 10.8
},
"control_groups": [
{ "ticker": "FMS", "company": "Fresenius Medical Care AG & Co. KGaA", "year": 2012, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — close industry peer with real scale, but no clearer bargain and a more complicated integrated device-and-services model." },
{ "ticker": "THC", "company": "Tenet Healthcare Corporation", "year": 2012, "gates_failed": ["g3_leverage", "g7_moat"], "conclusion": "PASS — hospital-system economics were more levered, less recurring, and less protected than DaVita's chronic dialysis franchise." }
],
"conclusion": "PASS",
"buffett_action": "By September 21, 2012 Berkshire reported beneficial ownership of 10,197,569 DaVita shares, or 10.8% of the company, via Schedule 13G.",
"actual_result": "DaVita went on to become a long-duration Berkshire healthcare holding, and Berkshire's ownership percentage later climbed much higher as the company kept repurchasing stock.",
"verdict": "❌ framework_wrong",
"key_insight": "DaVita extends the g6 problem beyond brands and ratings: a dense, recurring, regulated healthcare-service oligopoly can still compound even when a blunt earnings-yield screen says the stock is too expensive."
}
FILE:company_cards/PFE_2019.json
{
"ticker": "PFE",
"company": "Pfizer Inc.",
"analysis_year": 2020,
"data_source": "Pfizer FY2019 10-K, Pfizer Q3 2020 10-Q, Berkshire 2020-09-30 13F-HR, and Berkshire 2021-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.244, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": 1.2, "fcf": 10408, "net_income": 8686, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/2019 EBITDA proxy", "value": 2.09, "pass": true },
"g4_revenue_trend": { "description": "Revenue moved from $52.55B in 2017 to $53.65B in 2018 and $51.75B in 2019. The top line was not collapsing, but it also was not showing the kind of unmistakable structural compounding Buffett usually wants. By late 2020 the company was still reshaping itself around Upjohn and a broad drug portfolio rather than demonstrating a clean secular growth runway.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin improved rather than deteriorated: roughly 78.6% in 2017, 79.0% in 2018, and 80.3% in 2019 based on revenue less cost of goods and services sold. There was no two-year margin erosion.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.0335, "net_income_m": 8686, "ev_m": 258976, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Pfizer had immense scale, commercial reach, and scientific capability, but the enterprise in late 2020 was still a broad portfolio of patent-driven drug assets rather than a single Buffett-style tollbooth. Competitors could not replicate its global organization overnight, yet the economics still depended on continuous pipeline renewal, lifecycle management, and portfolio reshaping. That is good enough for a tactical pharma basket, but not for the kind of decade-long irreplicable moat this framework wants in a permanent core holding.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"sales_2019_usd_m": 51750,
"net_income_2019_usd_m": 16273,
"operating_cash_flow_2019_usd_m": 12588,
"capital_expenditures_2019_usd_m": 2176,
"cash_2020q3_usd_m": 1587,
"short_term_investments_2020q3_usd_m": 8912,
"debt_2020q3_usd_m": 63148,
"ttm_net_income_2020q3_usd_m": 8686,
"ttm_operating_cash_flow_2020q3_usd_m": 12547,
"ttm_capex_2020q3_usd_m": 2139,
"implied_price_2020q3_usd": 36.7,
"market_value_2020q3_usd_m": 206327,
"berkshire_shares_2020q3_m": 3.712,
"berkshire_value_2020q3_usd_m": 136.2
},
"control_groups": [
{ "ticker": "GSK", "company": "GlaxoSmithKline plc", "year": 2020, "gates_failed": ["g1_roe_roic", "g4_revenue_trend", "g7_moat"], "conclusion": "PASS — another global pharma incumbent, but weaker recent economics and an equally portfolio-driven moat profile." },
{ "ticker": "SNY", "company": "Sanofi", "year": 2020, "gates_failed": ["g4_revenue_trend", "g6_earnings_yield", "g7_moat"], "conclusion": "PASS — large diversified pharma peer, but not a cleaner decade-long franchise and not obviously cheap enough to underwrite around those limits." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire disclosed 3,711,780 Pfizer shares worth about $136.2M at September 30, 2020 via its 13F-HR.",
"actual_result": "Pfizer quickly proved to be a small, tactical healthcare basket position rather than a defining Berkshire compounder; the stake no longer appeared in Berkshire's 2021-12-31 13F.",
"verdict": "⭐ framework_wins",
"key_insight": "A profitable large-cap drug company can still be a pass when the moat is portfolio-based rather than structurally irreplicable and the earnings yield is only about 3%."
}
FILE:company_cards/COST_1999.json
{
"ticker": "COST",
"company": "Costco Wholesale Corporation",
"analysis_year": 2000,
"data_source": "Costco FY2001 annual report / 10-K (using point-in-time 1999 financials disclosed therein), SEC EDGAR; Berkshire 1999-12-31 and 2000-03-31 13F-HR/A; 2000 AGM Q&A",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.131, "metric_used": "ROE", "years_averaged": "1997-1999", "pass": true },
"g2_fcf_to_ni": { "value": 0.39, "fcf": 152.9, "net_income": 397.3, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.44, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $23.2B to $25.8B to $27.5B across 1997-1999. Unit growth, membership fees, and same-store traffic all pointed to expansion rather than structural decline.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Reported gross margin was intentionally thin but stable. Costco's merchandise margin hovered around the low-10% range while membership-fee economics supported overall profitability; there was no two-year structural deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.017, "net_income_m": 397.3, "ev_m": 23548, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "Costco had a real moat by 1999: a membership model that reinforced loyalty, extreme SKU discipline, rapid inventory turns, vendor purchasing power, low shrink, and a reputation for passing savings to customers instead of maximizing markups. Rivals could copy pieces of the model, but not the culture-and-scale system that made Costco trusted, efficient, and habit-forming.", "pass": true }
},
"special_channel": null,
"review_notes": {
"owner_earnings_note": {
"summary": "Raw free cash flow understated the economics because Costco was still opening clubs, funding logistics, and expanding internationally at a high rate.",
"maintenance_vs_growth_view": "A material share of 1999 capital spending was growth capex tied to new warehouses and infrastructure, not merely maintenance required to stand still.",
"decision_impact": "This archived PASS remains for comparability, but the note records that g2 was too blunt for an elite reinvestment machine like Costco."
},
"quality_multiple_note": {
"summary": "Costco screened expensive on a blunt earnings-yield basis even before the business reached its later cultural iconic status.",
"reason_for_low_yield": "The market was already paying for membership economics, cost leadership, and exceptional trust, but that premium turned out to be justified by the durability of the franchise.",
"decision_impact": "This is another case where a flat 6% earnings-yield hurdle missed a business whose long runway and moat quality were better than the raw multiple suggested."
},
"management_veto": {
"status": "clear",
"summary": "Management and culture were strengths, not red flags. The underwriting disagreement is about interpreting reinvestment and premium valuation, not stewardship quality."
}
},
"metrics_snapshot": {
"revenue_1999_usd_m": 27456.0,
"operating_income_1999_usd_m": 860.1,
"net_income_1999_usd_m": 397.3,
"operating_cash_flow_1999_usd_m": 940.9,
"capital_expenditures_1999_usd_m": 787.9,
"cash_1999_usd_m": 440.6,
"long_term_debt_1999_usd_m": 918.9,
"berkshire_shares_q1_2000_m": 0.71,
"berkshire_market_value_q1_2000_usd_m": 37.3
},
"control_groups": [
{ "ticker": "KM", "company": "Kmart Corporation", "year": 2000, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — Kmart lacked Costco's discipline, customer trust, and purchasing-system moat, and its economics were already deteriorating." },
{ "ticker": "BJ", "company": "BJ's Wholesale Club, Inc.", "year": 2000, "gates_failed": ["g6_earnings_yield", "g7_moat"], "conclusion": "PASS — the warehouse-club idea was real, but the scale, vendor leverage, and member mindshare were still much weaker than Costco's." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire first disclosed 355,000 Costco shares at year-end 1999 and 710,000 shares by March 31, 2000, with the Q1 position valued at about $37.3M.",
"actual_result": "Costco went on to become one of the clearest long-duration compounders in global retail, even though Berkshire's position remained small relative to the opportunity and was later exited decades after massive business progress.",
"verdict": "❌ framework_wrong",
"key_insight": "Costco is a clean example of why raw FCF and blunt earnings-yield gates can miss a rare reinvestment-heavy compounder with an unusually deep culture-and-scale moat."
}
FILE:company_cards/CCC_1985.json
{
"ticker": "CCC",
"company": "Capital Cities/ABC",
"analysis_year": 1985,
"data_source": "Berkshire Hathaway 1984 and 1986 shareholder letters",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROE", "years_averaged": "1983-1985", "pass": null },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/Capital", "value": null, "pass": null },
"g4_revenue_trend": { "description": "Capital Cities was a high-quality broadcasting franchise with strong economics; Buffett's emphasis was on management quality and the enduring value of its media assets.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "The business was admired for disciplined operations and strong media economics rather than showing any obvious sign of margin erosion.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "PASS", "moat_type": "network_effect", "description": "Capital Cities/ABC combined scarce broadcast assets, local advertising strength, and extraordinary management under Tom Murphy and Dan Burke. Buffett repeatedly stressed that management was tops in both ability and integrity, and the business itself enjoyed the economics that only a handful of media franchises had in that era.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"berkshire_purchase_shares_m": 3,
"purchase_price_per_share": 172.5,
"purchase_cost_m": 517.5
},
"control_groups": [
{ "ticker": "CBS", "company": "CBS", "year": 1985, "gates_failed": ["g7_moat"], "conclusion": "PASS — good assets, but not the same management or capital-allocation quality that distinguished Capital Cities." },
{ "ticker": "TIMESMIRROR", "company": "Times Mirror", "year": 1985, "gates_failed": ["g7_moat"], "conclusion": "PASS — strong media properties, but not the same rare operator-plus-asset combination." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire agreed in 1985 to buy 3M shares of Capital Cities at $172.50 as part of the Capital Cities/ABC transaction.",
"actual_result": "A major long-term winner and one of Berkshire's great media investments.",
"verdict": "✅ aligned",
"key_insight": "When extraordinary operators are matched with scarce media assets, Buffett is willing to act even without flashy short-term numbers."
}
FILE:company_cards/BRKTEXTILE_1965.json
{
"ticker": "BRKTEXTILE",
"company": "Berkshire Hathaway textile operations",
"analysis_year": 1965,
"data_source": "Berkshire Hathaway 2014 special letter 'Berkshire – Past, Present and Future' and Berkshire 1972/1976 shareholder letters",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROE", "years_averaged": "1955-1964", "pass": false },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/Equity", "value": 0.114, "pass": true },
"g4_revenue_trend": { "description": "The New England textile industry had been in long-term decline for decades. Berkshire's own 1954 board minutes said the trend must continue until supply and demand balanced.", "structural_decline": true, "pass": false },
"g5_gross_margin_trend": { "description": "By Buffett's later description, return on sales and return on capital employed were inadequate and the company had already suffered years of operating losses before control changed hands.", "declining_2plus_years": true, "pass": false },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Berkshire textile had no durable competitive advantage. It was a capital-intensive commodity manufacturer in a region losing cost competitiveness, unable to change the industry's direction even though the problems were long understood.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"share_price_1962": 7.5,
"working_capital_per_share_1962": 10.25,
"book_value_per_share_1962": 20.2,
"net_worth_1964_m": 22,
"bank_debt_1964_m": 2.5
},
"control_groups": [
{ "ticker": "JPSTEVENS", "company": "J.P. Stevens", "year": 1965, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — same structurally declining textile economics with no moat." },
{ "ticker": "BURL", "company": "Burlington Industries", "year": 1965, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — a larger operator, but still trapped in a deteriorating commodity textile industry." }
],
"conclusion": "PASS",
"buffett_action": "Buffett Partnership took control of Berkshire Hathaway in 1965 after accumulating 392,633 shares.",
"actual_result": "Buffett later called the decision monumentally stupid and eventually shut the textile operation in 1985 after two decades of frustration.",
"verdict": "⭐ framework_wins",
"key_insight": "Cheap working capital and book value can still be a trap when the business is structurally dying and every dollar stays imprisoned in the operation."
}
FILE:company_cards/BYD_2008.json
{
"ticker": "BYDDF",
"company": "BYD Company Limited",
"analysis_year": 2008,
"data_source": "FY2008 Annual Report (HKEX: 1211), public financial data",
"analyzed_date": "2026-03-12",
"hard_gates": {
"g1_roe_roic": { "value": 0.092, "metric_used": "ROE", "years_averaged": "2008", "pass": false },
"g2_fcf_to_ni": { "value": -0.2, "fcf": -100, "net_income": 180, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 1.8, "pass": true },
"g4_revenue_trend": { "description": "Revenue growing fast — batteries + autos both expanding", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Blended margin improving as higher-margin battery business grows", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.078, "net_income_m": 180, "ev_m": 2320, "exemption": null, "pass": true },
"g7_moat": { "verdict": "SPLIT", "moat_type": "ip", "description": "SPLIT: Battery business has strong IP moat (Wang Chuanfu holds 50+ patents, #1 global NiMH share, 30-40% cost advantage over Japanese competitors via vertical integration). Auto business weak (F3 is Toyota Corolla clone, competing on price only). FORWARD moat: battery+EV integration is the right long-term bet, but the moat hadn't materialized yet in 2008.", "pass": true }
},
"special_channel": "GROWTH_EXCEPTION",
"review_notes": {
"owner_earnings_note": {
"summary": "BYD's negative 2008 free cash flow came from aggressive plant buildout, tooling, and working-capital absorption during expansion, not from a mature business losing economic power.",
"maintenance_vs_growth_view": "Most of the spend looked expansionary rather than maintenance-like. The battery and auto platforms were still being built out, so raw FCF understated owner earnings power.",
"decision_impact": "This note supports why the case needed a named growth exception instead of being rejected mechanically on cash conversion."
},
"management_veto": {
"status": "watch",
"summary": "Wang Chuanfu was exceptional and central to the thesis, but the auto clone risk and execution intensity meant this was not a fully clear governance and capital-allocation setup."
}
},
"metrics_snapshot": {
"revenue_2008_usd_b": 3.5,
"net_income_2008_usd_m": 180,
"book_value_usd_b": 1.95,
"berkshire_paid_usd_m": 230,
"implied_market_cap_usd_b": 2.32,
"pe_ratio": 13,
"pb_ratio": 1.2,
"ps_ratio": 0.7
},
"control_groups": [
{ "ticker": "005380.KS", "company": "Hyundai Motor", "year": 2008, "gates_failed": ["g1_roe_roic", "g7_moat"], "conclusion": "PASS — similar auto exposure, weaker battery IP, no EV thesis" },
{ "ticker": "NSANY", "company": "Nissan", "year": 2008, "gates_failed": ["g2_fcf_to_ni", "g7_moat"], "conclusion": "PASS — legacy automaker, no battery IP, no EV platform" }
],
"conclusion": "BUY",
"buffett_action": "MidAmerican Energy (Berkshire sub) invested $232M for 9.89% at HK$8/share, Sept 2008",
"actual_result": "Berkshire sold entire stake Sept 2025 after 17 years — total return 3,890% (~40x)",
"verdict": "✅ aligned",
"key_insight": "GROWTH_EXCEPTION applied: ROE 9.2% and negative FCF triggered hard gates, but both explained by rapid expansion capex — not structural weakness. Battery IP moat + exceptional founder + Graham-level valuation (13x PE, 1.2x book) + credible EV thesis justified exception. This is Munger's investment, not classic Buffett — 'bet on the horseman, not the horse.'"
}
FILE:company_cards/MDLZ_2019.json
{
"ticker": "MDLZ",
"company": "Mondelez International, Inc.",
"analysis_year": 2020,
"data_source": "Mondelez FY2019 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.128, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": 0.782, "fcf": 3040, "net_income": 3885, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 3.59, "pass": true },
"g4_revenue_trend": { "description": "Revenue held roughly flat around $25.9B across 2017-2019. The business was mature, but there was no visible structural decline in the snack portfolio by late 2020.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin improved from about 38.7% in 2017 to 39.9% in 2018 and 40.0% in 2019. Margin quality was stable to better, not worse.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.038, "net_income_m": 3885, "ev_m": 101336, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Mondelez had a real brand and distribution moat in global snacks, with scaled shelf presence and consumer habit. The issue was not moat absence, but whether a mature branded-food asset at that price still met a Buffett-style return hurdle.", "pass": true }
},
"special_channel": null,
"review_notes": {
"owner_earnings_note": {
"summary": "The modest g2 miss does not signal a broken business; it reflects a mature branded-food company whose cash conversion was fine but not exceptional after capex and working capital.",
"maintenance_vs_growth_view": "Capex was not wildly expansionary, so this is closer to a genuine mediocre conversion signal than a Wal-Mart-style reinvestment distortion.",
"decision_impact": "The g2 fail is real enough to keep on the record, and it combines with a low earnings yield to hold the conclusion at PASS."
},
"quality_multiple_note": {
"summary": "Mondelez traded on a premium consumer-staples multiple because the market valued its global snack portfolio and defensive cash flows.",
"reason_for_low_yield": "The low yield reflected quality and scarcity, but also a world where many branded staples already traded at compressed expected returns.",
"decision_impact": "The note explains the valuation backdrop without overturning the PASS."
},
"management_veto": {
"status": "clear",
"summary": "No management veto applied. The debate is about adequate return at the paid price, not trust in stewardship."
}
},
"control_groups": [
{ "ticker": "KHC", "company": "The Kraft Heinz Company", "year": 2020, "gates_failed": ["g4_revenue_trend", "g5_gross_margin_trend"], "conclusion": "PASS — another large food company, but with much more visible franchise decay." },
{ "ticker": "CPB", "company": "Campbell Soup Company", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — stable business, but without Mondelez's global snack position." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 578,000 Mondelez shares worth about $33.8M at 2020-12-31 in its 13F-HR.",
"actual_result": "The small position remained unchanged at 578,000 shares through 2021-12-31 and 2022-12-31. It behaved more like a legacy or tracker position than a major Berkshire thesis.",
"verdict": "⭐ framework_wins",
"key_insight": "Mature consumer brands can be perfectly sound businesses and still fail the framework when cash conversion is merely okay and the starting earnings yield is under 4%."
}
FILE:company_cards/DEXTER_1993.json
{
"ticker": "DEXTER",
"company": "Dexter Shoe Company",
"analysis_year": 1993,
"data_source": "Berkshire Hathaway 2014 special letter 'Berkshire – Past, Present and Future'",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROIC", "years_averaged": "1990-1993", "pass": null },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": null, "pass": null },
"g4_revenue_trend": { "description": "Dexter's historical record looked strong at the time of purchase. The hidden problem was not visible revenue collapse but an industry structure vulnerable to foreign competition.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "The business looked healthy in 1993; the failure came from moat evaporation rather than an already obvious multi-year margin collapse.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Dexter looked like a fine shoe maker, but it did not possess a structural moat against foreign competition. If low-cost overseas manufacturers can erase your cost position and consumers are not deeply attached to your brand, the economics are not durable enough for Buffett-style permanence.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"purchase_price_1993_m": 433,
"opportunity_cost_2014_m": 5700
},
"control_groups": [
{ "ticker": "WWW", "company": "Wolverine World Wide", "year": 1993, "gates_failed": ["g7_moat"], "conclusion": "PASS — a capable operator, but the industry moat problem was the same." },
{ "ticker": "SRR", "company": "Stride Rite", "year": 1993, "gates_failed": ["g7_moat"], "conclusion": "PASS — brand recognition existed, but not enough to stop global sourcing pressure from overwhelming manufacturing economics." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire bought Dexter in 1993, paying $433M with Berkshire shares.",
"actual_result": "The business value quickly went to zero while the Berkshire shares used as currency later became worth roughly $5.7B.",
"verdict": "⭐ framework_wins",
"key_insight": "A company can have a terrific past record and still fail the moat test if globalization can erase its economics."
}
FILE:company_cards/NICO_1967.json
{
"ticker": "NICO",
"company": "National Indemnity Company",
"analysis_year": 1967,
"data_source": "Berkshire Hathaway 2017 annual report and 2014 special letter",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROE", "years_averaged": "1967 acquisition economics", "pass": null },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Float/Tangible Net Worth", "value": 2.9, "pass": true },
"g4_revenue_trend": { "description": "Buffett later disclosed that premium volume at National Indemnity and its sister operations was $22M in 1967 and grew dramatically over time without new Berkshire shares being issued.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "The attraction was disciplined underwriting, not aggressive premium growth. Buffett described the business as one that usually delivered an underwriting profit.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.221, "net_income_m": 1.9, "ev_m": 8.6, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "National Indemnity's moat was disciplined underwriting culture plus the structural advantage of insurance float. Buffett was effectively paying a modest premium over tangible net worth for a business that usually earned an underwriting profit while delivering investable float equal to almost three times that net worth. That combination created a financing advantage most industrial businesses simply do not have.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"purchase_price_1967_m": 8.6,
"tangible_net_worth_1967_m": 6.7,
"float_1967_m": 19.4,
"premium_volume_1967_m": 22
},
"control_groups": [
{ "ticker": "TRV", "company": "Travelers", "year": 1967, "gates_failed": ["g7_moat"], "conclusion": "PASS — large insurer, but without the same owner-operator purchase economics or uniquely attractive float-to-price relationship." },
{ "ticker": "AET", "company": "Aetna Casualty", "year": 1967, "gates_failed": ["g7_moat"], "conclusion": "PASS — a respectable insurer, but not available on anything like National Indemnity's purchase terms." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire bought National Indemnity and a smaller sister company for $8.6M in early 1967.",
"actual_result": "The foundational Berkshire acquisition. Insurance float became the engine that financed decades of compounding.",
"verdict": "✅ aligned",
"key_insight": "Buffett was not just buying earnings; he was buying a conservative underwriting machine attached to permanently reusable capital."
}
FILE:company_cards/LIVE_600900SH_2026.json
{
"analysis_scope": "live",
"ticker": "600900.SH",
"company": "China Yangtze Power Co., Ltd.",
"analysis_year": 2026,
"data_source": "Yangtze Power 2024 annual report (published 2025-04-30), company investor-relations disclosures for 2025 Q1/H1/Q3, and market valuation data available through 2026-03-12",
"analyzed_date": "2026-03-24",
"hard_gates": {
"g1_roe_roic": {
"value": 0.1285,
"metric_used": "ROE",
"years_averaged": "2022-2024",
"pass": true
},
"g2_fcf_to_ni": {
"value": 1.39,
"fcf": 45228.0,
"net_income": 32496.0,
"pass": true
},
"g3_leverage": {
"metric_used": "Net Debt/EBITDA",
"value": 4.48,
"pass": false
},
"g4_revenue_trend": {
"description": "Revenue rose from RMB 68.86bn in 2022 to RMB 78.11bn in 2023 and RMB 84.49bn in 2024. 2025 disclosed Q1/H1/Q3 earnings remained stable to improving.",
"structural_decline": false,
"pass": true
},
"g5_gross_margin_trend": {
"description": "Hydropower gross margin improved from about 59.74% in 2022 to 60.97% in 2023 and 62.51% in 2024; no multi-year deterioration.",
"declining_2plus_years": false,
"pass": true
},
"g6_earnings_yield": {
"value": 0.0339,
"net_income_m": 32496.0,
"ev_m": 958303.0,
"exemption": "INFRA_EXEMPTION",
"pass": false
},
"g7_moat": {
"verdict": "PASS",
"moat_type": "monopoly",
"description": "Yangtze Power owns and operates the core cascade assets of the world's largest hydropower corridor. These are irreplaceable strategic assets with dispatch advantages, low variable costs, state-backed importance, and decades-long remaining lives. In China, this is as close as a listed utility gets to a true monopoly moat.",
"pass": true
}
},
"special_channel": "INFRA_EXEMPTION",
"review_notes": {
"quality_multiple_note": {
"summary": "Yangtze Power deserves a quality premium because it owns irreplaceable hydropower assets and sits close to a listed monopoly in China.",
"reason_for_low_yield": "The low yield reflects genuine infrastructure quality, but also a price that has already moved near the upper end of what the infra-exemption should tolerate once leverage is considered.",
"decision_impact": "This note explains why the company is a great asset yet still a PASS today: the quality is real, but the valuation and leverage do not leave enough safety margin."
},
"management_veto": {
"status": "clear",
"summary": "No integrity or capital-allocation veto is visible from the public disclosures used here; the constraint is price and balance-sheet load, not stewardship trust."
}
},
"control_groups": [
{
"ticker": "600025.SH",
"company": "Huaneng Lancang River Hydropower Inc.",
"year": 2026,
"gates_failed": ["g1_roe_roic", "g2_fcf_to_ni", "g3_leverage", "g6_earnings_yield"],
"conclusion": "PASS — still a good hydro asset, but ROE is only about 11.28%, free cash flow is negative, leverage is 6.43x debt/EBITDA, and EV/EBITDA is above the infra-exemption boundary."
},
{
"ticker": "600886.SH",
"company": "SDIC Power Holdings Co., Ltd.",
"year": 2026,
"gates_failed": ["g1_roe_roic", "g3_leverage", "g6_earnings_yield", "g7_moat"],
"conclusion": "PASS — mixed hydro/thermal/new energy portfolio lacks Yangtze Power's monopoly position, while ROE is about 10.37% and debt/EBITDA is 5.65x."
}
],
"conclusion": "PASS",
"buffett_action": "N/A — live analysis, not a Berkshire historical backtest case",
"actual_result": "Open",
"verdict": "N/A",
"key_insight": "This is one of the best infrastructure assets in A-shares, but even great regulated monopolies become mediocre investments when leverage is high and the price moves to the top end of the fair range."
}
FILE:company_cards/MRK_2019.json
{
"ticker": "MRK",
"company": "Merck & Co., Inc.",
"analysis_year": 2020,
"data_source": "Merck FY2019 10-K, Merck Q3 2020 10-Q, Berkshire 2020-09-30 13F-HR, and Berkshire 2021-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.226, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": 0.58, "fcf": 6734, "net_income": 11517, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 1.27, "pass": true },
"g4_revenue_trend": { "description": "Sales rose from $40.12B in 2017 to $42.29B in 2018 to $46.84B in 2019, and nine-month 2020 sales of $35.48B were still above the comparable 2019 period. The business was not in structural decline at the decision point.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin improved rather than deteriorated: roughly 67.8% in 2017, 68.1% in 2018, and 69.9% in 2019 based on sales less cost of sales. There was no two-year margin erosion.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.05, "net_income_m": 11517, "ev_m": 231248, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Merck had exceptional scientific assets, global scale, and regulatory know-how, but the whole company was still a portfolio of patent-bound drug franchises rather than a single Buffett-style tollbooth. Keytruda was a tremendous asset in 2020, yet competitors could still chip away over time and the company had to keep replenishing its pipeline to defend economics. That is a good business, but not the sort of 10-year irreplicable moat this framework wants for a long-duration core holding.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"sales_2019_usd_m": 46840,
"net_income_2019_usd_m": 9843,
"operating_cash_flow_2019_usd_m": 13440,
"capital_expenditures_2019_usd_m": 3473,
"cash_2020q3_usd_m": 7356,
"debt_2020q3_usd_m": 28741,
"ttm_net_income_2020q3_usd_m": 11517,
"ttm_operating_cash_flow_2020q3_usd_m": 11041,
"ttm_capex_2020q3_usd_m": 4307,
"implied_price_2020q3_usd": 82.95,
"market_value_2020q3_usd_m": 209863,
"berkshire_shares_2020q3_m": 22.403,
"berkshire_value_2020q3_usd_m": 1858.3
},
"control_groups": [
{ "ticker": "PFE", "company": "Pfizer Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — large-scale pharma peer, but the legacy portfolio and transaction-driven reshaping made the moat even less clean than Merck's." },
{ "ticker": "GSK", "company": "GlaxoSmithKline plc", "year": 2020, "gates_failed": ["g1_roe_roic", "g4_revenue_trend", "g7_moat"], "conclusion": "PASS — another global pharma incumbent, but weaker recent economics and no clearer decade-long moat." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire disclosed 22,403,102 Merck shares worth about $1.86B at September 30, 2020 via its 13F-HR.",
"actual_result": "Merck remained a strong pharmaceutical company, but Berkshire did not turn the stake into a permanent core holding; by the 2021-12-31 13F the position no longer appeared.",
"verdict": "⭐ framework_wins",
"key_insight": "A high-quality drug company can still be a pass if current cash conversion is soft, the earnings yield is only average, and the moat depends on continual pipeline renewal rather than a single irreplicable franchise."
}
FILE:company_cards/BAC_2010.json
{
"ticker": "BAC",
"company": "Bank of America",
"analysis_year": 2011,
"data_source": "FY2010 10-K, SEC EDGAR",
"analyzed_date": "2026-03-11",
"hard_gates": {
"g1_roe_roic": { "value": -0.01, "metric_used": "ROE", "years_averaged": "2010", "pass": false },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": -2238, "pass": null },
"g3_leverage": { "metric_used": "Tier1", "value": 0.086, "pass": true },
"g4_revenue_trend": { "description": "Revenue $111.4B, structurally intact. Loss driven by $10.4B non-cash goodwill impairment.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Core margins stable", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": -2238, "ev_m": null, "exemption": "CRISIS_PREFERRED", "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "#1 US retail bank by deposits. $1T in consumer deposits with auto-pay, direct deposit, mortgage lock-in. Switching cost is behavioral inertia across millions of customers. Moat is INTACT — this is a crisis of confidence, not a broken business.", "pass": true }
},
"special_channel": "CRISIS_PREFERRED",
"metrics_snapshot": {
"total_assets_b": 2265,
"deposits_b": 1010,
"tangible_book_value_per_share": 12.98,
"stock_price_at_deal": 6.99,
"tbv_discount_pct": 0.46,
"tier1_common_ratio": 0.086
},
"control_groups": [
{ "ticker": "C", "company": "Citigroup", "year": 2011, "gates_failed": ["g5_gross_margin_trend"], "conclusion": "PASS — more complex international exposure, asset quality worse, deal terms not available" },
{ "ticker": "MS", "company": "Morgan Stanley", "year": 2011, "gates_failed": ["g1_roe_roic"], "conclusion": "PASS — ROE near zero, no TBTF retail franchise equivalent" }
],
"conclusion": "BUY",
"buffett_action": "$5B in 6% perpetual preferred + warrants for 700M shares at $7.14 (10-year)",
"actual_result": "~$3B in preferred dividends collected + warrants converted in 2017 at ~$24/share = ~$12B+ total return",
"verdict": "✅ aligned",
"key_insight": "Stock at 54% of tangible book value ($6.99 vs $12.98 TBV). Crisis preferred structure: 6% yield protects downside, warrants capture upside. The Countrywide tail risk was real but finite relative to $2.26T balance sheet."
}
FILE:company_cards/AMZN_2019.json
{
"ticker": "AMZN",
"company": "Amazon.com, Inc.",
"analysis_year": 2020,
"data_source": "Amazon FY2019 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.176, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": 0.733, "fcf": 8496, "net_income": 11588, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.08, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $177.9B in 2017 to $232.9B in 2018 to $280.5B in 2019. At late-2020 visibility there was no structural decline risk; the business was still compounding across e-commerce, AWS, and third-party services.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Amazon's reported cost buckets are noisy because fulfillment and technology spending sit below gross profit, but the business mix was moving toward higher-margin AWS, advertising, and marketplace services rather than showing a two-year deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.007, "net_income_m": 11588, "ev_m": 1637050, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "network_effect", "description": "Amazon clearly had a moat by late 2020: fulfillment scale, Prime membership lock-in, merchant density, AWS infrastructure, and a data flywheel that few competitors could replicate. The issue was not moat quality but whether any Buffett-style margin of safety remained at that price.", "pass": true }
},
"special_channel": null,
"review_notes": {
"owner_earnings_note": {
"summary": "Raw free cash flow understated economics because Amazon was still plowing massive amounts into logistics, data centers, and ecosystem expansion.",
"maintenance_vs_growth_view": "A large share of 2019 capex was expansionary rather than maintenance-like. That makes the mechanical g2 fail directionally useful but too blunt.",
"decision_impact": "The note softens the interpretation of g2, but it does not rescue the case because valuation was still far beyond the framework's hurdle."
},
"quality_multiple_note": {
"summary": "The very low earnings yield mainly reflected extraordinary market confidence in Amazon's future growth and moat depth.",
"reason_for_low_yield": "This was genuine quality scarcity, not hype alone, but the paid price still required years of continued excellent execution.",
"decision_impact": "Oracle keeps the PASS because Buffett-style underwriting still wants a clearer margin of safety than a sub-1% earnings yield."
},
"management_veto": {
"status": "clear",
"summary": "Management quality was not the problem. The rejection is a price-discipline call against a superb business."
}
},
"control_groups": [
{ "ticker": "EBAY", "company": "eBay Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — weaker ecosystem control and much less strategic breadth than Amazon." },
{ "ticker": "JD", "company": "JD.com, Inc.", "year": 2020, "gates_failed": ["g2_fcf_to_ni", "g3_leverage"], "conclusion": "PASS — scale was real, but economics and balance-sheet quality were less settled than Amazon's." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 419,500 pre-split Amazon shares worth about $1.37B at 2020-12-31 in its 13F-HR.",
"actual_result": "The stake stayed small through 2021 and, after Amazon's 20-for-1 split, still amounted to only 8.39M shares at 2022-12-31. Berkshire never turned it into a defining top-tier Buffett-style core holding.",
"verdict": "⭐ framework_wins",
"key_insight": "A truly great business can still be a pass when reinvestment muddies raw free cash flow and the market is already capitalizing years of future success."
}
FILE:company_cards/GS_2007.json
{
"ticker": "GS",
"company": "Goldman Sachs",
"analysis_year": 2008,
"data_source": "FY2007 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.327, "metric_used": "ROE", "years_averaged": "2005-2007", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 11600, "pass": null },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 26.0, "pass": false },
"g4_revenue_trend": { "description": "Strong pre-crisis growth", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Strong margins pre-crisis", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": "CRISIS_PREFERRED", "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Top-tier investment bank brand, talent density, deal flow access. TBTF status provides implicit government backstop.", "pass": true }
},
"special_channel": "CRISIS_PREFERRED",
"control_groups": [
{ "ticker": "LEH", "company": "Lehman Brothers", "year": 2008, "gates_failed": ["g7_moat", "g3_leverage"], "conclusion": "PASS — filed bankruptcy, would have been total loss" },
{ "ticker": "MS", "company": "Morgan Stanley", "year": 2008, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — deal terms not as favorable, weaker position than GS" }
],
"conclusion": "BUY",
"buffett_action": "$5B in 10% perpetual preferred + warrants for 50M shares at $115",
"actual_result": "GS paid $500M premium to redeem preferred + warrants generated large gains. Total return ~$3.7B+",
"verdict": "✅ aligned",
"key_insight": "Crisis preferred channel: standard gates don't apply. Key questions are (1) TBTF? (2) Does preferred yield adequately compensate? (3) Fundamentally solvent? GS: yes to all three. Lehman: no to #3. The TBTF filter is the differentiator."
}
FILE:company_cards/BIIB_2019.json
{
"ticker": "BIIB",
"company": "Biogen Inc.",
"analysis_year": 2020,
"data_source": "Biogen FY2019 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.332, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": 1.115, "fcf": 6564, "net_income": 5889, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.85, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $12.27B in 2017 to $13.45B in 2018 to $14.38B in 2019. The near-term issue was product concentration and pipeline durability, not an already-visible structural collapse.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Product economics stayed very high; nothing in the pre-2021 public numbers showed a two-year structural margin deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.133, "net_income_m": 5889, "ev_m": 44380, "exemption": null, "pass": true },
"g7_moat": { "verdict": "FAIL", "moat_type": "ip", "description": "Biogen had important neurology assets and scientific depth, but the whole company still depended on a relatively narrow portfolio and ongoing R&D renewal. That is a good biotech platform, not a decade-long Buffett tollbooth whose economics are easy to describe and hard to copy.", "pass": false }
},
"special_channel": null,
"control_groups": [
{ "ticker": "GILD", "company": "Gilead Sciences, Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — similarly profitable, but the franchise already showed more visible product concentration and revenue pressure." },
{ "ticker": "TEVA", "company": "Teva Pharmaceutical Industries Limited", "year": 2020, "gates_failed": ["g1_roe_roic", "g3_leverage", "g4_revenue_trend", "g7_moat"], "conclusion": "PASS — weaker balance sheet and much less dependable economics." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 643,022 Biogen shares worth about $157.5M at 2020-12-31 in its 13F-HR.",
"actual_result": "The position was still there at 2021-03-31, but it no longer appeared by 2021-12-31. It behaved like a tactical biotech allocation rather than a lasting Buffett franchise bet.",
"verdict": "⭐ framework_wins",
"key_insight": "A biotech can screen cheaply and still fail Buffett-style underwriting if moat durability depends on continually replacing a narrow product portfolio."
}
FILE:company_cards/HPQ_2021.json
{
"ticker": "HPQ",
"company": "HP Inc.",
"analysis_year": 2022,
"data_source": "FY2021 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.35, "metric_used": "ROIC", "years_averaged": "2019-2021", "pass": true },
"g2_fcf_to_ni": { "value": 1.13, "fcf": 3500, "net_income": 3100, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.8, "pass": true },
"g4_revenue_trend": { "description": "Growing during COVID WFH cycle", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Print operating margin 18.1%, stable", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.093, "net_income_m": 3100, "ev_m": 33000, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "Print consumables (ink/toner) create recurring revenue moat — corporate customers locked in by proprietary cartridge systems. $12.6B supplies revenue is stickier than hardware.", "pass": true }
},
"special_channel": null,
"control_groups": [
{ "ticker": "XRX", "company": "Xerox", "year": 2021, "gates_failed": ["g4_revenue_trend"], "conclusion": "PASS" },
{ "ticker": "DELL", "company": "Dell Technologies", "year": 2022, "gates_failed": [], "conclusion": "BUY — false positive, needs deeper moat analysis to differentiate from HP" }
],
"conclusion": "BUY",
"buffett_action": "Bought $4.2B at ~$34.70/share (~11% stake)",
"actual_result": "Neutral — Berkshire gradually reduced position",
"verdict": "✅ aligned",
"key_insight": "Note Dell false positive: hard gates alone cannot differentiate HP's consumables moat from Dell's commodity assembly business — moat analysis is the differentiator."
}
FILE:company_cards/MCO_2001.json
{
"ticker": "MCO",
"company": "Moody's Corporation",
"analysis_year": 2001,
"data_source": "Moody's FY2001 10-K, SEC EDGAR; Berkshire 2001 annual report",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.34, "metric_used": "ROIC", "years_averaged": "1999-2001 adjusted for buyback-distorted equity", "pass": true },
"g2_fcf_to_ni": { "value": 1.37, "fcf": 291.5, "net_income": 212.2, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.33, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $564.2M to $602.3M to $796.7M, driven by expanding structured finance, corporate ratings, and international demand. No structural decline was visible.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Operating margin improved from roughly 48% in 2000 to 50% in 2001, with no evidence of a two-year profitability collapse. For this asset-light ratings business, margin structure was strengthening, not weakening.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.03, "net_income_m": 212.2, "ev_m": 6973, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Moody's had a real moat: regulatory entrenchment, reputational trust, issuer habit, global analyst infrastructure, and the self-reinforcing position of being one of the few agencies embedded in the bond market's plumbing. Competitors could not easily replicate the installed role Moody's played in global debt issuance.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "Moody's looked expensive on a blunt earnings-yield basis because the market was already capitalizing a deeply embedded, asset-light ratings tollbooth.",
"reason_for_low_yield": "The low yield reflected regulatory entrenchment, global market infrastructure status, and very low incremental capital needs more than speculative hype.",
"decision_impact": "This note does not change the archived PASS, but it records that g6 is too blunt for elite information-service monopolies."
},
"management_veto": {
"status": "clear",
"summary": "No management-integrity veto was visible in the filed materials. The disagreement here is almost entirely about valuation framework, not trust."
}
},
"metrics_snapshot": {
"revenue_2001_usd_m": 796.7,
"operating_income_2001_usd_m": 398.5,
"net_income_2001_usd_m": 212.2,
"operating_cash_flow_2001_usd_m": 306.3,
"capital_expenditures_2001_usd_m": 14.8,
"cash_2001_usd_m": 163.2,
"notes_payable_2001_usd_m": 300.0,
"berkshire_shares_2001_m": 24.0,
"berkshire_cost_2001_usd_m": 499
},
"control_groups": [
{ "ticker": "MHP", "company": "The McGraw-Hill Companies", "year": 2001, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — Standard & Poor's was excellent, but it sat inside a broader publishing and information conglomerate that did not offer Moody's purity or margins at an obviously cheap price." },
{ "ticker": "DNB", "company": "The New Dun & Bradstreet Corporation", "year": 2001, "gates_failed": ["g1_roe_roic", "g7_moat"], "conclusion": "PASS — useful data assets, but the economics and strategic position were less singular than Moody's post-spin ratings franchise." }
],
"conclusion": "PASS",
"buffett_action": "By year-end 2001 Berkshire held 24.0M Moody's shares with a carrying cost of about $499M and described the business as one of the companies it still liked.",
"actual_result": "Moody's became one of Berkshire's strongest long-duration public-equity winners after the spin-era hold decision, compounding sharply over the following decade.",
"verdict": "❌ framework_wrong",
"key_insight": "The framework still underestimates elite asset-light information monopolies whose quality can justify earnings yields far below a blunt 6% screen."
}
FILE:company_cards/_schema.json
{
"_description": "Schema for Buffett Oracle company cards. One file per company per analysis year.",
"_filename_convention": "TICKER_YEAR.json (e.g., AAPL_2015.json, BAC_2010.json)",
"ticker": "string — stock ticker or identifier",
"company": "string — full company name",
"analysis_year": "integer — year of Buffett's decision",
"data_source": "string — e.g. 'FY2021 10-K, SEC EDGAR'",
"analyzed_date": "string — ISO date when this card was created",
"hard_gates": {
"g1_roe_roic": {
"value": "float — e.g. 0.46 for 46%",
"metric_used": "string — 'ROE' or 'ROIC' (use ROIC if equity is negative/distorted)",
"years_averaged": "string — e.g. '2019-2021'",
"pass": "boolean"
},
"g2_fcf_to_ni": {
"value": "float — FCF divided by Net Income",
"fcf": "float — free cash flow in millions USD",
"net_income": "float — net income in millions USD",
"pass": "boolean"
},
"g3_leverage": {
"metric_used": "string — 'Net Debt/EBITDA' or 'Tier1' for banks",
"value": "float",
"pass": "boolean"
},
"g4_revenue_trend": {
"description": "string — brief description of trend",
"structural_decline": "boolean — true means FAIL",
"pass": "boolean"
},
"g5_gross_margin_trend": {
"description": "string",
"declining_2plus_years": "boolean — true means FAIL",
"pass": "boolean"
},
"g6_earnings_yield": {
"value": "float — Net Income / EV",
"net_income_m": "float — in millions USD",
"ev_m": "float — enterprise value in millions USD",
"exemption": "string or null — 'INFRA_EXEMPTION' if applied",
"pass": "boolean"
},
"g7_moat": {
"verdict": "string — 'PASS', 'FAIL', or 'SPLIT'",
"moat_type": "string or null — 'brand', 'network_effect', 'switching_cost', 'cost_advantage', 'monopoly', 'ip'",
"description": "string — one paragraph explanation",
"pass": "boolean"
}
},
"special_channel": "string or null — 'CRISIS_PREFERRED', 'INFRA_EXEMPTION', 'GROWTH_EXCEPTION', or null",
"review_notes": {
"owner_earnings_note": {
"summary": "string — required when g2 fails but the moat still passes",
"maintenance_vs_growth_view": "string — distinguish maintenance capex from expansion capex",
"decision_impact": "string — explain whether the raw g2 fail still stands or looks too blunt"
},
"quality_multiple_note": {
"summary": "string — required when g6 fails but the moat still passes",
"reason_for_low_yield": "string — explain whether the low yield reflects genuine quality, strategic scarcity, or simple overpayment",
"decision_impact": "string — explain whether the raw g6 fail still stands or looks too blunt"
},
"management_veto": {
"status": "string — 'clear', 'watch', or 'fail'",
"summary": "string — integrity / capital-allocation assessment"
}
},
"control_groups": [
{
"ticker": "string",
"company": "string",
"year": "integer",
"gates_failed": ["string — list of gates that triggered, e.g. 'g1_roe_roic', 'g4_revenue_trend'"],
"conclusion": "PASS"
}
],
"conclusion": "string — 'BUY' or 'PASS'",
"buffett_action": "string — what Buffett actually did",
"actual_result": "string — brief outcome",
"verdict": "string — '✅ aligned', '⭐ framework_wins', or '❌ framework_wrong'",
"key_insight": "string — one sentence summary of the main lesson"
}
FILE:company_cards/IBM_2011.json
{
"ticker": "IBM",
"company": "International Business Machines",
"analysis_year": 2011,
"data_source": "FY2011 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.25, "metric_used": "ROIC", "years_averaged": "2009-2011", "pass": true },
"g2_fcf_to_ni": { "value": 1.0, "fcf": 15800, "net_income": 15900, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 1.5, "pass": true },
"g4_revenue_trend": { "description": "Aggregate revenue growing, but hardware structurally declining, masked by services growth", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "46% gross margin, slight multi-year decline from mix shift", "declining_2plus_years": true, "pass": false },
"g6_earnings_yield": { "value": 0.072, "net_income_m": 15900, "ev_m": 220000, "exemption": null, "pass": true },
"g7_moat": { "verdict": "FAIL", "moat_type": "switching_cost", "description": "Enterprise IT switching costs are real but eroding. AWS launched 2006, cloud migration undermining on-premise lock-in. IBM's mainframe moat is real for existing customers but new workloads going to cloud. Moat is defending, not growing.", "pass": false }
},
"special_channel": null,
"control_groups": [
{ "ticker": "ORCL", "company": "Oracle", "year": 2011, "gates_failed": [], "conclusion": "BUY — also passes hard gates. Oracle database moat arguably stronger than IBM (more defensible against cloud). Framework correctly identifies both as quality but IBM's moat more at risk." },
{ "ticker": "ACN", "company": "Accenture", "year": 2011, "gates_failed": [], "conclusion": "BUY — also passes. Services moat (talent + client relationships) different from IBM's product moat." }
],
"conclusion": "PASS",
"buffett_action": "Bought ~$12B starting 2011",
"actual_result": "Loss — sold entire position 2018, Buffett: 'I was wrong about IBM'",
"verdict": "⭐ framework_wins",
"key_insight": "Gate ⑦ is forward-looking. Gross margin decline (gate ⑤) was an early warning. The key question is not 'does the moat exist today' but 'is the moat expanding or contracting?' IBM's moat was contracting."
}
FILE:company_cards/AXP_1994.json
{
"ticker": "AXP",
"company": "American Express Company",
"analysis_year": 1994,
"data_source": "American Express 1993 annual report, 1994 Q3 10-Q, and Berkshire 1994 shareholder letter",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.17, "metric_used": "ROE", "years_averaged": "1992-1994 (normalized)", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 1400, "pass": null },
"g3_leverage": { "metric_used": "Total Capital", "value": 0.13, "pass": true },
"g4_revenue_trend": { "description": "1994 reported revenue and core segment profit were growing. TRS billed business, cards-in-force, and IDS fee assets all moved higher after the Lehman/FDC simplification.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Charge-card and travel economics remained stable; discount revenue and pretax profit were expanding while credit provisions were falling.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.094, "net_income_m": 1400, "ev_m": 14900, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "network_effect", "description": "American Express combined a premium global brand, a closed-loop merchant-and-cardmember network, and strong corporate travel/payment relationships. Merchants wanted affluent spend, cardmembers wanted acceptance and status, and corporate clients were embedded in expense-management workflows. That mix created a real network effect with pricing power and stickiness that commodity card lenders could not replicate.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"trs_billed_business_9m_1994_b": 101.9,
"cards_in_force_m_q3_1994": 35.6,
"trs_net_income_9m_1994_m": 762,
"berkshire_cost_1994_m": 724
},
"control_groups": [
{ "ticker": "SEARS", "company": "Sears / Discover", "year": 1994, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — Discover was useful, but the economics sat inside a weaker retail parent and lacked AmEx's premium closed-loop brand advantage." },
{ "ticker": "MBNA", "company": "MBNA Corporation", "year": 1994, "gates_failed": ["g3_leverage", "g7_moat"], "conclusion": "PASS — strong lender, but far more dependent on funding and commodity credit-card economics than on an enduring network moat." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire enlarged American Express in 1994 and essentially completed the position by 1995 at a total cost of about $1.3B.",
"actual_result": "American Express became a decades-long compounder and remains one of Berkshire's canonical long-term winners.",
"verdict": "✅ aligned",
"key_insight": "Closed-loop payment networks with a premium brand can look like financial companies in the statements but behave like consumer-network franchises in economics."
}
FILE:company_cards/MRSH_2019.json
{
"ticker": "MRSH",
"company": "Marsh & McLennan Companies, Inc.",
"analysis_year": 2020,
"data_source": "Marsh & McLennan FY2019 10-K and Berkshire 2020-12-31 / 2021-03-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.216, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": 1.094, "fcf": 1940, "net_income": 1773, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.87, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $14.0B in 2017 to $15.0B in 2018 to $16.7B in 2019. Advisory and brokerage demand was not in visible structural decline at the decision point.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "For a broker and consultancy, gross margin is less meaningful than operating conversion. Public filings showed stable underlying margin quality rather than a two-year deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.025, "net_income_m": 1773, "ev_m": 69701, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "Marsh had a real moat through client relationships, global placement scale, data, and sticky corporate risk-management workflows. Large commercial clients do not casually rip out their broker, benefits, or consulting relationships.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "Marsh traded on a low earnings yield because the market prized the durability of its client relationships and advisory embedment.",
"reason_for_low_yield": "This was a quality multiple on a real tollbooth-like service franchise, not a low-quality story stock.",
"decision_impact": "The note records that g6 is harsh on this kind of business, but the archived conclusion remains PASS for comparability."
},
"management_veto": {
"status": "clear",
"summary": "There was no capital-allocation or integrity veto. The only issue was paying a premium valuation for a high-quality franchise."
}
},
"control_groups": [
{ "ticker": "AON", "company": "Aon plc", "year": 2020, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — similarly excellent, but also priced too richly for the framework." },
{ "ticker": "WTW", "company": "Willis Towers Watson Public Limited Company", "year": 2020, "gates_failed": ["g3_leverage", "g4_revenue_trend"], "conclusion": "PASS — same broad category, but weaker quality and messier execution than Marsh." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 4,267,825 Marsh & McLennan shares worth about $499.3M at 2020-12-31 in its 13F-HR.",
"actual_result": "The stake actually increased to 5.29M shares by 2021-03-31, but Berkshire had cut it to just 404,911 shares by 2021-12-31 and kept only that token amount at 2022-12-31. It never became a core Berkshire position.",
"verdict": "⭐ framework_wins",
"key_insight": "Some wonderful service tollbooths are simply too expensive for the framework, especially when Berkshire itself treats them more like opportunistic positions than permanent pillars."
}
FILE:company_cards/PARA_2021.json
{
"ticker": "PARA",
"company": "Paramount Global (formerly ViacomCBS)",
"analysis_year": 2022,
"data_source": "FY2021 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.22, "metric_used": "ROE", "years_averaged": "2021", "pass": true },
"g2_fcf_to_ni": { "value": 0.13, "fcf": 600, "net_income": 4500, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 10.0, "pass": false },
"g4_revenue_trend": { "description": "Traditional TV declining, streaming only 14.7% of revenue", "structural_decline": true, "pass": false },
"g5_gross_margin_trend": { "description": "Margins under pressure from streaming investment", "declining_2plus_years": true, "pass": false },
"g6_earnings_yield": { "value": null, "net_income_m": 4500, "ev_m": null, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Paramount+ at 32.8M subs vs Netflix 220M. Traditional TV franchise eroding, streaming moat nonexistent. True liability $44.6B (10x OIBDA) including $32.6B off-balance-sheet content commitments.", "pass": false }
},
"special_channel": null,
"control_groups": [
{ "ticker": "DIS", "company": "Disney", "year": 2021, "gates_failed": ["g1_roe_roic", "g2_fcf_to_ni"], "conclusion": "PASS" },
{ "ticker": "WBD", "company": "Warner Bros Discovery", "year": 2022, "gates_failed": ["g3_leverage"], "conclusion": "PASS" }
],
"conclusion": "PASS",
"buffett_action": "Bought $2.6B in Q1 2022 at ~$38/share",
"actual_result": "Lost $1.6B, sold entire position 2024, Buffett admitted mistake",
"verdict": "⭐ framework_wins",
"key_insight": "FCF/NI of 0.13 is a hard veto — when earnings are 7x higher than cash generation, the profits are fiction."
}
FILE:company_cards/BUD_2005.json
{
"ticker": "BUD",
"company": "Anheuser-Busch Companies, Inc.",
"analysis_year": 2005,
"data_source": "Anheuser-Busch FY2005 annual report, SEC EDGAR; Berkshire 2005 annual report; 2005 Berkshire AGM Q&A",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.582, "metric_used": "ROE", "years_averaged": "2003-2005", "pass": true },
"g2_fcf_to_ni": { "value": 0.90, "fcf": 1565, "net_income": 1744, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.6, "pass": true },
"g4_revenue_trend": { "description": "The U.S. beer market was mature and volumes were flat, but the business was not yet in structural decline. Revenue remained stable and the company retained premium category leadership.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Margin pressure existed, but there was not a clean two-year structural collapse; 2005 margins stabilized versus 2004 after a tougher 2005 operating backdrop.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.046, "net_income_m": 1744, "ev_m": 37900, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "Budweiser and the wider Anheuser portfolio still held very strong consumer mindshare, distribution muscle, and category economics. Buffett said in 2005 that the product was easy to understand and that private-label pressure in beer was unusually limited versus many other consumer categories.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "Anheuser-Busch traded on a low earnings yield because the market was paying for scarce brand power, distribution muscle, and strategic value in global beer.",
"reason_for_low_yield": "The low yield was not pure hype. It reflected a durable brand franchise and the possibility that a strategic buyer would eventually value the asset more highly than a standalone screen would.",
"decision_impact": "The note does not automatically overturn the valuation fail, but it explains why a flat 6% hurdle was too crude for this case."
},
"management_veto": {
"status": "clear",
"summary": "There was no governance veto here. The debate was about valuation discipline versus brand scarcity, not management trust."
}
},
"metrics_snapshot": {
"net_sales_2005_usd_m": 15036,
"net_income_2005_usd_m": 1744,
"operating_cash_flow_2005_usd_m": 2702,
"capex_2005_usd_m": 1137,
"berkshire_cost_2005_usd_m": 2133
},
"control_groups": [
{ "ticker": "TAP", "company": "Molson Coors", "year": 2005, "gates_failed": ["g6_earnings_yield", "g7_moat"], "conclusion": "PASS — meaningful brands, but not the same U.S. category dominance and economics." },
{ "ticker": "HEINY", "company": "Heineken", "year": 2005, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — global brand strength was real, but valuation offered similarly limited margin of safety." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire established an Anheuser-Busch position in 2005 and held 43.9M shares at year-end.",
"actual_result": "InBev agreed to acquire Anheuser-Busch in 2008 for $70 per share in cash, giving Berkshire a solid gain.",
"verdict": "❌ framework_wrong",
"key_insight": "The framework still undershoots some strong brands when a strategic buyer later pays more than the standalone earnings yield would justify."
}
FILE:company_cards/BNI_2008.json
{
"ticker": "BNI",
"company": "Burlington Northern Santa Fe (BNSF Railway)",
"analysis_year": 2009,
"data_source": "FY2008 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.19, "metric_used": "ROE", "years_averaged": "2006-2008", "pass": true },
"g2_fcf_to_ni": { "value": 0.86, "fcf": 1800, "net_income": 2100, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.3, "pass": true },
"g4_revenue_trend": { "description": "Revenue CAGR +13% over 5 years (2004-2008)", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Stable, operating ratio improving 85%→78%", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.048, "net_income_m": 2100, "ev_m": 44000, "exemption": "INFRA_EXEMPTION", "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "monopoly", "description": "Western US rail duopoly with Union Pacific. Government cannot approve new competing railroad. Physical infrastructure irreplaceable. Trucking cost per ton-mile is 3-4x rail. Pricing power embedded in franchise.", "pass": true }
},
"special_channel": "INFRA_EXEMPTION",
"control_groups": [
{ "ticker": "UNP", "company": "Union Pacific", "year": 2008, "gates_failed": [], "conclusion": "BUY — also passes. Both are excellent railroads. Buffett chose BNSF because he could acquire the full company (BNI was public, UP was not available for full acquisition at the time)." },
{ "ticker": "CSX", "company": "CSX", "year": 2008, "gates_failed": [], "conclusion": "BUY — also passes. Eastern railroad, same quality tier." }
],
"conclusion": "BUY",
"buffett_action": "$44B full acquisition (Berkshire already held a stake)",
"actual_result": "Historic win — Buffett called it 'an all-in wager on America's economic future'. Cumulative profits 2010-2025 exceed $40B.",
"verdict": "✅ aligned",
"key_insight": "INFRA_EXEMPTION applied: earnings yield 4.8% is below 6% threshold, but infrastructure monopoly with pricing power and improving efficiency justifies lower yield. All three railroads pass — framework identifies the quality tier correctly."
}
FILE:company_cards/GE_2007.json
{
"ticker": "GE",
"company": "General Electric Company",
"analysis_year": 2008,
"data_source": "FY2007 annual report / 10-K, GE Sep-Oct 2008 guidance and Buffett deal filings",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.192, "metric_used": "ROE", "years_averaged": "2005-2007", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 22208, "pass": null },
"g3_leverage": { "metric_used": "Debt/Capital", "value": 11.4, "pass": false },
"g4_revenue_trend": { "description": "Strong industrial and infrastructure growth pre-crisis; 3Q08 guide cut driven by GE Capital stress, not industrial demand collapse", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Industrial margins and returns remained solid pre-crisis; pressure came from financial services, not a two-year industrial margin collapse", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": "CRISIS_PREFERRED", "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "The moat was not in GE Capital. It was in GE's industrial installed base, service backlogs, global infrastructure franchises, and quasi-systemic importance. Buffett was effectively underwriting whether the industrial crown jewels and government importance made GE solvent enough for a 10% preferred plus warrants deal.", "pass": true }
},
"special_channel": "CRISIS_PREFERRED",
"control_groups": [
{ "ticker": "AIG", "company": "American International Group", "year": 2008, "gates_failed": ["g3_leverage", "g7_moat"], "conclusion": "PASS — needed a government rescue and was not a safe private capital candidate." },
{ "ticker": "CIT", "company": "CIT Group", "year": 2008, "gates_failed": ["g3_leverage", "g7_moat"], "conclusion": "PASS — funding model was too fragile and the franchise was not strong enough to support Buffett-style rescue capital." }
],
"conclusion": "BUY",
"buffett_action": "$3B in 10% perpetual preferred, callable after 3 years at a 10% premium, plus warrants for $3B of common at $22.25",
"actual_result": "GE redeemed the preferred in 2011 at a 10% premium after Berkshire collected $900M of dividends; Berkshire later exercised the warrants cashlessly for 10.7M GE shares. Positive outcome, but smaller than GS/BAC.",
"verdict": "✅ aligned",
"key_insight": "Crisis preferred channel: the common stock was messy, but the rescue-capital terms were excellent and GE remained solvent enough for Buffett to earn equity-like upside with bond-like protection."
}
FILE:company_cards/LIVE_600026SH_2026.json
{
"analysis_scope": "live",
"ticker": "600026.SH",
"company": "COSCO SHIPPING Energy Transportation Co., Ltd.",
"analysis_year": 2026,
"data_source": "COSCO Shipping Energy 2024 annual report summary (published 2025-03-27), 2025 Q3 report (published 2025-10-31), and market valuation / TTM metrics available through 2026-03-24",
"analyzed_date": "2026-03-24",
"hard_gates": {
"g1_roe_roic": {
"value": 0.0875,
"metric_used": "ROE",
"years_averaged": "2022-2024",
"pass": false
},
"g2_fcf_to_ni": {
"value": 0.42,
"fcf": 1369.0,
"net_income": 3303.0,
"pass": false
},
"g3_leverage": {
"metric_used": "Net Debt/EBITDA",
"value": 3.71,
"pass": true
},
"g4_revenue_trend": {
"description": "Revenue rose from RMB 18.66bn in 2022 to RMB 22.73bn in 2023 and RMB 23.24bn in 2024. 2025 first nine months softened versus 2024, but this looks cyclical, not structural.",
"structural_decline": false,
"pass": true
},
"g5_gross_margin_trend": {
"description": "Gross margin moved from 18.55% in 2022 to 29.51% in 2023 and 27.24% in 2024. It is off the peak, but not a 2+ year consecutive decline.",
"declining_2plus_years": false,
"pass": true
},
"g6_earnings_yield": {
"value": 0.0221,
"net_income_m": 3303.0,
"ev_m": 149360.0,
"exemption": null,
"pass": false
},
"g7_moat": {
"verdict": "SPLIT",
"moat_type": "cost_advantage",
"description": "Scale, state-backed relationships, domestic coastal share, and LNG long-term charters provide some stability. But most earnings power still comes from a tanker shipping business whose rates are cyclical, capital intensity is high, and pricing power is limited. I cannot underwrite a decade-long moat comparable to Buffett's preferred compounders.",
"pass": false
}
},
"special_channel": null,
"control_groups": [
{
"ticker": "601872.SH",
"company": "China Merchants Energy Shipping Co., Ltd.",
"year": 2026,
"gates_failed": ["g1_roe_roic", "g2_fcf_to_ni", "g6_earnings_yield", "g7_moat"],
"conclusion": "PASS — same tanker economics: ROIC is sub-12%, cash conversion is weak, earnings yield is only about 3.1%, and the moat is still rate-cycle dependent."
},
{
"ticker": "601975.SH",
"company": "Nanjing Tanker Corporation",
"year": 2026,
"gates_failed": ["g1_roe_roic", "g7_moat"],
"conclusion": "PASS — balance sheet is cleaner, but ROE is still below 12% and the business remains an asset-heavy commodity shipper without a Buffett-grade moat."
}
],
"conclusion": "PASS",
"buffett_action": "N/A — live analysis, not a Berkshire historical backtest case",
"actual_result": "Open",
"verdict": "N/A",
"key_insight": "This is a better cyclical shipper than many peers, but it is still a cyclical shipper; today's returns on capital, cash conversion, and valuation do not justify a Buffett-style hold."
}
FILE:company_cards/AAPL_2015.json
{
"ticker": "AAPL",
"company": "Apple Inc.",
"analysis_year": 2016,
"data_source": "FY2015 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.46, "metric_used": "ROE", "years_averaged": "2013-2015", "pass": true },
"g2_fcf_to_ni": { "value": 1.31, "fcf": 69800, "net_income": 53400, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": -1.5, "pass": true },
"g4_revenue_trend": { "description": "Strong growth driven by iPhone ecosystem", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "~40% gross margin, stable to expanding", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.12, "net_income_m": 53400, "ev_m": 445000, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "iPhone ecosystem: App Store, iMessage, AirDrop, iCloud, Apple Watch integration create switching costs estimated at $1,000+ per customer. 1B+ active devices. Services revenue growing rapidly. Consumer brand among most trusted globally.", "pass": true }
},
"special_channel": null,
"control_groups": [
{ "ticker": "MSFT", "company": "Microsoft", "year": 2015, "gates_failed": [], "conclusion": "BUY — also passes. Buffett chose Apple due to consumer product understandability. Both are correct choices." },
{ "ticker": "GOOGL", "company": "Alphabet", "year": 2015, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — earnings yield ~5%, just below threshold" }
],
"conclusion": "BUY",
"buffett_action": "Started buying in Q1 2016, peaked at $17.7B position",
"actual_result": "Historic win — largest position in Berkshire portfolio, 10x+ return",
"verdict": "✅ aligned",
"key_insight": "All 7 gates passed with wide margin. Microsoft also passes — framework correctly identifies the quality tier, final selection comes from circle of competence (Buffett understood iPhone as consumer product, not as tech company)."
}
FILE:company_cards/GEICO_1976.json
{
"ticker": "GEICO",
"company": "GEICO Corporation",
"analysis_year": 1976,
"data_source": "Berkshire Hathaway 1985 and 1986 shareholder letters",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": null, "metric_used": "ROE", "years_averaged": "1975-1976", "pass": null },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": null, "pass": null },
"g3_leverage": { "metric_used": "Capital / solvency", "value": null, "pass": null },
"g4_revenue_trend": { "description": "The company had suffered a brutal period, but the underlying direct-auto model was not structurally broken; the issue was solvency and execution, not franchise logic.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Near-bankruptcy obscured near-term margin figures, but the enduring economics came from GEICO's lower cost structure rather than temporary accounting cleanliness.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": null, "net_income_m": null, "ev_m": null, "exemption": null, "pass": null },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "Buffett later described GEICO's cost gap versus competitors as a moat around the castle. Direct distribution gave GEICO materially lower operating costs than both traditional insurers and even other direct writers. That cost advantage was durable enough that once the company was recapitalized and properly managed, the franchise could compound brilliantly.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"premium_volume_1986_m": 500,
"combined_ratio_1986": 0.969,
"underwriting_expense_plus_lae_ratio_1986": 0.235
},
"control_groups": [
{ "ticker": "ALL", "company": "Allstate", "year": 1976, "gates_failed": ["g7_moat"], "conclusion": "PASS — large scale, but materially higher cost structure than GEICO." },
{ "ticker": "TRV", "company": "Travelers", "year": 1976, "gates_failed": ["g7_moat"], "conclusion": "PASS — important insurer, but without GEICO's direct-distribution moat in auto." }
],
"conclusion": "BUY",
"buffett_action": "Buffett bought GEICO aggressively during the 1976 rescue period and later made it a permanent Berkshire pillar.",
"actual_result": "A historic winner. Buffett later credited Jack Byrne's revival and GEICO's moat for enormous gains to Berkshire.",
"verdict": "✅ aligned",
"key_insight": "A near-death experience does not negate a moat if the underlying cost advantage is real and recapitalization fixes the immediate crisis."
}
FILE:company_cards/LIVE_01072HK_2026.json
{
"analysis_scope": "live",
"ticker": "01072.HK",
"company": "Dongfang Electric Corporation Limited",
"analysis_year": 2026,
"data_source": "Dongfang Electric 2024 annual report (published 2025-04-30), 2025 interim report (published 2025-08-29), and market valuation data available through 2026-03-12",
"analyzed_date": "2026-03-24",
"hard_gates": {
"g1_roe_roic": {
"value": 0.0865,
"metric_used": "ROE",
"years_averaged": "2022-2024",
"pass": false
},
"g2_fcf_to_ni": {
"value": 2.42,
"fcf": 7060.4,
"net_income": 2922.1,
"pass": true
},
"g3_leverage": {
"metric_used": "Net Debt/EBITDA",
"value": -6.1,
"pass": true
},
"g4_revenue_trend": {
"description": "Revenue grew from RMB 55.4bn in 2022 to RMB 60.7bn in 2023 and RMB 69.7bn in 2024; no structural decline signal.",
"structural_decline": false,
"pass": true
},
"g5_gross_margin_trend": {
"description": "Gross margin fell to about 15.5% in 2024 from about 18.8% in 2023, but the data used does not show a 2+ year consecutive decline.",
"declining_2plus_years": false,
"pass": true
},
"g6_earnings_yield": {
"value": 0.0247,
"net_income_m": 3314.0,
"ev_m": 134410.0,
"exemption": null,
"pass": false
},
"g7_moat": {
"verdict": "FAIL",
"moat_type": null,
"description": "Dongfang Electric is a major state-backed power equipment supplier with real engineering depth, but this is still a project-driven capital-goods business. I cannot describe a decade-long moat that prevents peers such as Harbin Electric, Shanghai Electric, or global turbine OEMs from replicating enough of the offering to compress returns.",
"pass": false
}
},
"special_channel": null,
"control_groups": [
{
"ticker": "01133.HK",
"company": "Harbin Electric Company Limited",
"year": 2024,
"gates_failed": ["g1_roe_roic", "g6_earnings_yield"],
"conclusion": "PASS — 2024 ROE is still below 12%, and the 2025-10-31 market PE implies a sub-6% earnings yield."
},
{
"ticker": "02727.HK",
"company": "Shanghai Electric Group Company Limited",
"year": 2024,
"gates_failed": ["g1_roe_roic", "g6_earnings_yield"],
"conclusion": "PASS — even weaker ROE and no valuation edge, so the control group does not improve the case."
}
],
"conclusion": "PASS",
"buffett_action": "N/A — live analysis, not a Berkshire historical backtest case",
"actual_result": "Open",
"verdict": "N/A",
"key_insight": "Policy tailwinds and order growth are real, but current returns on capital and earnings yield are too weak for a Buffett-style hold."
}
FILE:company_cards/BMY_2019.json
{
"ticker": "BMY",
"company": "Bristol-Myers Squibb Company",
"analysis_year": 2020,
"data_source": "Bristol-Myers Squibb FY2019 10-K, Bristol-Myers Squibb Q3 2020 10-Q, and Berkshire 2020-09-30 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.168, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": true },
"g2_fcf_to_ni": { "value": -276.3, "fcf": 12157, "net_income": -44, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.04, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $20.78B in 2017 to $22.56B in 2018 to $26.15B in 2019, and nine-month 2020 revenue of $31.45B reflected an even larger platform after Celgene. No structural decline was visible at the decision point.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin stayed healthy but not pristine: roughly 71.1% in 2017, 71.3% in 2018, and 69.1% in 2019. That was one year of compression, not a two-year deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": -0.0003, "net_income_m": -44, "ev_m": 163578, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": "ip", "description": "Bristol-Myers had important oncology and immunology assets, but in late 2020 the thesis depended on digesting a huge merger, managing Revlimid patent erosion, and continually replenishing the pipeline. That can make for a profitable drug company, but not a simple decade-long tollbooth with Buffett-level moat clarity.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"sales_2019_usd_m": 26145,
"net_income_2019_usd_m": 3439,
"operating_cash_flow_2019_usd_m": 8210,
"capital_expenditures_2019_usd_m": 836,
"cash_2020q3_usd_m": 19435,
"debt_2020q3_usd_m": 44949,
"ttm_net_income_2020q3_usd_m": -44,
"ttm_operating_cash_flow_2020q3_usd_m": 12878,
"ttm_capex_2020q3_usd_m": 721,
"implied_price_2020q3_usd": 60.29,
"market_value_2020q3_usd_m": 138064,
"berkshire_shares_2020q3_m": 29.971,
"berkshire_value_2020q3_usd_m": 1807.0
},
"control_groups": [
{ "ticker": "PFE", "company": "Pfizer Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — another mega-cap pharma operator, but with no clearer company-level moat and a more mature legacy portfolio." },
{ "ticker": "GSK", "company": "GlaxoSmithKline plc", "year": 2020, "gates_failed": ["g1_roe_roic", "g4_revenue_trend", "g7_moat"], "conclusion": "PASS — globally scaled, yet weaker on recent economics and still dependent on portfolio renewal rather than a singular tollbooth." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire disclosed 29,971,194 Bristol-Myers shares worth about $1.81B at September 30, 2020 via its 13F-HR.",
"actual_result": "Berkshire cut the stake to 5,202,674 shares by 2021-12-31 and it no longer appeared in the 2022-12-31 13F. The position never developed into a defining Berkshire compounder.",
"verdict": "⭐ framework_wins",
"key_insight": "A post-merger pharma platform can throw off cash and still fail Buffett-style underwriting when GAAP earnings vanish, moat clarity weakens, and the thesis depends on ongoing pipeline replacement."
}
FILE:company_cards/MTB_2000.json
{
"ticker": "MTB",
"company": "M&T Bank Corporation",
"analysis_year": 2000,
"data_source": "M&T Bank FY2000 10-K, SEC EDGAR; Berkshire 2000 annual report; 2000 Berkshire AGM Q&A",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.151, "metric_used": "ROE", "years_averaged": "1998-2000 normalized", "pass": true },
"g2_fcf_to_ni": { "value": null, "fcf": null, "net_income": 286, "pass": null },
"g3_leverage": { "metric_used": "Tier1 (lead bank)", "value": 0.1071, "pass": true },
"g4_revenue_trend": { "description": "Loans, deposits, and earnings all expanded into 2000. Pressure in mortgage banking was cyclical, not a structural break in the franchise.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "For a bank, the economic analogue is spread discipline and credit cost control. Net interest margin remained near 4% and there was no two-year structural profitability collapse.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.091, "net_income_m": 286, "ev_m": 3140, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "M&T's moat was not scale for scale's sake. It was a disciplined low-ego banking culture under Bob Wilmers, sticky local deposits, conservative underwriting, and customer relationships that made the franchise much harder to imitate than a generic regional bank. Buffett's own test was simple: it was a bank that let him sleep well.", "pass": true }
},
"special_channel": null,
"metrics_snapshot": {
"net_income_2000_usd_m": 286,
"capital_expenditures_2000_usd_m": 23,
"tier1_ratio_lead_bank": 0.1071,
"berkshire_lookthrough_earnings_share_2000_usd_m": 23
},
"control_groups": [
{ "ticker": "FLT", "company": "FleetBoston Financial", "year": 2000, "gates_failed": ["g7_moat", "g3_leverage"], "conclusion": "PASS — larger franchise, but weaker cultural edge and less conservative underwriting reputation than M&T." },
{ "ticker": "FTU", "company": "First Union", "year": 2000, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — merger friction and integration strain were visible, and the franchise quality was not as clean." }
],
"conclusion": "BUY",
"buffett_action": "Berkshire disclosed M&T as a major investee in 2000, and Buffett said at the 2000 AGM that Berkshire would likely still own it in ten years.",
"actual_result": "M&T became a long-duration Berkshire bank holding and a strong compounder before Berkshire later exited as part of broader bank retrenchment.",
"verdict": "✅ aligned",
"key_insight": "In banking, owner-operator culture and underwriting discipline can be a moat if they survive scale."
}
FILE:company_cards/PG_2020.json
{
"ticker": "PG",
"company": "The Procter & Gamble Company",
"analysis_year": 2020,
"data_source": "Procter & Gamble FY2020 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.179, "metric_used": "ROE", "years_averaged": "2018-2020", "pass": true },
"g2_fcf_to_ni": { "value": 1.094, "fcf": 14330, "net_income": 13103, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.95, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $66.8B in FY2018 to $67.7B in FY2019 to $71.0B in FY2020. The portfolio was plainly not in structural decline.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin improved from roughly 48.5% in FY2018 to 48.6% in FY2019 to 50.3% in FY2020. No deterioration was visible.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.036, "net_income_m": 13103, "ev_m": 363277, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "P&G still had one of the strongest portfolios of household brands in the world, backed by advertising scale, shelf presence, and global distribution. The only real issue was paying a premium consumer-staples multiple for that quality.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "P&G's low earnings yield was a pure quality multiple on a globally dominant branded-consumer platform.",
"reason_for_low_yield": "This was not a dubious story stock. It was a great business already priced like one in a low-rate environment.",
"decision_impact": "The valuation note explains why Buffett could still hold a token stake, but it does not overturn the framework's PASS."
},
"management_veto": {
"status": "clear",
"summary": "No management veto applied. This is a price-discipline rejection against a very high-quality staple franchise."
}
},
"control_groups": [
{ "ticker": "KMB", "company": "Kimberly-Clark Corporation", "year": 2020, "gates_failed": ["g4_revenue_trend", "g6_earnings_yield"], "conclusion": "PASS — respectable brand portfolio, but slower growth and still not cheap." },
{ "ticker": "CL", "company": "Colgate-Palmolive Company", "year": 2020, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — another excellent staple, but also priced below the framework's required return." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 315,400 P&G shares worth about $43.9M at 2020-12-31 in its 13F-HR.",
"actual_result": "That tiny stake remained unchanged at both 2021-12-31 and 2022-12-31. It looked like a legacy position, not a fresh high-conviction Berkshire move.",
"verdict": "⭐ framework_wins",
"key_insight": "World-class staple franchises can remain passes when the only thing clearly on offer is safety, not a sufficient forward return."
}
FILE:company_cards/TESCO_2007.json
{
"ticker": "TESCO",
"company": "Tesco PLC",
"analysis_year": 2007,
"data_source": "Tesco FY2007 annual report",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.249, "metric_used": "ROE", "years_averaged": "2005-2007", "pass": true },
"g2_fcf_to_ni": { "value": 0.21, "fcf": 394, "net_income": 1892, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 1.4, "pass": true },
"g4_revenue_trend": { "description": "Revenue and profit were still growing in 2005-2007 across UK and international retail. This was not a structural decline case at the decision point.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Reported gross margin improved from 7.7% to 8.1%; no two-year margin erosion before the investment case.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.047, "net_income_m": 1892, "ev_m": 40469, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Tesco looked dominant, but grocery customers still switch primarily on price, convenience, and promotions. Clubcard data, scale, and real estate helped execution, yet they did not create a 10-year moat that competitors could not replicate. Thin margins plus low switching costs meant the apparent moat was narrower than the headline market share suggested.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"revenue_2007_m": 42641,
"gross_profit_2007_m": 3463,
"fcf_2007_m": 394,
"net_debt_2007_m": 5024
},
"control_groups": [
{ "ticker": "SBRY", "company": "J Sainsbury", "year": 2007, "gates_failed": ["g6_earnings_yield", "g7_moat"], "conclusion": "PASS — recovering execution, but valuation support and moat quality were still insufficient for a Buffett-style BUY." },
{ "ticker": "MRW", "company": "Wm Morrison Supermarkets", "year": 2007, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — post-Safeway integration strain and the same low-switching-cost grocery economics kept it outside the circle." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire began building Tesco in 2006-2007 and eventually accumulated a multibillion-dollar stake costing about $2.3B.",
"actual_result": "Buffett exited after Tesco's 2014 accounting scandal and market-share collapse, recording an after-tax loss of about $444M.",
"verdict": "⭐ framework_wins",
"key_insight": "A retailer can show beautiful growth statistics and still fail Buffett's test when free cash flow is weak, valuation is full, and the customer relationship has no real switching cost."
}
FILE:company_cards/GOLD_2019.json
{
"ticker": "GOLD",
"company": "Barrick Gold Corporation",
"analysis_year": 2020,
"data_source": "Barrick Gold FY2019 Form 40-F, Barrick Gold Q3 2020 6-K / Exhibit 99.2, Berkshire 2020-09-30 13F-HR, Berkshire 2020-12-31 13F-HR, and Berkshire 2021-03-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.063, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": false },
"g2_fcf_to_ni": { "value": 0.74, "fcf": 2700, "net_income": 3631, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/9M 2020 Adjusted EBITDA proxy", "value": 0.08, "pass": true },
"g4_revenue_trend": { "description": "Revenue fell from $8.37B in 2017 to $7.24B in 2018, then recovered sharply to $9.72B in 2019 as gold prices and portfolio quality improved. That pattern looks cyclical and commodity-linked rather than structurally broken.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin moved from roughly 36.7% in 2017 to 27.9% in 2018 and back up to 28.9% in 2019. Margins were volatile, but there was not a two-year consecutive deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.072, "net_income_m": 3631, "ev_m": 50397, "exemption": null, "pass": true },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Barrick in late 2020 had become a better-run gold miner with lower leverage and a stronger asset base, but it was still fundamentally a commodity producer. Its economics were heavily influenced by gold prices, reserve quality, and operating discipline rather than by a structurally irreplicable tollbooth. Competitors could not copy a world-class mine overnight, yet the business still lacked the kind of durable pricing power and customer captivity this framework wants for a long-duration core holding.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"sales_2019_usd_m": 9717,
"net_income_2019_usd_m": 4574,
"operating_cash_flow_2019_usd_m": 2833,
"capital_expenditures_2019_usd_m": 1701,
"cash_2020q3_usd_m": 4744,
"debt_2020q3_usd_m": 5161,
"net_debt_2020q3_usd_m": 417,
"adjusted_ebitda_9m_2020_usd_m": 5386,
"ttm_net_income_2020q3_usd_m": 3631,
"ttm_operating_cash_flow_2020q3_usd_m": 4654,
"ttm_capex_2020q3_usd_m": 1954,
"implied_price_2020q3_usd": 28.11,
"market_value_2020q3_usd_m": 49980,
"berkshire_shares_2020q3_m": 12.0,
"berkshire_value_2020q3_usd_m": 337.3
},
"control_groups": [
{ "ticker": "NEM", "company": "Newmont Corporation", "year": 2020, "gates_failed": ["g2_fcf_to_ni", "g7_moat"], "conclusion": "PASS — another high-quality gold miner, but still a commodity business whose long-term economics depend more on metal prices than on an irreplicable franchise." },
{ "ticker": "AEM", "company": "Agnico Eagle Mines Limited", "year": 2020, "gates_failed": ["g1_roe_roic", "g7_moat"], "conclusion": "PASS — operationally respected, but still not the kind of decade-long customer-captive moat this framework underwrites." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire disclosed 12,000,000 Barrick Gold shares worth about $337.3M at September 30, 2020 via its 13F-HR.",
"actual_result": "The stake was already gone by Berkshire's 2020-12-31 13F, which makes the case look far more like a short-lived macro or commodity expression than a core Buffett-style franchise investment.",
"verdict": "⭐ framework_wins",
"key_insight": "A miner can look optically cheap and financially repaired, yet still be a pass if returns are cyclical, cash conversion is not consistently strong, and the moat is really just exposure to the commodity cycle."
}
FILE:company_cards/NUE_1999.json
{
"ticker": "NUE",
"company": "Nucor Corporation",
"analysis_year": 2000,
"data_source": "Nucor FY1999 10-K complete submission, SEC EDGAR; Berkshire 13F-HR/A for quarter ended 2000-03-31",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.131, "metric_used": "ROE", "years_averaged": "1997-1999", "pass": true },
"g2_fcf_to_ni": { "value": 0.94, "fcf": 230.1, "net_income": 244.6, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": -0.39, "pass": true },
"g4_revenue_trend": { "description": "Sales slipped from $4.18B in 1997 to $4.15B in 1998 to $4.01B in 1999, but this was cyclical steel pricing pressure rather than evidence that Nucor's business model was structurally deteriorating.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin compressed from about 14.5% in 1997 to 13.5% in 1998 to 13.2% in 1999 as steel conditions softened. That is a real two-year decline, even if it was cyclical rather than existential.", "declining_2plus_years": true, "pass": false },
"g6_earnings_yield": { "value": 0.059, "net_income_m": 244.6, "ev_m": 4175, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "Nucor had a real moat by steel standards: a low-cost mini-mill footprint, decentralized operating culture, flexible labor model, and management discipline that let it outperform integrated competitors across cycles. The moat was real, but it was still a moat inside a cyclical commodity business, not a tollbooth immune to price swings.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "Nucor was not actually expensive in an absolute sense, but the earnings-yield hurdle still failed once enterprise value was adjusted for the market price implied by Berkshire's disclosed Q1 2000 holding.",
"reason_for_low_yield": "The sub-6% yield did not reflect hype. It reflected a fair price for the best operator in a cyclical steel industry whose margins were already compressing.",
"decision_impact": "This note reinforces the PASS rather than softening it. Nucor was an admirable steel company, but not the kind of high-certainty compounding franchise the framework wants to underwrite as a Buffett-grade long hold."
},
"management_veto": {
"status": "clear",
"summary": "Management quality and culture were strengths, not concerns. The issue was industry economics and valuation discipline, not trust."
}
},
"metrics_snapshot": {
"net_sales_1999_usd_m": 4009.3,
"net_earnings_1999_usd_m": 244.6,
"operating_cash_flow_1999_usd_m": 604.8,
"capital_expenditures_1999_usd_m": 374.7,
"cash_1999_usd_m": 572.2,
"long_term_debt_1999_usd_m": 390.5,
"shareholders_equity_1999_usd_m": 2262.2,
"berkshire_shares_2000_m": 1.268,
"berkshire_market_value_2000_usd_m": 63.4
},
"control_groups": [
{ "ticker": "X", "company": "United States Steel Corporation", "year": 2000, "gates_failed": ["g1_roe_roic", "g7_moat"], "conclusion": "PASS — an integrated steelmaker with weaker economics, less flexible cost structure, and no Nucor-style operating moat." },
{ "ticker": "AKS", "company": "AK Steel Holding Corporation", "year": 2000, "gates_failed": ["g3_leverage", "g5_gross_margin_trend", "g7_moat"], "conclusion": "PASS — more leveraged sheet-steel exposure with lower resilience and no clear Nucor-equivalent culture advantage." }
],
"conclusion": "PASS",
"buffett_action": "By March 31, 2000 Berkshire disclosed 1,267,900 Nucor shares valued at about $63.4M via a confidential-treatment 13F amendment.",
"actual_result": "Nucor remained the best-managed major U.S. steelmaker and later had strong cycles, but it did not become a defining Berkshire-style long-duration compounding franchise.",
"verdict": "⭐ framework_wins",
"key_insight": "The best company in a cyclical commodity industry can still be a pass if margin compression and only-fair valuation leave too little room for Buffett-style long-hold certainty."
}
FILE:company_cards/KR_2020.json
{
"ticker": "KR",
"company": "The Kroger Co.",
"analysis_year": 2020,
"data_source": "Kroger FY2020 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.25, "metric_used": "ROE", "years_averaged": "2018-2020", "pass": true },
"g2_fcf_to_ni": { "value": 1.016, "fcf": 1536, "net_income": 1512, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.0, "pass": true },
"g4_revenue_trend": { "description": "Sales stayed resilient across 2018-2020 at roughly $122B-123B, with the pandemic making grocery demand even more defensive by late 2020. No structural decline was visible.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin remained around the low-22% range with no clean two-year deterioration. This was a steady, low-margin retailer rather than a margin-collapse story.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.044, "net_income_m": 1512, "ev_m": 34629, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Kroger was a solid operator with scale, private label, and digital execution, but grocery retail is still brutally competitive and not easy to describe as a 10-year irreplicable Buffett moat. The business can be good without being a tollbooth.", "pass": false }
},
"special_channel": null,
"control_groups": [
{ "ticker": "ACI", "company": "Albertsons Companies, Inc.", "year": 2020, "gates_failed": ["g3_leverage", "g7_moat"], "conclusion": "PASS — similar category, but weaker balance-sheet quality and no clearer moat." },
{ "ticker": "KSS", "company": "Kohl's Corporation", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — more visible structural pressure and weaker competitive positioning." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 3.9M Kroger shares worth about $123.9M at 2020-12-31, then increased the position materially during 2021.",
"actual_result": "The stake rose to 28.0M shares by 2021-12-31 and was still 16.6M shares at 2022-12-31. Kroger worked as a solid defensive grocery holding, but not as a classic Buffett monopoly or legendary compounder.",
"verdict": "⭐ framework_wins",
"key_insight": "A retailer can be operationally strong and still fail Buffett-style underwriting when its moat is merely good execution rather than a truly irreplicable franchise."
}
FILE:company_cards/MA_2019.json
{
"ticker": "MA",
"company": "Mastercard Incorporated",
"analysis_year": 2020,
"data_source": "Mastercard FY2019 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.44, "metric_used": "ROIC", "years_averaged": "2017-2019 (proxy because buybacks compressed reported equity)", "pass": true },
"g2_fcf_to_ni": { "value": 0.956, "fcf": 7761, "net_income": 8118, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.02, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $12.5B in 2017 to $15.0B in 2018 to $16.9B in 2019. The business was still compounding strongly before the pandemic temporarily disrupted transaction volumes.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "As a global payments network, Mastercard's direct-cost ratio stayed extremely favorable and underlying operating margins remained elite. There was no two-year structural margin decline.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.022, "net_income_m": 8118, "ev_m": 364963, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "network_effect", "description": "Mastercard is one of the clearest network-effect moats in public markets: issuer and merchant acceptance scale, regulatory licenses, data, and the impracticality of displacing a trusted global payments rail. The challenge in late 2020 was paying a premium price for that quality.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "Mastercard's low earnings yield reflected one of the best network moats in the world, not any doubt about business quality.",
"reason_for_low_yield": "The market was capitalizing decades of expected payment-volume growth and extraordinary capital-light economics.",
"decision_impact": "This is a documented false negative for the framework: the moat is real, but the flat 6% hurdle still rejects it."
},
"management_veto": {
"status": "clear",
"summary": "No management veto applied. The miss comes from valuation rigidity against a world-class network franchise."
}
},
"control_groups": [
{ "ticker": "V", "company": "Visa Inc.", "year": 2020, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — similarly superb, but also too expensive on the framework's earnings-yield hurdle." },
{ "ticker": "AXP", "company": "American Express Company", "year": 2020, "gates_failed": ["g4_revenue_trend", "g6_earnings_yield"], "conclusion": "PASS — a strong franchise, but with more pandemic-era volume disruption and a less pristine network model." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 4,564,756 Mastercard shares worth about $1.63B at 2020-12-31 in its 13F-HR.",
"actual_result": "Berkshire still owned 3,986,648 shares at both 2021-12-31 and 2022-12-31. Mastercard remained one of the durable payments-network franchises in Berkshire's portfolio.",
"verdict": "❌ framework_wrong",
"key_insight": "The current earnings-yield gate still rejects some genuinely exceptional network businesses that Berkshire is willing to own for years."
}
FILE:company_cards/KRFT_2014.json
{
"ticker": "KRFT",
"company": "Kraft Foods Group",
"analysis_year": 2015,
"data_source": "FY2014 10-K, SEC EDGAR (press release)",
"analyzed_date": "2026-03-12",
"hard_gates": {
"g1_roe_roic": { "value": 0.18, "metric_used": "ROIC", "years_averaged": "2012-2014", "pass": true },
"g2_fcf_to_ni": { "value": 1.42, "fcf": 1485, "net_income": 1043, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 2.3, "pass": true },
"g4_revenue_trend": { "description": "Revenue flat (-0.1%), organic +0.9% but VOLUME -0.3% — price masking volume decline. Meals & Desserts segment -6.5%.", "structural_decline": true, "pass": false },
"g5_gross_margin_trend": { "description": "Reported 26.6% (2014) vs 37.4% (2013) — pension accounting distortion, normalized ~34-35%, but 3-year trend declining from 38%→36%→35%.", "declining_2plus_years": true, "pass": false },
"g6_earnings_yield": { "value": 0.050, "net_income_m": 2300, "ev_m": 46000, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": null, "description": "Brands are 'recognized' not 'loved.' Oscar Mayer (processed meat, health trend headwind), Maxwell House (losing to premium/K-Cup), Jell-O (category dying), Velveeta (processed cheese), Planters (commodity nuts). Only Philadelphia cream cheese has genuine pricing power. No pricing power = no moat.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"revenue_2014_m": 18205,
"revenue_2013_m": 18218,
"fcf_m": 1485,
"total_debt_m": 10032,
"normalized_gross_margin_pct": 0.34
},
"control_groups": [
{ "ticker": "CL", "company": "Colgate-Palmolive", "year": 2014, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — earnings yield ~4.5%, borderline. But moat (Colgate toothpaste #1 globally) is far stronger than Kraft." },
{ "ticker": "HSY", "company": "Hershey", "year": 2014, "gates_failed": [], "conclusion": "BUY — passes all gates. Chocolate brand with genuine pricing power, consumers trade up, holiday/emotional consumption stickiness." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire + 3G Capital engineered the Kraft-Heinz merger, Berkshire invested ~$5B additional cash",
"actual_result": "$15.4B goodwill impairment 2018, SEC investigation, dividend cut, stock fell from $90→$25. Berkshire lost ~$20B+ on paper.",
"verdict": "⭐ framework_wins",
"key_insight": "Gates ④⑤⑥⑦ all triggered simultaneously — rare case of multiple failures. Volume declining while price rises is the classic sign of a brand losing relevance. Hershey passes the same framework: the difference is genuine vs. legacy brand."
}
FILE:company_cards/CVX_2020.json
{
"ticker": "CVX",
"company": "Chevron",
"analysis_year": 2020,
"data_source": "FY2020 10-K, SEC EDGAR",
"analyzed_date": "2026-03-10",
"hard_gates": {
"g1_roe_roic": { "value": 0.14, "metric_used": "ROE", "years_averaged": "2017-2019 normalized", "pass": true },
"g2_fcf_to_ni": { "value": 1.1, "fcf": 11000, "net_income": 10000, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 1.2, "pass": true },
"g4_revenue_trend": { "description": "COVID cyclical decline — not structural. Core demand intact.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Stable structurally, cyclical 2020 impact", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.079, "net_income_m": null, "ev_m": null, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "Moat is the balance sheet, not the product. CVX entered COVID with lowest debt/capital ratio in major oil (22.7%). 33 consecutive years of dividend increases including loss years. Can outlast competitors in downturns and acquire assets cheaply.", "pass": true }
},
"special_channel": null,
"control_groups": [
{ "ticker": "XOM", "company": "ExxonMobil", "year": 2020, "gates_failed": ["g1_roe_roic", "g2_fcf_to_ni"], "conclusion": "PASS" },
{ "ticker": "COP", "company": "ConocoPhillips", "year": 2020, "gates_failed": ["g5_gross_margin_trend"], "conclusion": "PASS" }
],
"conclusion": "BUY",
"buffett_action": "Bought $4.1B in Q4 2020, added to $19.8B by 2022",
"actual_result": "Large win — oil recovery + dividend income",
"verdict": "✅ aligned",
"key_insight": "For cyclical businesses, normalize ROE/FCF over the cycle. The key differentiator between CVX and XOM was balance sheet discipline — same industry, vastly different financial quality."
}
FILE:company_cards/CHTR_2019.json
{
"ticker": "CHTR",
"company": "Charter Communications, Inc.",
"analysis_year": 2020,
"data_source": "Charter FY2019 10-K and Berkshire 2020-12-31 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.099, "metric_used": "ROE", "years_averaged": "2017-2019", "pass": false },
"g2_fcf_to_ni": { "value": 2.286, "fcf": 4553, "net_income": 1992, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 6.34, "pass": false },
"g4_revenue_trend": { "description": "Revenue climbed from $41.6B in 2017 to $43.6B in 2018 to $45.8B in 2019 as broadband and cable bundles remained resilient. No structural decline was visible at the decision point.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Contribution margins were stable to improving as broadband mix increased. The issue was leverage and price, not a two-year margin unwind.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.008, "net_income_m": 1992, "ev_m": 257608, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "switching_cost", "description": "Charter had a real local-market moat: last-mile infrastructure, customer switching friction, and strong broadband positioning in many territories. But the capital structure and price already left almost no room for underwriting error.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "The low earnings yield partly reflected the scarcity value of broadband infrastructure and local-network economics.",
"reason_for_low_yield": "Investors were paying up for a real moat, but they were also accepting leverage and valuation risk that sat well outside the framework's comfort zone.",
"decision_impact": "Even after acknowledging the moat, the combined g3 and g6 failures keep the conclusion at PASS."
},
"management_veto": {
"status": "clear",
"summary": "There was no integrity veto. The rejection comes from leverage and price, not stewardship concerns."
}
},
"control_groups": [
{ "ticker": "DISH", "company": "DISH Network Corporation", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — weaker customer position and far less dependable broadband economics." },
{ "ticker": "ATUS", "company": "Altice USA, Inc.", "year": 2020, "gates_failed": ["g3_leverage", "g7_moat"], "conclusion": "PASS — similar industry, but a weaker competitive footprint and even more leverage strain." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire reported 5,213,461 Charter shares worth about $3.45B at 2020-12-31 in its 13F-HR.",
"actual_result": "Berkshire still owned 3,828,941 shares at both 2021-12-31 and 2022-12-31, but the quoted value was far below the late-2020 level by the end of 2022. This was not a clean Buffett-style compounding win.",
"verdict": "⭐ framework_wins",
"key_insight": "A real moat does not rescue a business when leverage is above 6x and the earnings yield is still under 1%."
}
FILE:company_cards/HRB_2002.json
{
"ticker": "HRB",
"company": "H&R Block, Inc.",
"analysis_year": 2002,
"data_source": "H&R Block FY2002 annual report / EX-13, SEC EDGAR; Berkshire 2002 annual report",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.319, "metric_used": "ROE", "years_averaged": "2000-2002", "pass": true },
"g2_fcf_to_ni": { "value": 1.39, "fcf": 604.1, "net_income": 434.4, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 0.57, "pass": true },
"g4_revenue_trend": { "description": "Revenue rose from $2.43B to $2.98B to $3.32B across 2000-2002. The tax-prep core stayed structurally intact while mortgage and business-services operations added growth.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "The closest economic proxy is operating efficiency rather than reported gross margin. Return on total revenues moved from 10.4% in 2000 to 9.3% in 2001 and 13.1% in 2002, so there was no two-year structural deterioration.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.05, "net_income_m": 434.4, "ev_m": 8650.9, "exemption": null, "pass": false },
"g7_moat": { "verdict": "PASS", "moat_type": "brand", "description": "H&R Block had a real though not impregnable moat: national consumer trust in tax prep, a dense seasonal storefront network, franchise reach, software and e-file scale, and customer behavior built around annual repetition in a compliance-driven category. That is a better business than a generic tax shop, even if it is not Coca-Cola-level permanence.", "pass": true }
},
"special_channel": null,
"review_notes": {
"quality_multiple_note": {
"summary": "H&R Block's sub-6% earnings yield reflected a genuine franchise in tax preparation and consumer finance adjacency, not a broken business being dressed up.",
"reason_for_low_yield": "The market was paying for trusted national distribution, repeat-file behavior, and strong cash generation, but the franchise still lacked the depth and duration of Berkshire's very best consumer compounds.",
"decision_impact": "This note supports keeping the valuation gate intact here. The business was good, but not so extraordinary that a 5% earnings yield obviously represented a bargain."
},
"management_veto": {
"status": "clear",
"summary": "No management-integrity veto is visible in the filed materials used here. The underwriting debate is about franchise quality versus valuation, not stewardship trust."
}
},
"metrics_snapshot": {
"revenue_2002_usd_m": 3317.7,
"net_income_2002_usd_m": 434.4,
"net_operating_free_cash_flow_2002_usd_m": 604.1,
"cash_2002_usd_m": 436.1,
"long_term_debt_2002_usd_m": 928.0,
"berkshire_cost_2002_usd_m": 255.0
},
"control_groups": [
{ "ticker": "INTU", "company": "Intuit Inc.", "year": 2002, "gates_failed": ["g6_earnings_yield"], "conclusion": "PASS — excellent software franchise, but at the time the valuation gave even less margin of safety than H&R Block." },
{ "ticker": "JTX", "company": "Jackson Hewitt Tax Service Inc.", "year": 2002, "gates_failed": ["g7_moat"], "conclusion": "PASS — a meaningful competitor, but with weaker brand trust, less national density, and less durable economics than H&R Block." }
],
"conclusion": "PASS",
"buffett_action": "By year-end 2002 Berkshire held 15,999,200 H&R Block shares at a cost of about $255M.",
"actual_result": "A respectable but non-canonical outcome: Berkshire's position appreciated, but H&R Block never became a defining long-duration compounder in the way Berkshire's very best public-equity wins did.",
"verdict": "⭐ framework_wins",
"key_insight": "A good branded service business can still be a pass if the valuation leaves too little room for extraordinary long-term compounding."
}
FILE:company_cards/ABBV_2019.json
{
"ticker": "ABBV",
"company": "AbbVie Inc.",
"analysis_year": 2020,
"data_source": "AbbVie FY2019 10-K, AbbVie Q3 2020 10-Q, and Berkshire 2020-09-30 / 2021-12-31 / 2022-12-31 13F-HR",
"analyzed_date": "2026-03-26",
"hard_gates": {
"g1_roe_roic": { "value": 0.178, "metric_used": "ROIC", "years_averaged": "2017-2019 (NOPAT / capital-employed proxy because equity was distorted by buybacks and acquisition accounting)", "pass": true },
"g2_fcf_to_ni": { "value": 2.08, "fcf": 15327, "net_income": 7381, "pass": true },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 4.52, "pass": false },
"g4_revenue_trend": { "description": "Revenue rose from $28.22B in 2017 to $32.75B in 2018 to $33.27B in 2019, and nine-month 2020 revenue of $31.95B was already above the prior-year comparable period. No structural decline was visible at the decision point.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin improved rather than deteriorated: roughly 75.0% in 2017, 76.4% in 2018, and 77.6% in 2019 based on sales less cost of products sold. There was no two-year erosion.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.032, "net_income_m": 7381, "ev_m": 229831, "exemption": null, "pass": false },
"g7_moat": { "verdict": "FAIL", "moat_type": "ip", "description": "AbbVie had strong commercial execution, a valuable immunology franchise, and deeper scale after the Allergan deal, but in late 2020 the economics still depended on a patent-bound drug portfolio, looming Humira erosion, and successful pipeline replacement. That is a good pharmaceutical platform, not a simple 10-year Buffett tollbooth.", "pass": false }
},
"special_channel": null,
"metrics_snapshot": {
"sales_2019_usd_m": 33266,
"net_income_2019_usd_m": 7882,
"operating_cash_flow_2019_usd_m": 13324,
"capital_expenditures_2019_usd_m": 552,
"cash_2020q3_usd_m": 7890,
"debt_2020q3_usd_m": 82336,
"ttm_net_income_2020q3_usd_m": 7381,
"ttm_operating_cash_flow_2020q3_usd_m": 16009,
"ttm_capex_2020q3_usd_m": 682,
"implied_price_2020q3_usd": 87.59,
"market_value_2020q3_usd_m": 155385,
"berkshire_shares_2020q3_m": 21.264,
"berkshire_value_2020q3_usd_m": 1862.5
},
"control_groups": [
{ "ticker": "PFE", "company": "Pfizer Inc.", "year": 2020, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — another large-cap drug platform, but with weaker recent growth and no cleaner decade-long moat than AbbVie." },
{ "ticker": "GSK", "company": "GlaxoSmithKline plc", "year": 2020, "gates_failed": ["g1_roe_roic", "g4_revenue_trend", "g7_moat"], "conclusion": "PASS — similarly global and diversified, but with softer economics and no clearer structural moat." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire disclosed 21,264,316 AbbVie shares worth about $1.86B at September 30, 2020 via its 13F-HR.",
"actual_result": "AbbVie generated solid cash flow and a respectable stock outcome, but Berkshire cut the position to 3,033,561 shares by 2021-12-31 and it no longer appeared in the 2022-12-31 13F. The stake behaved more like a tactical large-pharma basket position than a permanent Buffett-style core holding.",
"verdict": "⭐ framework_wins",
"key_insight": "A high-cash-flow pharma platform can still be a pass when a megadeal pushes leverage above 4x, the earnings yield is only about 3%, and the moat depends on replacing expiring patents."
}
FILE:company_cards/WMT_2005.json
{
"ticker": "WMT",
"company": "Wal-Mart Stores, Inc.",
"analysis_year": 2005,
"data_source": "Wal-Mart FY2005 annual report / 10-K, SEC EDGAR; Berkshire 2005 annual report",
"analyzed_date": "2026-03-25",
"hard_gates": {
"g1_roe_roic": { "value": 0.221, "metric_used": "ROE", "years_averaged": "2004-2006", "pass": true },
"g2_fcf_to_ni": { "value": 0.27, "fcf": 3070, "net_income": 11231, "pass": false },
"g3_leverage": { "metric_used": "Net Debt/EBITDA", "value": 1.39, "pass": true },
"g4_revenue_trend": { "description": "Net sales rose from $256.3B to $285.2B to $312.4B. The issue was not structural decline but whether growth capex was consuming too much of the accounting profit.", "structural_decline": false, "pass": true },
"g5_gross_margin_trend": { "description": "Gross margin remained stable to slightly higher across 2004-2006; there was no two-year structural margin decay.", "declining_2plus_years": false, "pass": true },
"g6_earnings_yield": { "value": 0.074, "net_income_m": 11231, "ev_m": 152682, "exemption": null, "pass": true },
"g7_moat": { "verdict": "PASS", "moat_type": "cost_advantage", "description": "Wal-Mart clearly had a moat: unmatched scale, everyday-low-price purchasing power, distribution density, and customer traffic that smaller retailers could not replicate. The problem in 2005 was not business quality but that a large portion of the economics was still being reinvested through store growth, logistics, and international expansion, which kept raw free cash flow conversion below the framework threshold.", "pass": true }
},
"special_channel": null,
"review_notes": {
"owner_earnings_note": {
"summary": "Wal-Mart's raw free cash flow looked weak mainly because the company was still funding a very large global store, logistics, and international expansion program.",
"maintenance_vs_growth_view": "A meaningful portion of 2005-2006 capex was expansionary rather than maintenance-like, so raw FCF / NI overstated how weak the underlying economics really were.",
"decision_impact": "This is exactly the kind of case where g2 needs interpretation. The archived conclusion stays PASS for comparability, but the note records that the raw gate was too harsh."
},
"management_veto": {
"status": "clear",
"summary": "Management quality and capital allocation were not the problem. This was a pricing and reinvestment-interpretation issue, not an integrity or stewardship failure."
}
},
"metrics_snapshot": {
"net_sales_2006_usd_m": 312427,
"net_income_2006_usd_m": 11231,
"operating_cash_flow_2006_usd_m": 17633,
"capital_expenditures_2006_usd_m": 14563,
"market_value_july_2005_usd_m": 120277
},
"control_groups": [
{ "ticker": "SHLD", "company": "Sears Holdings", "year": 2005, "gates_failed": ["g4_revenue_trend", "g7_moat"], "conclusion": "PASS — merger complexity and deteriorating retail relevance made the economics far less dependable than Wal-Mart's." },
{ "ticker": "TGT", "company": "Target Corporation", "year": 2005, "gates_failed": ["g2_fcf_to_ni"], "conclusion": "PASS — still a strong retailer, but free-cash conversion and scale economics were not cleaner than Wal-Mart's at the time." }
],
"conclusion": "PASS",
"buffett_action": "Berkshire established a 19.9M-share Wal-Mart position in 2005 at an actual cost of about $944M.",
"actual_result": "Wal-Mart remained a strong company, but Berkshire never turned the position into a canonical high-conviction compounder and ultimately exited years later after ordinary, not extraordinary, results.",
"verdict": "❌ framework_wrong",
"key_insight": "The current framework is still too harsh on reinvestment-heavy retail compounders when moat quality is exceptional but growth capex suppresses raw FCF."
}
FILE:agents/openai.yaml
interface:
display_name: "Buffett Oracle"
short_description: "Point-in-time Buffett BUY/PASS analysis"
icon_small: "./assets/icon.svg"
icon_large: "./assets/logo.svg"
brand_color: "#8B5E3C"
default_prompt: "Use $buffett-oracle to analyze Apple 2016 with point-in-time Buffett rules."
policy:
allow_implicit_invocation: true