thesis-ci 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- thesis_ci-0.5.0/.gitignore +12 -0
- thesis_ci-0.5.0/CHANGELOG.md +389 -0
- thesis_ci-0.5.0/LICENSE +21 -0
- thesis_ci-0.5.0/LICENSE-SPEC.md +14 -0
- thesis_ci-0.5.0/PKG-INFO +260 -0
- thesis_ci-0.5.0/README.md +240 -0
- thesis_ci-0.5.0/action.yml +83 -0
- thesis_ci-0.5.0/pyproject.toml +53 -0
- thesis_ci-0.5.0/spec/SPEC.md +455 -0
- thesis_ci-0.5.0/spec/checks.yml +406 -0
- thesis_ci-0.5.0/spec/metrics.yml +266 -0
- thesis_ci-0.5.0/spec/schemas/agent.schema.json +105 -0
- thesis_ci-0.5.0/spec/schemas/ci-results.schema.json +360 -0
- thesis_ci-0.5.0/spec/schemas/constitution-rules.schema.json +55 -0
- thesis_ci-0.5.0/spec/schemas/decision-log.schema.json +81 -0
- thesis_ci-0.5.0/spec/schemas/decision-rights.schema.json +368 -0
- thesis_ci-0.5.0/spec/schemas/escalation.schema.json +76 -0
- thesis_ci-0.5.0/spec/schemas/forecast.schema.json +97 -0
- thesis_ci-0.5.0/spec/schemas/industry.schema.json +265 -0
- thesis_ci-0.5.0/spec/schemas/ledger.schema.json +215 -0
- thesis_ci-0.5.0/spec/schemas/memo.schema.json +261 -0
- thesis_ci-0.5.0/spec/schemas/prereg-settlement.schema.json +141 -0
- thesis_ci-0.5.0/spec/schemas/prereg.schema.json +251 -0
- thesis_ci-0.5.0/spec/schemas/readings.schema.json +108 -0
- thesis_ci-0.5.0/spec/schemas/repo.schema.json +45 -0
- thesis_ci-0.5.0/spec/schemas/sources.schema.json +124 -0
- thesis_ci-0.5.0/spec/schemas/story.schema.json +43 -0
- thesis_ci-0.5.0/spec/schemas/thesis.schema.json +1021 -0
- thesis_ci-0.5.0/spec/schemas/valuation.schema.json +324 -0
- thesis_ci-0.5.0/spec/templates/lynch/README.md +17 -0
- thesis_ci-0.5.0/spec/templates/lynch/_common.yml +5 -0
- thesis_ci-0.5.0/spec/templates/lynch/asset_play.yml +32 -0
- thesis_ci-0.5.0/spec/templates/lynch/cyclical.yml +32 -0
- thesis_ci-0.5.0/spec/templates/lynch/fast_grower.yml +41 -0
- thesis_ci-0.5.0/spec/templates/lynch/slow_grower.yml +32 -0
- thesis_ci-0.5.0/spec/templates/lynch/stalwart.yml +52 -0
- thesis_ci-0.5.0/spec/templates/lynch/turnaround.yml +32 -0
- thesis_ci-0.5.0/src/thesis_ci/__init__.py +8 -0
- thesis_ci-0.5.0/src/thesis_ci/__main__.py +5 -0
- thesis_ci-0.5.0/src/thesis_ci/brier.py +104 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/__init__.py +3 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/archive.py +306 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/code.py +328 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/constitution.py +471 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/governance.py +258 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/language.py +90 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/public.py +390 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/schema.py +188 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/sources.py +143 -0
- thesis_ci-0.5.0/src/thesis_ci/checks/thesis_tests.py +269 -0
- thesis_ci-0.5.0/src/thesis_ci/cli.py +269 -0
- thesis_ci-0.5.0/src/thesis_ci/contract.py +78 -0
- thesis_ci-0.5.0/src/thesis_ci/engine.py +234 -0
- thesis_ci-0.5.0/src/thesis_ci/evaluate.py +860 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/README.md +11 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/companies/ACME/sources.yml +6 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/companies/ACME/valuation.yml +26 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/companies/BETA/sources.yml +6 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/companies/BETA/valuation.yml +21 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/decision-log/2026.yml +10 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/escalations/2026-09-21-BETA-management.yml +9 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/hq/ranking.yml +5 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/memos/2026-09-20-ACME-entry.yml +21 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/memos/2026-09-22-BETA-trim.yml +17 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/prompts/03-update.md +13 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/prompts/14-blind-read.md +11 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/private/repo.yml +4 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/README.md +3 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/agents/auditor.yml +8 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/agents/blind_reader.yml +8 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/agents/company_manager.yml +9 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/ledger.yml +22 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/prereg/FY2027Q1-owner.yml +20 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/prereg/FY2027Q1.settlement.yml +7 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/prereg/FY2027Q1.yml +32 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/sources.yml +22 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/story.md +15 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/thesis.yml +165 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/companies/ACME/updates/2026-09-22.md +11 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/constitution/decision-rights.yml +49 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/constitution/rules.yml +56 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/forecasts/2026.yml +13 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/industries/widgets/README.md +3 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/industries/widgets/industry.yml +38 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/industries/widgets/sources.yml +5 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/letters/2026-09.md +4 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/pipeline/llm.py +3 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/repo.yml +3 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/sources.yml +5 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/trust/levels.yml +6 -0
- thesis_ci-0.5.0/src/thesis_ci/fixtures/workspace/public/zh-CN/companies/ACME/story.md +14 -0
- thesis_ci-0.5.0/src/thesis_ci/metrics.py +514 -0
- thesis_ci-0.5.0/src/thesis_ci/periods.py +168 -0
- thesis_ci-0.5.0/src/thesis_ci/readings.py +151 -0
- thesis_ci-0.5.0/src/thesis_ci/repo.py +437 -0
- thesis_ci-0.5.0/src/thesis_ci/scaffold.py +98 -0
- thesis_ci-0.5.0/src/thesis_ci/selftest.py +453 -0
- thesis_ci-0.5.0/src/thesis_ci/staleness.py +85 -0
- thesis_ci-0.5.0/src/thesis_ci/starter/README.md +43 -0
- thesis_ci-0.5.0/src/thesis_ci/starter/companies/ACME/sources.yml +12 -0
- thesis_ci-0.5.0/src/thesis_ci/starter/companies/ACME/story.md +15 -0
- thesis_ci-0.5.0/src/thesis_ci/starter/companies/ACME/thesis.yml +105 -0
- thesis_ci-0.5.0/src/thesis_ci/textscan.py +360 -0
- thesis_ci-0.5.0/tests/conftest.py +30 -0
- thesis_ci-0.5.0/tests/fixtures/archive_rules.yml +2110 -0
- thesis_ci-0.5.0/tests/test_archive_rules.py +136 -0
- thesis_ci-0.5.0/tests/test_brier.py +52 -0
- thesis_ci-0.5.0/tests/test_checks.py +601 -0
- thesis_ci-0.5.0/tests/test_chinese.py +97 -0
- thesis_ci-0.5.0/tests/test_cli.py +180 -0
- thesis_ci-0.5.0/tests/test_english.py +567 -0
- thesis_ci-0.5.0/tests/test_evaluate.py +536 -0
- thesis_ci-0.5.0/tests/test_hardening.py +560 -0
- thesis_ci-0.5.0/tests/test_metrics.py +175 -0
- thesis_ci-0.5.0/tests/test_packaging.py +73 -0
- thesis_ci-0.5.0/tests/test_profiles.py +216 -0
- thesis_ci-0.5.0/tests/test_readings.py +100 -0
- thesis_ci-0.5.0/tests/test_registry.py +98 -0
- thesis_ci-0.5.0/tests/test_spec_0_2.py +651 -0
- thesis_ci-0.5.0/tests/test_textscan.py +115 -0
- thesis_ci-0.5.0/zh-CN/README.md +181 -0
- thesis_ci-0.5.0/zh-CN/docs/reference.md +13 -0
- thesis_ci-0.5.0/zh-CN/spec/SPEC.md +455 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
The specification (`spec/`) and the tool (`thesis_ci`) are released together. Incompatible specification changes
|
|
4
|
+
before v1.0 are listed here one by one.
|
|
5
|
+
|
|
6
|
+
## v0.5.0 — Profiles and init (2026-09-27)
|
|
7
|
+
|
|
8
|
+
thesis-ci is usable by people other than its first user. Every check now belongs to a profile, `core`, `pipeline` or
|
|
9
|
+
`owners-office`, and an archive chooses in `repo.yml` which profiles it runs, so the checks that encode one
|
|
10
|
+
investor's rules can be left out. `thesis-ci init` starts a new archive that lints clean. The checks themselves are
|
|
11
|
+
unchanged, and an archive without `profiles` lints exactly as before; archives keep `spec_version: "0.2"`.
|
|
12
|
+
|
|
13
|
+
### New
|
|
14
|
+
|
|
15
|
+
- Profiles (SPEC 8.6). `spec/checks.yml` gains a top-level `profiles` list and a `profile` for every check:
|
|
16
|
+
- `core` (21 checks), for any thesis archive: schemas, sources, thesis tests with their coverage and metrics,
|
|
17
|
+
staleness, the two-minute story, pre-registration timing and immutability, frozen thresholds, no secrets, no
|
|
18
|
+
price feed, no trading, and the public-content checks that keep valuations, prices, position amounts and advice
|
|
19
|
+
out of a public archive;
|
|
20
|
+
- `pipeline` (4), for an archive written by an LLM research pipeline: `C-LLM-ENTRY`, `C-AGENT-ISOLATION`,
|
|
21
|
+
`C-PROMPT-ISOLATION`, `C-TRUST-WRITE`;
|
|
22
|
+
- `owners-office` (10), the Owner's Office constitution: `C-RATING-ORDER`, `C-CONCENTRATION`, `C-DISCOUNT-RATE`,
|
|
23
|
+
`C-SELL-REASONS`, `C-HURDLE`, `C-SINGLE-ORDER`, `C-DEFAULT-HOLD`, `C-DECISION-RIGHTS`, `C-CONSTITUTION-MAP`,
|
|
24
|
+
`C-LANGUAGE`.
|
|
25
|
+
|
|
26
|
+
SPEC 8.6 gives the reason for each borderline assignment (`C-TESTS-COVERAGE`, `C-TESTS-CAPALLOC` and
|
|
27
|
+
`C-TEST-QUAL-EVIDENCE` are `core`; `C-LLM-ENTRY` and `C-TRUST-WRITE` are `pipeline`; `C-RATING-ORDER`,
|
|
28
|
+
`C-DECISION-RIGHTS` and `C-LANGUAGE` are `owners-office`).
|
|
29
|
+
- `repo.yml` takes an optional `profiles: [core, ...]` (`repo.schema.json`). Without it every profile runs. A value that
|
|
30
|
+
is not a non-empty list of distinct, known profiles also runs every profile, and `C-SCHEMA` reports it. An older
|
|
31
|
+
thesis-ci rejects the new field (`C-SCHEMA`), so upgrade before adding it.
|
|
32
|
+
- `thesis-ci lint --profile <profile>,...` (comma-separated or repeated) runs those profiles instead of the ones in
|
|
33
|
+
`repo.yml`; `--only` still runs exactly the checks it names, whatever the profiles. When profiles select the checks,
|
|
34
|
+
the summary line names them (`21 checks (profiles: core) on public repo ...`); with no selection it reads as before,
|
|
35
|
+
and the JSON output is unchanged. The GitHub Action takes a matching `profile` input.
|
|
36
|
+
- `thesis-ci checks` shows each check's profile (a `profile` column, and a `profile` key in the JSON rows).
|
|
37
|
+
- `thesis-ci init <dir> [--visibility public|private] [--profiles core,...]` writes `repo.yml`, a short `README.md`
|
|
38
|
+
and one fictitious example company, `companies/ACME/`: `thesis.yml` with five tests (three quantitative, one
|
|
39
|
+
qualitative, one staleness: five is the minimum, and together they cover the six dimensions `core` requires),
|
|
40
|
+
`story.md` and `sources.yml`. Review dates are the day of the run and the tests take effect from the next quarter,
|
|
41
|
+
so the archive lints with no errors and no warnings. A public archive with `owners-office` also gets
|
|
42
|
+
`constitution/rules.yml` and `constitution/decision-rights.yml` from the example archive. `init` never overwrites a
|
|
43
|
+
file: if any of its files exists, it writes nothing and exits 2. `thesis_ci.scaffold.init_archive()` does the same
|
|
44
|
+
from Python.
|
|
45
|
+
|
|
46
|
+
### Documentation
|
|
47
|
+
|
|
48
|
+
- The README describes the three profiles and how to choose them in place of the "Opinionated by default" paragraph,
|
|
49
|
+
adds `init` and `--profile` to the Quickstart, a profile column to the table of checks, and drops the planned
|
|
50
|
+
switch from "Not included yet". SPEC 1, 8, 8.1, 8.5, 8.6 (new) and 10 are updated, and `docs/reference.md` says the
|
|
51
|
+
constitution files are required only with `owners-office`; the Chinese versions follow.
|
|
52
|
+
|
|
53
|
+
## v0.4.0 — The evaluation engine (2026-09-27)
|
|
54
|
+
|
|
55
|
+
thesis-ci now judges quantitative thesis tests: given a company's `thesis.yml` and a document of metric readings, it
|
|
56
|
+
writes the `ci_results` the quarterly update reads, with each test's result, the readings it rests on and the reason
|
|
57
|
+
(SPEC 4.5). It can also compute the `data: xbrl` metrics from an SEC companyfacts document. Archive file formats are
|
|
58
|
+
unchanged; archives keep `spec_version: "0.2"`.
|
|
59
|
+
|
|
60
|
+
### New
|
|
61
|
+
|
|
62
|
+
- `thesis-ci evaluate <archive> --company <TICKER> --period FY<year>Q<quarter> --readings <file> [--today YYYY-MM-DD]
|
|
63
|
+
[--format yaml|json]` prints the `ci_results` document. It exits 0 whenever it ran (a failing test is a result, not
|
|
64
|
+
an error) and 2 on a usage error: an unreadable thesis, an invalid readings file, or companies that disagree.
|
|
65
|
+
- `thesis_ci.evaluate`: `evaluate_company(thesis, readings, period, today)` returns the `ci_results` document;
|
|
66
|
+
`needed_readings(thesis, period)` lists what the tests in force need (metric, segment, periods including the
|
|
67
|
+
earlier periods of `consecutive` and the year-earlier bases of `increase`/`decrease`, unit, data kind, tests);
|
|
68
|
+
`shape_problems(test)` says why the engine cannot judge a rule. Results are `pass`, `warn`, `fail`,
|
|
69
|
+
`undetermined` or `not_due` (the test was not judged this period: an annual rule outside Q4, `evaluate_on`,
|
|
70
|
+
`evaluate_from`). Tests not in force (`effective_from`, `retired_at`) are listed apart, with the superseding test.
|
|
71
|
+
- Rule semantics (SPEC 4.5): `period` is inherited by sub-rules; `consecutive` on a comparison asks for N periods in a
|
|
72
|
+
row, on `all_of`/`any_of` for the combination to hold in the same period N periods in a row; periods before
|
|
73
|
+
`evaluate_from` never count toward a run; three-valued logic, so a known "not triggered" in `all_of` (or a known
|
|
74
|
+
"triggered" in `any_of`) decides whatever else is missing, but a run whose latest period has no reading stays
|
|
75
|
+
undetermined; `warn_rule` is judged only when the fail rule is not triggered; missing data is never guessed.
|
|
76
|
+
- `increase` / `decrease` compare with the same period one fiscal year earlier (the same quarter a year earlier for a
|
|
77
|
+
quarter rule, the previous year for a year rule), as the Lynch templates and every archive rule that uses them say
|
|
78
|
+
("down year on year"). `pp` is a difference of percentages, `%` a relative change of an amount, the metric's own
|
|
79
|
+
unit a difference.
|
|
80
|
+
- Readings documents (`spec/schemas/readings.schema.json`, `thesis_ci.readings`): `{company, as_of, readings: [{metric,
|
|
81
|
+
period, value, unit, source, basis?, note?, segment?, series?}]}`. Periods may be `FY<year>H<half>` for half-year
|
|
82
|
+
rules; `value: null` (with a `note`) means checked, nothing to measure; `segment` matches a test's `params.segment`;
|
|
83
|
+
`series` carries parallel readings such as one per holder group; an `op: event` sub-rule without a metric is keyed
|
|
84
|
+
by the test id. Units of one kind are converted (`USD` and `USD 100 million`, `RMB` and `CNY`).
|
|
85
|
+
- `thesis_ci.metrics.readings_from_companyfacts(companyfacts, metric_ids, periods, fiscal_year_end, *, ticker=None,
|
|
86
|
+
definitions=None, currency=None)`: a pure function over a downloaded companyfacts JSON. Only 10-K, 10-Q, 20-F and
|
|
87
|
+
40-F facts count, each placed in the fiscal calendar by its dates; the most recently filed value of a span wins;
|
|
88
|
+
Q2, Q3, Q4 and H2 are derived from year-to-date figures when no filing reports them (Q4 = FY − 9M), except share
|
|
89
|
+
counts and per-share amounts; monetary facts are read in the reporting currency (PDD in CNY, not its USD
|
|
90
|
+
translation). It computes 20 of the 21 registered `xbrl` metrics (`book_value_per_share_yoy` has no registered
|
|
91
|
+
share-count concept) and `metric_def`s whose formula is the growth of one quantity (AXP-Q1, AXP-Q15). Sources read
|
|
92
|
+
`<TICKER>-XBRL#<concept>:<accession>`; `basis` spells out the formula and the values used.
|
|
93
|
+
- `spec/schemas/ci-results.schema.json` describes the output. `thesis_ci.periods` gains fiscal halves and years and the
|
|
94
|
+
fiscal calendar (`Fiscal`, `parse_fiscal`, `period_dates`).
|
|
95
|
+
|
|
96
|
+
### Changes
|
|
97
|
+
|
|
98
|
+
- `C-TEST-METRIC` also reports a rule the engine cannot judge: a threshold unit that does not fit the metric, a `%`
|
|
99
|
+
threshold on `increase`/`decrease` of a percentage (ambiguous: write `pp`), `consecutive` on `all_of`/`any_of` over
|
|
100
|
+
sub-rules of another period, an `evaluate_on` quarter in which a year or half rule can never be judged, or several
|
|
101
|
+
metric-less events in one test. Two new selftest cases. All 92 quantitative tests of the six archives pass.
|
|
102
|
+
- Lynch template `cyclical`, test `Q-cycle`: the rule compared the provision's level in USD with 50%; it is now
|
|
103
|
+
`{op: increase, threshold: 50, unit: "%", consecutive: 2, period: quarter}`, which is what its `fail_if` says
|
|
104
|
+
(provision growth above 50% year on year). An archive that copied the old rule should supersede it.
|
|
105
|
+
- `metrics.yml`: `interest_expense_minus_income_growth` also accepts `us-gaap:InterestExpenseOperating`, which filers
|
|
106
|
+
such as American Express use instead of `us-gaap:InterestExpense` since 2024. A header note says how formulas over
|
|
107
|
+
several quantities map to concepts.
|
|
108
|
+
|
|
109
|
+
### Documentation and wording
|
|
110
|
+
|
|
111
|
+
- The README opens with what thesis-ci is for, a sample test and who it serves; it says which parts ship and which are
|
|
112
|
+
planned, and that several checks encode one investor's rules (a switch to turn them off is planned). The reference
|
|
113
|
+
on how checks read an archive moves to `docs/reference.md`.
|
|
114
|
+
- Clearer titles for 14 checks in `spec/checks.yml` (the checks themselves are unchanged).
|
|
115
|
+
- `prereg-settlement.schema.json`: `reasoning` is described as an audit record of how the criterion applies, not as
|
|
116
|
+
step-by-step reasoning.
|
|
117
|
+
|
|
118
|
+
## v0.3.0 — English first (2026-09-25)
|
|
119
|
+
|
|
120
|
+
The archives are English-first from now on: the Chinese version of a key document lives at `zh-CN/<same path>`, and
|
|
121
|
+
every other file is in English. thesis-ci follows: its documentation, specification data and example archive are in
|
|
122
|
+
English, the checks read English content properly, and a new check keeps English files free of Chinese, Japanese and
|
|
123
|
+
Korean text. File formats are unchanged apart from the optional `title_original`; archives keep `spec_version: "0.2"`.
|
|
124
|
+
|
|
125
|
+
### Incompatible changes
|
|
126
|
+
|
|
127
|
+
- New check `C-LANGUAGE` (both, error; 35 checks): a text file outside the root `zh-CN/` directory must not contain
|
|
128
|
+
Chinese, Japanese or Korean characters (CJK ideographs, kana, hangul, CJK punctuation and full-width forms). Exempt
|
|
129
|
+
are `zh-CN/`; tests and fixtures (`tests/`, `test/` and `fixtures/` directories, `test_*.py`, `*_test.py`,
|
|
130
|
+
`conftest.py`); and the `title_original` of a `sources.yml` entry. One error per file, at its first line with CJK
|
|
131
|
+
text. An archive still written in Chinese fails until its translation lands.
|
|
132
|
+
- English sentences are split at `.`, `!`, `?` and `;` followed by whitespace (not after `U.S.`, `Inc.`, `Corp.`,
|
|
133
|
+
`Ltd.`, `e.g.`, `i.e.`, `vs.`, `No. 1`, an initial or an abbreviated month, and not in a decimal or a source tag). A
|
|
134
|
+
line break inside an English paragraph no longer ends a sentence; blank lines, headings, list items, table rows and
|
|
135
|
+
block quotes do. `C-SRC-TAG`, `C-SRC-FACT` and the price-multiple rule of `C-PUBLIC-NO-VALUATION` work sentence by
|
|
136
|
+
sentence, so one tag no longer covers several English sentences on a line, and a tag on the next line of a
|
|
137
|
+
hard-wrapped sentence now counts. A tag written right after the period (`16%.[src:TAG]`) belongs to that sentence.
|
|
138
|
+
Lines with CJK characters are split exactly as before. A finding points at the line of the fact number.
|
|
139
|
+
- The Chinese version of public content is public content: the wording checks of `C-PUBLIC-NO-VALUATION`,
|
|
140
|
+
`C-PUBLIC-NO-ADVICE`, `C-PUBLIC-NO-AMOUNTS`, `C-NO-PRICE-FEED` (share prices) and `C-DEPENDS` (neutrality), and
|
|
141
|
+
`C-SRC-TAG`, read `zh-CN/companies/`, `zh-CN/industries/`, `zh-CN/forecasts/`, `zh-CN/letters/` and
|
|
142
|
+
`zh-CN/mistakes.md`; tags there resolve as for the English file (SPEC 8.5).
|
|
143
|
+
- `spec/checks.yml` ties checks to constitution rules as "Constitution rule N" (it used the Chinese form);
|
|
144
|
+
`C-CONSTITUTION-MAP` reads the new form.
|
|
145
|
+
|
|
146
|
+
### English support
|
|
147
|
+
|
|
148
|
+
- Fact numbers (SPEC 3.4): English units in any letter case (`3 Billion`, `16 PERCENT`), plus `ppt` / `ppts`, `bln`,
|
|
149
|
+
`mln`, currency names (`dollars`, `euros`, `yuan`, `yen`, ...), ISO codes after the number (`5 USD`) and `CHF`,
|
|
150
|
+
`INR`, `KRW`, `TWD`, `SGD` before it. English dates (`September 30, 2026`), `3Q26` / `1H26` and section numbers
|
|
151
|
+
(`Item 15`, `Note 12`) are not quantities for the price-multiple rule.
|
|
152
|
+
- 00 §H4 in English (SPEC 7.5). `C-PUBLIC-NO-VALUATION`: `implied return` (annual, annualized, IRR), `price grade`,
|
|
153
|
+
`price rating`, `value centre`; `central value`, `fair` / `value` / `buy` / `cheap range`, `intrinsic value` and `margin of safety`
|
|
154
|
+
with a number (and "a 30% margin of safety", "a 30% discount to intrinsic value"); a price event on a range
|
|
155
|
+
("entered the buy range"); the multiples `price-to-earnings`, `price/earnings`, `PE ratio` and "trades at 25 times
|
|
156
|
+
earnings". `C-PUBLIC-NO-ADVICE`: recommending a buy, a sell, adding, reducing, or opening or closing a position
|
|
157
|
+
("analysts recommend buying the stock", "we recommend ACME", "our recommendation is to buy"), ratings ("rated a Buy", "upgraded to Buy", "Rating: Sell", "Buy-rated", "is a buy"),
|
|
158
|
+
"should buy / sell" with the investor as subject, "the shares should be sold", adding to, trimming or accumulating a
|
|
159
|
+
position, buying on dips, "top pick", "worth buying", "time to buy". As with the Chinese terms, a negative sentence is
|
|
160
|
+
no exception ("we do not recommend buying" fails, 00 §H4). Not advice: a company buying back its own
|
|
161
|
+
shares ("buybacks", "the company should buy back stock", "we recommend buying back shares"), a company's own trades
|
|
162
|
+
("Berkshire trimmed its position"), corporate actions ("the board recommended selling the division") and product
|
|
163
|
+
names ("Best Buy", "Buy with Prime", "Buy Box"). The v0.2 pattern "I / we recommend adding / trimming / reducing" now
|
|
164
|
+
needs a security or a position after the verb, so "we suggest adding a source tag" or "we recommend reducing debt"
|
|
165
|
+
(in a README, say) no longer fails.
|
|
166
|
+
- `C-PUBLIC-NO-VALUATION` and `C-PUBLIC-NO-ADVICE` also read the progress files `docs/STATUS.md` and `CLAUDE.md` (and
|
|
167
|
+
their Chinese versions): a progress file once listed two companies' price-grade changes. The rule documents
|
|
168
|
+
(`docs/DESIGN.md`, `docs/decisions/`, `constitution/`) are still not read. A price grade next to a ticker
|
|
169
|
+
("AXP B− → C", "AXP: C") in a sentence about prices or valuation is an error, unless the sentence speaks of the
|
|
170
|
+
business, management, quality, culture or capital-allocation ratings.
|
|
171
|
+
- `C-STORY`: a story in English is at most 350 words, about two minutes read aloud; a story in Chinese, Japanese or
|
|
172
|
+
Korean keeps the 700-character limit. A story is measured in characters when it has at least as many CJK characters
|
|
173
|
+
as English words.
|
|
174
|
+
- `C-DEPENDS`: "we hold ACME" or "I own shares of ACME" in an industry module (a ticker in capitals; "we hold that ..."
|
|
175
|
+
is an opinion). `C-PUBLIC-NO-AMOUNTS`: a portfolio weight in a two-minute story.
|
|
176
|
+
- `C-SINGLE-ORDER`: a negation up to 12 characters before the tranche wording (`without tranches`) now counts.
|
|
177
|
+
|
|
178
|
+
### Documentation and data in English
|
|
179
|
+
|
|
180
|
+
- `README.md`, `spec/SPEC.md`, `CHANGELOG.md` and `LICENSE-SPEC.md` are in English. The Chinese text of the README and
|
|
181
|
+
the specification is kept in `zh-CN/README.md` and `zh-CN/spec/SPEC.md`, which carry the 0.3.0 additions too.
|
|
182
|
+
- The titles and descriptions of `spec/checks.yml`, the descriptions and `where` of `spec/metrics.yml`, the titles and
|
|
183
|
+
descriptions of the JSON Schemas and the Lynch templates (claims, questions, `fail_if`, `where`, notes) are in
|
|
184
|
+
English; every id, key, enum and number is unchanged. `sources.schema.json` has an optional `title_original`.
|
|
185
|
+
- The example archive (`src/thesis_ci/fixtures/workspace`) is in English, with the Chinese version of the ACME story
|
|
186
|
+
in `public/zh-CN/` and a `title_original` in `public/companies/ACME/sources.yml`. The selftest cases are in English;
|
|
187
|
+
the cases that fed Chinese text are kept in `tests/test_chinese.py`.
|
|
188
|
+
- Code comments, docstrings and lint messages are in English; the Chinese detection lists (units, the §H4 phrases and
|
|
189
|
+
patterns, neutrality phrases, sell reasons, tranche wording) are unchanged.
|
|
190
|
+
|
|
191
|
+
## v0.2.1 — bug fix (2026-09-25)
|
|
192
|
+
|
|
193
|
+
- `C-PREREG-IMMUTABLE`: a pending proof checked while the OpenTimestamps calendars were unreachable was reported as
|
|
194
|
+
an error ("the file changed after it was timestamped"), which was false. The check now compares the file's sha256
|
|
195
|
+
with the digest the proof commits to locally first (`ots info`, no network): a different digest or an unreadable
|
|
196
|
+
proof is an error; once the digest matches, `ots verify` failing for lack of a Bitcoin node, a pending attestation or
|
|
197
|
+
unreachable calendars is a warning, and only a client message that the proof itself is bad is an error.
|
|
198
|
+
|
|
199
|
+
## v0.2.0 — specification 0.2 (2026-09-24)
|
|
200
|
+
|
|
201
|
+
Specification 0.2 aligns the format with the owner's rulebook (series rules 00 v3: §H4, §V1/§V7/§V10/§V11/§V13/§V20,
|
|
202
|
+
§G3/§G7/§G8/§G9, §F2/§F5/§F6). Archives written for 0.1 must be migrated; `C-SCHEMA` reports every file that is
|
|
203
|
+
not. The hardening changes below (previously unreleased) ship in this version too.
|
|
204
|
+
|
|
205
|
+
### Incompatible changes
|
|
206
|
+
|
|
207
|
+
- `thesis.yml`: `schema_version: "0.2"`. `reviewed` keys are the twelve dossier parts `business`, `economics`,
|
|
208
|
+
`moat`, `capital_allocation`, `management`, `culture`, `runway`, `valuation`, `bear_case`, `monitoring`, `thesis`,
|
|
209
|
+
`breakers` (required) plus `munger`, `unknowns` (optional); `ratings`, `matrix`, `peers`, `ranking` and
|
|
210
|
+
`failure_modes` are gone. Staleness `section` takes the same fourteen keys. Lynch `_common.yml`: `S-failure`
|
|
211
|
+
(`failure_modes`) is now `S-bear_case` (`bear_case`, 2 quarters).
|
|
212
|
+
- Every thesis test requires `effective_from` (`FY<year>Q<quarter>`); optional `supersedes` (a test id) and
|
|
213
|
+
`retired_at`. Retired tests are records: they no longer count toward the five tests, the three types or the
|
|
214
|
+
covers of `C-TESTS-MIN`, `C-TESTS-COVERAGE`, `C-TESTS-CAPALLOC`, and `C-STALENESS` skips them.
|
|
215
|
+
- Qualitative tests require `where` (string or list) and `lookback` (integer ≥ 1); optional `judge_notes`. The Lynch
|
|
216
|
+
templates' qualitative tests carry default `where` and `lookback`.
|
|
217
|
+
- `prereg.schema.json` describes the immutable items file only: required `company`, `event` (`period`
|
|
218
|
+
`FY<year>Q<quarter>`, `expected_release`, `form`, `placeholder`), `deadline` (ISO 8601 date-time with a UTC
|
|
219
|
+
offset), `author`, `items`; optional `horizon`. Items (1–8) require `id` (`<TICKER>-<period>-<n>`), `statement`,
|
|
220
|
+
`probability` (0.05–0.95), `criterion`, `data_source`, `horizon`, `resolves_by`, `domain`, `added_by`; optional
|
|
221
|
+
`pillar`, `falsifies_thesis`, `reference`. `merged_at`, `ots_proof`, `acceptance_datetime`, `accession` and
|
|
222
|
+
results moved to the new `prereg/<period>.settlement.yml` (`prereg-settlement.schema.json`). The owner's file
|
|
223
|
+
`prereg/<period>-owner.yml` (`author: owner`) may add `overrides`; the system's file may not.
|
|
224
|
+
- `ledger.schema.json`: `probability` (0.05–0.95) is required for `side: system|owner`, whose status is one of
|
|
225
|
+
`pending`, `kept`, `not_kept`, `undetermined`; new `last_mentioned`, `acknowledged_source`.
|
|
226
|
+
- `valuation.schema.json`: required `doc_status` (`proposed` / `effective`); new `margin_of_safety`,
|
|
227
|
+
`comparable_anchor`, `discount_rate.risk_free_date`; `discount_rate.note` (the premium rationale) is required once
|
|
228
|
+
`total` is a number; `price_rating` is `A`–`E` without a sign; `error_band` is documented as an absolute band in
|
|
229
|
+
the unit of `center`; the quality description no longer says "higher quality, lower premium".
|
|
230
|
+
- `memo.schema.json`: required `options` (at least two, one with `key: maintain`) and `drafted_by:
|
|
231
|
+
hq_capital_allocator`; new `evidence`, `trigger`; `company` may be omitted for `amend_constitution`;
|
|
232
|
+
`constitution_refs` accept `R<n>` and `H<n>`. New `escalation.schema.json` for the private `escalations/*.yml`.
|
|
233
|
+
- `decision-rights.schema.json`: `ranking` is `{rule, candidates?, rotation?}` (no `order`); `trust.routing`
|
|
234
|
+
(`"0"`–`"3"`) is required, `trust.scoring` and a top-level `gate` are optional; actions add `valuation_update` and
|
|
235
|
+
`prompt_change`.
|
|
236
|
+
- `agent.schema.json`: roles are `company_manager`, `auditor`, `model_reviewer`, `red_team`, `synthesis_reviewer`,
|
|
237
|
+
`design_reviewer`, `blind_reader`, `judge`, `settler`, `extractor`, `hq_capital_allocator`,
|
|
238
|
+
`industry_researcher`, `typesetter`.
|
|
239
|
+
- `C-TEST-METRIC`: a rule's `metric` that does not resolve is an error (was a warning).
|
|
240
|
+
- `C-RATING-ORDER` runs on both archives (the ranking file is private).
|
|
241
|
+
|
|
242
|
+
### Additions
|
|
243
|
+
|
|
244
|
+
- `metric_def.components` (component → `{description, unit, where?, xbrl?}`), `rule.metric` as `<metric>.<component>`,
|
|
245
|
+
`rule.evaluate_on` / `rule.evaluate_from`, test `data: external | mixed`, `origin` values `archive:breaker`,
|
|
246
|
+
`archive:watch`, `proposal:04B|04B-lite|07|08|11`. `params.metric_defs` still resolves during the migration.
|
|
247
|
+
- `sources.yml` kinds `news`, `review`; SPEC 3.3 follows 00 §E1 (owner reports `<TICKER>-RPT<n>-<YYYY-MM-DD>`).
|
|
248
|
+
- `industry.yml` optional `trust_level`; `trust/levels.yml` (SPEC 4.2) records the pipeline's trust levels.
|
|
249
|
+
- `metrics.yml`: card-issuer metrics (`net_card_fees_yoy`, `card_member_services_to_revenue`,
|
|
250
|
+
`discount_revenue_to_billed_business`, `reserve_build_release`); the header no longer says 20-F filers use
|
|
251
|
+
`ifrs-full` (the taxonomy follows the accounting standard: PDD reports under US GAAP).
|
|
252
|
+
- `lint --base-ref REF --period FY####Q#` (and the Action inputs `base-ref`, `period`).
|
|
253
|
+
- New checks: `C-PREREG-IMMUTABLE` (error: timestamp proof after the deadline, `ots verify` when installed),
|
|
254
|
+
`C-TRUST-WRITE` (warning: trust levels and `reviewed_sections`), `C-TEST-FROZEN` (error: thresholds of tests in
|
|
255
|
+
force are not edited or removed after the base ref), `C-PROMPT-ISOLATION` (warning: prompt inputs against the
|
|
256
|
+
role's `cannot_see`). 34 checks.
|
|
257
|
+
|
|
258
|
+
### Changed checks
|
|
259
|
+
|
|
260
|
+
- `C-DISCOUNT-RATE`: the cross-company rule "higher quality must not carry a higher premium" is removed (it
|
|
261
|
+
contradicted §V10: the premium comes from the company's own record). Checks `total = risk_free + premium`,
|
|
262
|
+
a non-empty `discount_rate.note`, a non-empty `method_note`, and warns when `risk_free_date` is missing.
|
|
263
|
+
- `C-RATING-ORDER`: no longer reads `ranking.order`; checks the business and management ratings and that every
|
|
264
|
+
row of the private `hq/ranking.yml` states a `reason`.
|
|
265
|
+
- `C-PUBLIC-NO-ADVICE` / `C-PUBLIC-NO-VALUATION`: the literal phrase lists are exactly the terms of 00 §H4
|
|
266
|
+
(`建议加仓`, `建议减仓` added; `buy rating`, `sell rating`, `we recommend …` are still caught as other wordings);
|
|
267
|
+
`mistakes.md` and `companies/*/updates/` are scanned; a price-derived multiple (`市盈率`, `P/E`, `市值`,
|
|
268
|
+
`自由现金流收益率`, `FCF yield`) with a number in the same sentence is an error; `escalations/` is private-only.
|
|
269
|
+
- `C-NO-PRICE-FEED`: the private `pipeline/price_history.py` is allowed next to `pipeline/price_alert.py`.
|
|
270
|
+
- `C-PREREG-TIMING`: reads `merged_at` / `acceptance_datetime` from the settlement file; the owner's file must use
|
|
271
|
+
the system file's deadline.
|
|
272
|
+
- `C-SCHEMA`: prereg file names, periods, authors and item ids must agree; `repo.yml` at `spec_version: "0.1"`
|
|
273
|
+
warns during the migration.
|
|
274
|
+
- `C-SRC-FACT`: `acknowledged_source` must resolve; the system's and the owner's ledger predictions need no tags
|
|
275
|
+
(00 §E1).
|
|
276
|
+
|
|
277
|
+
### Hardening after an adversarial mutation run (2026-09-24)
|
|
278
|
+
|
|
279
|
+
A mutation run injected one or more realistic violations per check into an independent clean archive pair,
|
|
280
|
+
plus false-positive probes. Every violation below used to pass the lint, or clean content used to fail it. Each
|
|
281
|
+
fix has a regression test (`tests/test_hardening.py`) and, for violations, a selftest case. The specification
|
|
282
|
+
files are unchanged; the lint is stricter where noted, so content that passed before can now fail.
|
|
283
|
+
|
|
284
|
+
#### File walking and parsing (all checks)
|
|
285
|
+
|
|
286
|
+
- Hidden directories other than `.github` were skipped entirely, so a secret in `.claude/settings.json`, a model
|
|
287
|
+
call in `.claude/hooks/`, or `valuation.yml` under `.data/` went unseen. Only `.git`, virtual environments,
|
|
288
|
+
caches, `build/` and `dist/` are skipped now. Inside a git work tree, files git ignores are not scanned (they are
|
|
289
|
+
not published); if the archive itself is ignored by an enclosing repository, everything is scanned.
|
|
290
|
+
- Key scans read only the first document of a YAML file: `value_ranges` or `cost_basis` after a `---` separator
|
|
291
|
+
passed. They now read every document, and JSON data files too (tool configuration such as `package.json` or
|
|
292
|
+
`.vscode/` excepted). Key names are normalized (`valueRanges`, `Value-Ranges`).
|
|
293
|
+
- A UTF-8 byte-order mark or Windows line endings made `story.md` look like it had no front matter (false error
|
|
294
|
+
in `C-SCHEMA` / `C-STORY`), and CRLF fenced code blocks were not masked.
|
|
295
|
+
- Crashes found by type fuzzing (a crashing check reports only an internal error and hides its findings):
|
|
296
|
+
`sources: -1.5` or `sources: true` in a sources.yml crashed `C-SRC-TAG` and `C-SRC-FACT`; a thesis test with
|
|
297
|
+
`type: []` crashed `C-TESTS-MIN`. 5,004 single-value type mutations now run without a crash.
|
|
298
|
+
|
|
299
|
+
#### Per check
|
|
300
|
+
|
|
301
|
+
- `lint --expect-visibility public|private` (and the Action's `expect-visibility` input) lints as that visibility
|
|
302
|
+
whatever `repo.yml` says and reports a mismatch under `C-SCHEMA`: without it, changing a public archive's
|
|
303
|
+
`repo.yml` to `private` skipped every public check in its own CI.
|
|
304
|
+
- `C-SCHEMA`: repeated YAML keys (PyYAML keeps the last value silently) are errors; `company` must match the
|
|
305
|
+
`companies/<TICKER>/` directory (thesis, ledger, valuation, prereg) and `id` the `industries/<id>/` directory;
|
|
306
|
+
a tag may be defined once per `sources.yml`; with `--counterpart`, both archives may not declare the same
|
|
307
|
+
visibility (a public archive relabelled `private` skipped every public check).
|
|
308
|
+
- `C-SRC-TAG`: other spellings of the SPEC 3.4 units are fact numbers (`16 percent`, `30 basis points`, `40 cents`,
|
|
309
|
+
`1.2 trillion`, `25x`, `€500`, `RMB 5`, `5 港元`, `5 千美元`, `3 百亿`, `$66`); two spaces between number and unit
|
|
310
|
+
(common in PDF text: `1,570 亿美元`) or a zero-width character no longer hide a fact. `mistakes.md` is scanned
|
|
311
|
+
(its own format says fact numbers carry tags). A date before a name (`2019-06 百亿补贴`) is not a fact.
|
|
312
|
+
- `C-SRC-FACT`: `source` fields resolve in every YAML file under `companies/` and `industries/` (update records and
|
|
313
|
+
every document of a stream), not only in the files that have a schema.
|
|
314
|
+
- `C-PUBLIC-NO-VALUATION`: `valuation.json`, key aliases (`price_target`, `target_price`, `intrinsic_value`, ...),
|
|
315
|
+
the value ranges by their DESIGN names with a number (`合理区间 280–330`) or a price event on them (`进入便宜区间`),
|
|
316
|
+
`估值中枢`, intrinsic value or margin of safety with a number.
|
|
317
|
+
- `C-PUBLIC-NO-ADVICE`: advice in other words (`建议减仓`, the conclusion wording DESIGN.md names; `建议加仓`,
|
|
318
|
+
`推荐买入`, `应该卖出`, `评级上调至买入`, `I recommend buying`, `strong sell`), in traditional characters, with spaces,
|
|
319
|
+
zero-width or full-width characters, or hyphenated (`strong-buy`). `overweight` / `underweight` count only as a
|
|
320
|
+
rating (a beverage module can write about overweight adults); `strong buyer power` no longer matches `strong buy`.
|
|
321
|
+
- `C-PUBLIC-NO-AMOUNTS`: IBKR paper accounts (`DU1234567`); position sizes in prose (`我们的仓位 15%`,
|
|
322
|
+
`our stake in X is 12%`; in `story.md` any `仓位 15%`, per SPEC 5). Python escapes such as `"\U00020000"` are
|
|
323
|
+
no longer taken for account numbers.
|
|
324
|
+
- `C-NO-PRICE-FEED`: quote clients by import (`polygon`, `akshare`, `tushare`, `pandas_datareader`, ...) and by name
|
|
325
|
+
or URL (Financial Modeling Prep, EOD Historical Data, Tiingo, ...); price-key aliases (`share_price`, ...); a
|
|
326
|
+
share price displayed in public prose (`现价 $350`, `shares closed at $350`; hard rule 2).
|
|
327
|
+
- `C-NO-TRADING`: Futu / moomoo, Tiger, Longbridge, Questrade, Wealthsimple, Tradier, tastytrade, Webull, Kite,
|
|
328
|
+
ccxt, `create_order` / `createOrder` / `submitOrder`; short names are matched as imports (`from __future__` is
|
|
329
|
+
not `futu`).
|
|
330
|
+
- `C-LLM-ENTRY`: more SDKs (`claude_agent_sdk`, `vertexai`, `groq`, `ollama`, `dashscope`, ...), model APIs over
|
|
331
|
+
HTTP (`api.anthropic.com`, ...), JavaScript SDK imports, notebook code cells, and model actions in workflows or
|
|
332
|
+
scripts (`anthropics/claude-code-action`). Dependency lists may still name the SDK that `pipeline/llm.py` uses.
|
|
333
|
+
- `C-NO-SECRETS`: GitHub `ghs_` / `ghu_` / `ghr_` tokens, private keys (PEM, PGP), Google `AIza` keys, Hugging Face
|
|
334
|
+
and Slack tokens, `sk-` keys in lowercase hex (DeepSeek / DashScope style), `apiKey` / `*_SECRET` / `*_PASSWORD`
|
|
335
|
+
literals. No longer reported: attribute references (`api_key = self.settings.api_key`), `"${ANTHROPIC_API_KEY}"`
|
|
336
|
+
and environment-variable names.
|
|
337
|
+
- `C-DEPENDS`: holdings and dependants in other words (`我们持有`, `仓位`, `our portfolio`, `our stake in`,
|
|
338
|
+
`依赖于本行业的公司`, `companies that rely on this industry`); `our holding company` (20-F wording) is allowed.
|
|
339
|
+
- `C-STORY`: the story's `status` and `category` must match `thesis.yml`.
|
|
340
|
+
- `C-SELL-REASONS`: the allowed reasons never go beyond the memo schema's enum, so an edited `sell_reasons` list in
|
|
341
|
+
the counterpart cannot let a `price_decline` trim or sell memo through.
|
|
342
|
+
- `C-HURDLE`: Berkshire's hurdle is the first bar and VOO's a second reference (00 §V6); the check no longer takes
|
|
343
|
+
the higher of the two. A buy/add memo's `hurdle` may not be below the first bar in the company's `valuation.yml`
|
|
344
|
+
and `implied_return` must beat it (error); clearing the first bar but not VOO is a warning. With no Berkshire
|
|
345
|
+
number, VOO is the bar. A holding below either line is a warning.
|
|
346
|
+
- `C-PUBLIC-NO-VALUATION`: the price-multiple terms also cover price-to-book (`市净率`, `P/B`, `price-to-book`) and
|
|
347
|
+
the market price against book value in words (`价格低于 1.2 倍账面`). A company's disclosed average repurchase price
|
|
348
|
+
against book is a company fact (00 §H2 item 3) and is not flagged.
|
|
349
|
+
- `C-CONCENTRATION`: 10–20% is an entry bar, not a target (constitution rule 4). A buy/add memo's `target_weight`
|
|
350
|
+
below 10% is an error; above 20% is allowed, with a warning when the new optional `weight_note` is empty. More
|
|
351
|
+
holdings than `max_holdings`, or `max_holdings` above 5, is a warning ("about 4–5 companies").
|
|
352
|
+
- `C-SINGLE-ORDER`: a buy/add memo whose `order.note` or `summary` plans tranches (`分两批`, `scale in`, ...) is an
|
|
353
|
+
error even with `order.type: single`; several live buy/add memos for one company within 31 days warn.
|
|
354
|
+
- `C-DECISION-RIGHTS`: `levels.L3.who` must name the owner (the chairman).
|
|
355
|
+
- `C-CONSTITUTION-MAP`: every check that `spec/checks.yml` ties to a constitution rule (by rule number) must be
|
|
356
|
+
referenced by some rule; dropping a rule from `rules.yml` no longer passes.
|
|
357
|
+
- `C-AGENT-ISOLATION`: `can_see` may not list what `cannot_see` hides (`conclusions`, `draft_conclusions`, `thesis`;
|
|
358
|
+
the last token decides, so `thesis_question_list` stays allowed).
|
|
359
|
+
- `C-PREREG-TIMING`: the deadline must fall before the release day (a deadline set after the release excused a
|
|
360
|
+
merge after the results); a UTC deadline is read on EDGAR's US Eastern clock. A deadline that has passed with no
|
|
361
|
+
`merged_at` recorded warns.
|
|
362
|
+
|
|
363
|
+
## v0.1.0 — 2026-09-24
|
|
364
|
+
|
|
365
|
+
First release.
|
|
366
|
+
|
|
367
|
+
### Specification v0.1
|
|
368
|
+
|
|
369
|
+
- `SPEC.md`: repository roles, directory layout, file-to-schema mapping, source tags and the fact-number rule,
|
|
370
|
+
`thesis.yml` and thesis tests, two-minute stories, industry modules, private value ranges.
|
|
371
|
+
- 14 JSON Schemas (draft 2020-12): `agent`, `constitution-rules`, `decision-log`, `decision-rights`, `forecast`,
|
|
372
|
+
`industry`, `ledger`, `memo`, `prereg`, `repo`, `sources`, `story`, `thesis`, `valuation`.
|
|
373
|
+
- `checks.yml`: 30 registered checks. `metrics.yml`: 29 metrics. Six Lynch monitoring templates.
|
|
374
|
+
|
|
375
|
+
### Tool
|
|
376
|
+
|
|
377
|
+
- `thesis-ci lint PATH [--format text|json] [--counterpart PATH] [--today DATE] [--only CHECK_ID ...]`:
|
|
378
|
+
reads `repo.yml`, runs every applicable check, exits 1 on any error-level finding.
|
|
379
|
+
- `thesis-ci checks`, `thesis-ci selftest`, `thesis-ci staleness`, `thesis-ci brier`.
|
|
380
|
+
- All 30 checks implemented and registered with `@check`; the selftest proves each one flags a violating fixture
|
|
381
|
+
and passes the bundled clean example archive.
|
|
382
|
+
- The spec ships inside the wheel as `thesis_ci/spec`; editable installs read `spec/` directly.
|
|
383
|
+
- Composite GitHub Action (`action.yml`) and CI workflow (pytest + selftest).
|
|
384
|
+
|
|
385
|
+
### Notes
|
|
386
|
+
|
|
387
|
+
- `C-TEST-METRIC` also warns (does not fail) when a compound rule's sub-rule `metric` is neither registered nor
|
|
388
|
+
defined in the test (`metric`, `metric_def`, `params.metric_defs`, or `<id>.<component>` of one of those).
|
|
389
|
+
- Not yet included: EDGAR listener, settlement, OpenTimestamps verification (planned phases).
|
thesis_ci-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kentian742-creator
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Specification and documentation license
|
|
2
|
+
|
|
3
|
+
Everything in `spec/` (`SPEC.md`, `schemas/*.schema.json`, `checks.yml`, `metrics.yml`,
|
|
4
|
+
`templates/`) and the documentation of this repository (`README.md`, `CHANGELOG.md` and other
|
|
5
|
+
Markdown documents, including their Chinese versions in `zh-CN/`) is licensed under the
|
|
6
|
+
[Creative Commons Attribution 4.0 International License (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/).
|
|
7
|
+
|
|
8
|
+
You may copy, redistribute and adapt it, including commercially, provided you give credit
|
|
9
|
+
("thesis-ci format specification, kentian742-creator, CC BY 4.0"), link to the license, and
|
|
10
|
+
indicate whether you made changes.
|
|
11
|
+
|
|
12
|
+
The code (`src/`, `tests/`, `action.yml`, `.github/`) is licensed under the MIT License, see
|
|
13
|
+
[LICENSE](LICENSE). The copy of the specification bundled in the wheel as `thesis_ci/spec/` is the
|
|
14
|
+
same specification and is likewise CC BY 4.0.
|