A finding is the conclusion of an investigation — neither a claim nor a piece of evidence. A claim asserts something about the world; evidence bears on one claim; a finding is what someone concluded after synthesising several pieces of evidence, and it usually touches several claims, methodologies and assumptions at once. Before findings were artifacts, that synthesis lived in prose scattered across change rationales and erratum documents, where it could be read but not queried, reviewed as a unit, or routed.
4 adverse relationship(s), 5 total
| Source | Relation | Target | Effect | Directness | Detail |
|---|---|---|---|---|---|
| finding/declared-rules-do-not-execute@1 | invalidates results of | methodology/hrp@1 | blocking | direct | Declares min_history; the rule does not execute. |
| finding/declared-rules-do-not-execute@1 | invalidates results of | methodology/hrp@2 | blocking | direct | Declares min_history and turnover_cap; neither rule executes. |
| finding/declared-rules-do-not-execute@1 | invalidates results of | methodology/hrp@3 | blocking | direct | Declares concentration_cap <= 0.25, which is satisfied only because... |
| finding/declared-rules-do-not-execute@1 | invalidates results of | methodology/xsmom@1 | blocking | direct | Declares min_history and has_full_formation_history; neither executes. |
| finding/declared-rules-do-not-execute@1 | introduced | assumption/declarations-name-th... | none | direct | Generalised the fix into a standing principle: every declaration must... |
A methodology's `rules` and `universe_filters` are declared, merged, and hashed into its identity, but no pipeline step evaluates them. They have zero references in the executor. A reader seeing rules: - id: concentration_cap expr: max_asset_weight <= 0.25 reasonably concludes the constraint is enforced by that rule. It is not. In hrp@3 the constraint happens to hold because `contract.weight_bounds.max` is also 0.25 — the rule is decorative, and the two could disagree silently. This inverts the defect class the project has found repeatedly. The usual pattern is a hidden choice that takes effect without being declared. Here a declared rule appears to take effect and does not, which is arguably worse: declaring it creates the belief that it is checked. Surfaced by adding a second methodology family. xsmom@1 declares `has_full_formation_history` and a `min_history` rule; neither runs, and the history requirement is enforced only incidentally by an ExecutionError inside compute_momentum.
| Evidence | Kind | Stance | Finding |
|---|
| Artifact | Relation | Detail |
|---|---|---|
| assumption/declarations-name-their-realization@1 | introduced | Generalised the fix into a standing principle: every declaration must identify what realizes it, and the realization must be checkable. |
| methodology/hrp@1 | invalidates results of | Declares min_history; the rule does not execute. |
| methodology/hrp@2 | invalidates results of | Declares min_history and turnover_cap; neither rule executes. |
| methodology/hrp@3 | invalidates results of | Declares concentration_cap <= 0.25, which is satisfied only because contract.weight_bounds independently enforces the same number. |
| methodology/xsmom@1 | invalidates results of | Declares min_history and has_full_formation_history; neither executes. |
Resolved by option (c): a rule now names the field that realizes it and the property that field must have. Contracts execute, rules verify, policies interpret — three responsibilities that had blurred together. rules: - id: concentration_cap enforced_by: contract.weight_bounds.max expected: "<= 0.25" `src/methodology/verify.py` resolves each `enforced_by` path against the methodology and checks the assertion. Three drift modes now fail loudly: a contract that moves while the rule does not, a rule naming a field that does not exist, and a rule naming a pipeline stage absent from the pipeline. `universe_filters` were restructured the same way and name the stage that realizes them. An unrealized declaration is a hard blocker in the publication gate, alongside contract violation and failed reproducibility — a methodology asserting what its own fields do not support is making a claim it cannot keep. Rejected: (a) an expression evaluator, which would add a language to the spec and make rules a second execution path competing with the contract; (b) demoting rules to documentation, which would remove them from content identity and weaken versioning.
3 adverse relationship(s), 6 total
| Source | Relation | Target | Effect | Directness | Detail |
|---|---|---|---|---|---|
| finding/hrp-degenerates-to-cash-proxy@1 | refutes | claim/hrp-diversifies-without-c... | blocking | direct | The claim asserts HRP diversifies without explicit constraints. It allocated... |
| finding/hrp-degenerates-to-cash-proxy@1 | qualifies | claim/hrp-outperforms-mvo-out-o... | advisory | direct | The source claim survives, narrowed: it holds for universes of... |
| finding/hrp-degenerates-to-cash-proxy@1 | invalidates results of | methodology/hrp@1 | blocking | direct | Its reported Sharpe of 6.59 was cash return divided by cash volatility. The... |
| finding/hrp-degenerates-to-cash-proxy@1 | invalidates results of | methodology/hrp@2 | blocking | direct | Same degeneracy; the turnover cap does not address concentration. |
| finding/hrp-degenerates-to-cash-proxy@1 | motivated | methodology/hrp@3 | none | direct | Created in response, imposing a 25% per-asset ceiling — the smallest change... |
| finding/hrp-degenerates-to-cash-proxy@1 | introduced | assumption/hard-bounds-beat-sof... | none | direct | Imposing a ceiling surfaced a conflict with the turnover cap, forcing the... |
Hierarchical risk parity degenerates into a cash proxy when the universe contains a near-zero-variance instrument and no per-asset ceiling is imposed. Recursive bisection allocates inverse-variance, so an instrument whose variance approaches zero absorbs an unbounded share of the portfolio. This is a property of the method, not an implementation error, and the source paper does not address it because it demonstrates HRP on assets of comparable risk.
| Evidence | Kind | Stance | Finding |
|---|
| Artifact | Relation | Detail |
|---|---|---|
| assumption/hard-bounds-beat-soft-turnover@1 | introduced | Imposing a ceiling surfaced a conflict with the turnover cap, forcing the precedence rule to be declared rather than resolved in executor code. |
| claim/hrp-diversifies-without-constraints@1 | refutes | The claim asserts HRP diversifies without explicit constraints. It allocated 99.6% to BIL with an effective breadth of 1.01 assets. |
| claim/hrp-outperforms-mvo-out-of-sample@1 | qualifies | The source claim survives, narrowed: it holds for universes of comparable-risk assets, not for any universe. |
| methodology/hrp@1 | invalidates results of | Its reported Sharpe of 6.59 was cash return divided by cash volatility. The figure is arithmetically correct and economically meaningless. |
| methodology/hrp@2 | invalidates results of | Same degeneracy; the turnover cap does not address concentration. |
| methodology/hrp@3 | motivated | Created in response, imposing a 25% per-asset ceiling — the smallest change that makes the allocation describe the methodology rather than describing BIL. |
Published methodology/hrp@3 with a 25% per-asset ceiling; effective breadth 6.37 assets, Sharpe 0.53, no diagnostic flags. Added result-level degeneracy diagnostics (concentration, degenerate volatility, implausible Sharpe, effective breadth) that refuse publication of a flagged result. hrp@1 and hrp@2 remain published and reachable; their results are not deleted, and the publication gate now blocks them rather than the library hiding them.
2 adverse relationship(s), 5 total
| Source | Relation | Target | Effect | Directness | Detail |
|---|---|---|---|---|---|
| finding/joined-panel-inherits-w... | introduced | assumption/nyse-sessions@1 | none | direct | Forced the trading calendar to be declared as a referenced artifact... |
| finding/joined-panel-inherits-w... | introduced | assumption/adjusted-close-is-restated@1 | none | direct | Investigating the panel also established that a declared date range does not... |
| finding/joined-panel-inherits-w... | corrected | erratum/2026-07-30-02 | affecting | direct | Published as a material erratum superseding the figures it affected. |
| finding/joined-panel-inherits-w... | invalidates results of | methodology/hrp@3 | blocking | direct | Annualized 1.3664% -> 2.2892% and volatility 3.1879% -> 4.0939% once weekend... |
| finding/joined-panel-inherits-w... | invalidates results of | erratum/2026-07-30-01 | blocking | direct | The earlier erratum's absolute levels were computed on the contaminated... |
A price panel joined across instruments with different trading calendars inherits the union of their sessions. Forward-filling a five-session instrument onto a seven-day index manufactures zero-return observations that are not market data — deflating realized volatility and mis-scaling any annualization that assumes a session count the data does not have.
| Evidence | Kind | Stance | Finding |
|---|
| Artifact | Relation | Detail |
|---|---|---|
| assumption/adjusted-close-is-restated@1 | introduced | Investigating the panel also established that a declared date range does not identify data — only a content hash does. |
| assumption/nyse-sessions@1 | introduced | Forced the trading calendar to be declared as a referenced artifact (calendar/nyse@1) rather than assumed by the panel's accidental index. |
| erratum/2026-07-30-01 | invalidates results of | The earlier erratum's absolute levels were computed on the contaminated calendar. Its relative conclusion — that the look-ahead was the dominant correction — is unchanged. |
| erratum/2026-07-30-02 | corrected | Published as a material erratum superseding the figures it affected. |
| methodology/hrp@3 | invalidates results of | Annualized 1.3664% -> 2.2892% and volatility 3.1879% -> 4.0939% once weekend padding was removed; a further correction to 2.2094% once NYSE holidays were excluded. |
Trading calendars became versioned artifacts with rule-based holidays (calendar/nyse@1, calendar/crypto@1), each declaring the range it covers and refusing to extrapolate beyond it. Protocols reference a calendar rather than naming a rule inline, and annualization reads the session count from the calendar instead of a hardcoded 252. Erratum 2026-07-30-02 published.
Both findings here came out of ordinary engineering work, and each touched more than one thing at once. The cash-proxy finding refuted one claim, qualified another, invalidated the results of two methodology versions, motivated a third, and forced a constraint-precedence assumption to be declared. Recording that as five separate edits would have lost the fact that they were one conclusion.
Findings are also what an investigation produces and what a review consumes — which is what makes them the natural unit for Discovery to emit and Mission to route, without either needing to infer intent from prose.