Skip to content

feat(valuation): Issue #67 — flip USE_SECTOR_COE True (Damodaran 11-sector Ke)#294

Merged
dackclup merged 1 commit into
mainfrom
claude/issue-67-sector-coe-flip
May 28, 2026
Merged

feat(valuation): Issue #67 — flip USE_SECTOR_COE True (Damodaran 11-sector Ke)#294
dackclup merged 1 commit into
mainfrom
claude/issue-67-sector-coe-flip

Conversation

@dackclup
Copy link
Copy Markdown
Owner

Summary

Closes Issue #67 — flips USE_SECTOR_COE from FalseTrue per methodology-scientist Mode B verdict 2026-05-28 + cron #69 empirical confirmation. Consumes the data-collection module landed in PR #204 (2026-05-22).

Empirical gate (cron #69 metadata)

Field Value
value_trap_risk_count_without_sector_coe (flat 10% Ke) 132
value_trap_risk_count_with_sector_coe (per-GICS Ke 6-12%) 109
Delta −23 tickers, −17.4% reduction
Target band (PR #204) [80, 110]

The 38%-vs-17% spread vs original projection is explained by baseline drift — PR #166 (Issue #11 RIM equity-denominator fix) already removed ~44 false positives from the pre-PR-#204 ~176 baseline. The absolute landing point (109) inside the target band is the substantive gate condition; methodology-scientist verdict confirms this clears the gate.

Methodology-scientist verdict — APPROVED (LITERATURE-ANCHORED)

Per Damodaran 2019 Investment Valuation 3rd ed. Ch. 8.4 §"Industry Beta" + NYU January 2025 betas dataset (11 GICS sectors with Ke range 6%-12%):

Lower-Ke sectors (Utilities/REIT/Staples) gain leniency; higher-Ke sectors (Tech/Energy) gain stringency; net is negative because S&P 500 has more market-cap exposure to defensives than the flat 10% baseline assumed.

Per-sector shape verification recommended but NOT a blocker — Q3 2026-08-19 cohort audit (~12 weekly crons of post-flip data) is the natural shape-verification gate per the existing methodology-scientist review cadence.

Changes (5 files)

File Change
compute/config.py:86 USE_SECTOR_COE: bool = False → True + docstring rewritten (methodology verdict + cron #69 numbers + load-bearing-default semantics)
compute/scoring/cost_of_equity.py:73-79 Module docstring updated to post-flip state
tests/test_scoring/test_value_trap_risk_sector_coe.py:134-156 Test renamed + assertion inverted (not config.USE_SECTOR_COEconfig.USE_SECTOR_COE); would BREAK on flip otherwise
tests/test_config.py New test_use_sector_coe_flipped_true pin per methodology-scientist Q5b (Phase 2.4/2.5 convention)
PHASE_STATUS_INFLIGHT.md Side-file lockstep entry per PR #237 convention

Impact (first methodology-affecting flip post-v1.4.0)

Verification

  • ruff check . — PASS
  • python -m compute.output.schema_check — PASS (no schema change in this PR)
  • python -m pytest tests/test_config.py tests/test_scoring/test_value_trap_risk_sector_coe.py tests/test_scoring/test_cost_of_equity.py tests/test_valuation/ -q -m "not network"256 passed
  • python -m pytest tests/ -q -m "not network" --ignore=tests/test_validation1207 passed, 7 skipped (optional deps), 0 failed
  • methodology-scientist Mode B verdict — APPROVED (LITERATURE-ANCHORED across all 11 GICS sectors)

What's NOT in this PR

Test plan

https://claude.ai/code/session_01AGU8d6pm4u2fQQ5cebg9qa


Generated by Claude Code

…ector Ke)

Closes Issue #67 — flips `USE_SECTOR_COE` False → True per methodology-
scientist Mode B verdict 2026-05-28 + cron #69 empirical confirmation.
Consumes the data-collection module landed in PR #204 (2026-05-22).

Empirical gate satisfied (cron #69 metadata):
- value_trap_risk_count_without_sector_coe: 132 (flat 10% Ke baseline)
- value_trap_risk_count_with_sector_coe:    109 (per-GICS Ke 6-12%)
- Delta: -23 tickers, -17.4% reduction
- Absolute landing point (109) inside original PR #204 target band [80, 110]
- 38%-vs-17% spread vs original projection explained by baseline drift
  (PR #166 Issue #11 RIM equity-denominator fix already removed ~44 FP
  from the pre-PR-#204 ~176 baseline; proportional difference is baseline
  drift, not signal failure)

Methodology-scientist verdict (Damodaran 2019 Ch. 8.4 §"Industry Beta"
+ NYU January 2025 betas dataset): APPROVED. Lower-Ke sectors
(Utilities/REIT/Staples) gain leniency; higher-Ke sectors (Tech/Energy)
gain stringency; net is negative because S&P 500 has more market-cap
exposure to defensives than the flat 10% baseline assumed.

Changes (5 files):

- compute/config.py:86 — USE_SECTOR_COE flipped True. Docstring rewritten
  to cite methodology verdict + cron #69 numbers + load-bearing-default
  semantics (flipping back requires separate methodology-scientist verdict).
- compute/scoring/cost_of_equity.py:73-79 — module docstring updated to
  reflect post-flip state.
- tests/test_scoring/test_value_trap_risk_sector_coe.py:134-156 —
  test renamed (`_flat_coe_path_unchanged_...` → `_use_sector_coe_default_
  post_issue_67_flip`); assertion inverted from `not config.USE_SECTOR_COE`
  → `config.USE_SECTOR_COE`. Would BREAK on flip otherwise.
- tests/test_config.py — new `test_use_sector_coe_flipped_true` pin
  added per methodology-scientist Q5b recommendation (Phase 2.4/2.5
  convention: pin every config-value flip in tests/test_config.py).

Impact (first methodology-affecting flip post-v1.4.0):
- value_trap_risk universe count: 132 → 109 (per cron #69 dual-counter)
- 23 newly-not-flagged tickers regain RIM as a contributing valuation method
- Composite ranks shift for the cyclical-vs-defensive cohort
  (magnitude bounded by per-pillar weight + median-of-6 aggregation)
- Rule 16 + Top-5 rotation mechanics UNCHANGED (only Ke parameter shift)
- No schema change (Metadata dual-counter fields already shipped PR #204)
- No new defense flag (defense layer count unchanged at 33 declared)

Verification:
- `ruff check .` — PASS
- `python -m pytest tests/test_config.py tests/test_scoring/test_value_trap_risk_sector_coe.py tests/test_scoring/test_cost_of_equity.py tests/test_valuation/ -q -m "not network"` — 256 passed
- `python -m pytest tests/ -q -m "not network" --ignore=tests/test_validation` — 1207 passed
- methodology-scientist Mode B verdict — APPROVED (LITERATURE-ANCHORED)

Deferred follow-ups (NOT in this PR):
- Per-sector delta instrumentation (Metadata.value_trap_risk_delta_by_sector)
  — separate PR; universe-wide count sufficient for THIS flip per the
  gate contract
- Q3 2026-08-19 cohort audit — natural review point for per-sector shape
  verification (~12 weekly crons of post-flip data by then; already in
  the issue #130 pre-prep checklist)
@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
quantrank Ready Ready Preview, Comment May 28, 2026 5:30am

@github-actions
Copy link
Copy Markdown
Contributor

Pre-merge production simulation

Field Value
Duration 383s
Universe size 502
Schema version 0.10.8-phase4.6
Compute commit e5b575b65a321057b9da1ffc1cba1d9dad3df1ef
PR-branch output pr-294-compute-output (14-day retention)

Diff vs main

Field Main PR Δ
Universe size 502 502 +0
Schema version 0.10.7-phase4.6 0.10.8-phase4.6 ⚠️ bumped

Main baseline: 2026-05-28T03:14:33Z (0.1 days old)

Top-10 movers (sorted by |Δcomposite_score|)

Ticker PR rank main rank Δrank PR score main score Δscore
HD 226 271 +45 51.75 50.18 +1.57
LVS 122 108 -14 56.79 57.70 -0.91
SNPS 493 495 +2 31.80 31.55 +0.25
DDOG 426 423 -3 40.51 40.75 -0.24
MCHP 492 491 -1 32.21 32.41 -0.20
PCG 285 289 +4 49.38 49.24 +0.14
ROST 222 218 -4 51.99 52.13 -0.14
NKE 442 438 -4 39.59 39.73 -0.14
PNW 224 223 -1 51.81 51.93 -0.12
LITE 496 497 +1 30.89 30.79 +0.10

@dackclup dackclup marked this pull request as ready for review May 28, 2026 05:39
@dackclup dackclup merged commit 0ddb6b8 into main May 28, 2026
5 checks passed
@dackclup dackclup deleted the claude/issue-67-sector-coe-flip branch May 28, 2026 05:39
dackclup added a commit that referenced this pull request May 28, 2026
…+ bump pointers (#295)

End-of-day Track-A2 housekeeping. After 6 PRs landed on main today
(#286 / #290 / #291 / #292 / #293 / #294), the CLAUDE.md / PHASE_STATUS.md
/ SKILL.md pointers drifted again — schema bumped via PR #292
(0.10.7 → 0.10.8-phase4.6); USE_SECTOR_COE flipped via PR #294. This
PR closes the doc-drift loop so session N+1 reads correct state.

Changes (4 files, doc-only):

- CLAUDE.md §Phase status — schema `0.10.7-phase4.6 → 0.10.8-phase4.6`;
  defense layer narrative notes `USE_SECTOR_COE = True` post-#294;
  new "Post-tag production patches" subsection citing PRs #292 / #293
  / #294. "Recently merged" list prepended with 6 same-day entries;
  legacy "Earlier (PR #264 → PR #285)" subsection relabeled.

- PHASE_STATUS.md §Current state — schema mirror; new "Post-tag
  production patches" row; Production-run pointer `559c5269 →
  0ad1d57` (cron #69 chore-commit). "Recently merged" prepended.

- SKILL.md schema-version table — new top row for `0.10.8-phase4.6`
  (PR #292 GOOG/GOOGL XBRL fix + Rule 18 disambiguator).

- PHASE_STATUS_INFLIGHT.md — 6 stale `(in flight, 2026-05-28)`
  markers drained to `(merged 2026-05-28, <SHA>)` (PRs #286 / #290 /
  #291 / #292 / #293 / #294). Bodies preserved.

Doc-only PR — `ruff` / `schema_check` pass; no compute / schema /
scoring / valuation / frontend / Python / TS change. CLAUDE.md
substance touched (pointer block + Recently merged refresh).
AGENTS.md substance unchanged per the delegation-pattern (PR #291
already bumped this morning).

Co-authored-by: Claude <noreply@anthropic.com>
dackclup pushed a commit that referenced this pull request May 28, 2026
…main.md

End-of-day Track-A3 follow-up to the post-session-housekeeping commit
(0949a3c). Adds a single-file CONTEXT.md entry point at the repo
root so external tools / fresh agents / vendored skills that expect
the upstream mattpocock single-CONTEXT.md convention have one bridge
file to read first. Reconciles docs/agents/domain.md which previously
declared "QuantRank has NO CONTEXT.md" (now stale).

Changes (3 files, doc-only — additive):

- CONTEXT.md (NEW, ~245 lines) — bridge / live-snapshot pointer.
  11 sections: Design note (explicit "not source of truth" framing)
  · What is QuantRank · Live snapshot (schema 0.10.8-phase4.6 ·
  v1.4.0-phase4.6 tag · 33 declared flags · USE_SECTOR_COE=True
  post-#294 · cron #69 green) · Multi-file mapping (12-row file→topic
  + 6-row topic→file tables mirroring docs/agents/domain.md) · 8 Key
  invariants (Rule 16 / schema triple / Rule 18 / lockstep / rebase
  / mobile-only / formula sacred / orchestrator role) · Stack ·
  Layout · Quick-start commands · 9 Standing constraints · 7
  Vocabulary discipline terms · Roadmap pointer (Stage 0 → Stage 6
  / v2.0) · Companion files index.

- docs/agents/domain.md §"QuantRank has NO CONTEXT.md" — section
  header + opening paragraph rewritten to "CONTEXT.md is a pointer,
  not the source of truth" with the new framing (the four-file
  analog remains canonical; CONTEXT.md is a bridge). Topic-driven
  lookup table + "update CONTEXT.md inline when a term resolves" +
  "Use the project vocabulary" sections unchanged — their semantics
  still apply (updates land in the appropriate deep file, not in
  CONTEXT.md which is pointer-only).

- PHASE_STATUS_INFLIGHT.md — appended in-flight entry per §Conventions
  lockstep (PR #237 convention).

Design discipline:

- CONTEXT.md MUST NOT duplicate content from the four canonical files
  (CLAUDE.md + SKILL.md + WORKFLOW.md + docs/METHODOLOGY.md) — when
  content drifts, the four files win and CONTEXT.md updates to point
  at the new location.
- "Live snapshot" block IS expected to drift; the next end-of-session
  housekeeping commit refreshes it the same way it refreshes
  CLAUDE.md §Phase status.

Doc-only PR — ruff / schema_check N/A; no compute / schema / scoring
/ valuation / frontend / Python / TS change. CLAUDE.md substance
untouched this PR (CONTEXT.md is a NEW top-level file that pointers
TO CLAUDE.md, not a substance change WITHIN it).
dackclup added a commit that referenced this pull request May 28, 2026
…main.md (#296)

End-of-day Track-A3 follow-up to the post-session-housekeeping commit
(0949a3c). Adds a single-file CONTEXT.md entry point at the repo
root so external tools / fresh agents / vendored skills that expect
the upstream mattpocock single-CONTEXT.md convention have one bridge
file to read first. Reconciles docs/agents/domain.md which previously
declared "QuantRank has NO CONTEXT.md" (now stale).

Changes (3 files, doc-only — additive):

- CONTEXT.md (NEW, ~245 lines) — bridge / live-snapshot pointer.
  11 sections: Design note (explicit "not source of truth" framing)
  · What is QuantRank · Live snapshot (schema 0.10.8-phase4.6 ·
  v1.4.0-phase4.6 tag · 33 declared flags · USE_SECTOR_COE=True
  post-#294 · cron #69 green) · Multi-file mapping (12-row file→topic
  + 6-row topic→file tables mirroring docs/agents/domain.md) · 8 Key
  invariants (Rule 16 / schema triple / Rule 18 / lockstep / rebase
  / mobile-only / formula sacred / orchestrator role) · Stack ·
  Layout · Quick-start commands · 9 Standing constraints · 7
  Vocabulary discipline terms · Roadmap pointer (Stage 0 → Stage 6
  / v2.0) · Companion files index.

- docs/agents/domain.md §"QuantRank has NO CONTEXT.md" — section
  header + opening paragraph rewritten to "CONTEXT.md is a pointer,
  not the source of truth" with the new framing (the four-file
  analog remains canonical; CONTEXT.md is a bridge). Topic-driven
  lookup table + "update CONTEXT.md inline when a term resolves" +
  "Use the project vocabulary" sections unchanged — their semantics
  still apply (updates land in the appropriate deep file, not in
  CONTEXT.md which is pointer-only).

- PHASE_STATUS_INFLIGHT.md — appended in-flight entry per §Conventions
  lockstep (PR #237 convention).

Design discipline:

- CONTEXT.md MUST NOT duplicate content from the four canonical files
  (CLAUDE.md + SKILL.md + WORKFLOW.md + docs/METHODOLOGY.md) — when
  content drifts, the four files win and CONTEXT.md updates to point
  at the new location.
- "Live snapshot" block IS expected to drift; the next end-of-session
  housekeeping commit refreshes it the same way it refreshes
  CLAUDE.md §Phase status.

Doc-only PR — ruff / schema_check N/A; no compute / schema / scoring
/ valuation / frontend / Python / TS change. CLAUDE.md substance
untouched this PR (CONTEXT.md is a NEW top-level file that pointers
TO CLAUDE.md, not a substance change WITHIN it).

Co-authored-by: Claude <noreply@anthropic.com>
dackclup added a commit that referenced this pull request May 28, 2026
…rkers + bump pointers (#299)

Closes today's 10-PR cycle (#286 / #290 / #291 / #292 / #293 / #294 /
#295 / #296 / #297 / #298). Mirror of PR #286 (post-v1.4.0 cycle
drain) for the post-cron-#71 cycle.

Three stale `(in flight, 2026-05-28)` markers in
PHASE_STATUS_INFLIGHT.md drained to `(merged 2026-05-28, <SHA>)`:

  - PR #295 (`2d2ec83e`) — Post-session housekeeping drain 6 INFLIGHT
    + bump pointers
  - PR #297 (`ecb60e64`) — Issue #287 PR A: durable timeout + cache
    canary + per-loop wall-clock Metadata (schema 0.10.8 → 0.10.9-phase4.6)
  - PR #298 (`030675e9`) — Issue #288 follow-up: cache-key bump v4 → v5

Bodies preserved (historical record).

CLAUDE.md §Phase status — drained the "(In flight this PR — cache-v5)"
qualifier (PR #298 merged) + added post-PR-#298 confirmation note +
cron Run #71 production-verified pointer.

AGENTS.md open-issues list — #288 status flipped "(fix in flight this
PR)" → "(closed by PR #298 cache-v5 bump)" + clarified the silent-
failure root-cause + Run #72 verification gate.

Why this PR exists: without end-of-day drain, session N+1 reading
CLAUDE.md / PHASE_STATUS_INFLIGHT.md would see 3 PRs still marked
"in flight" despite them merging hours earlier — the same friction
pattern PR #286 closed for the post-v1.4.0 cycle. Three same-day
drains in one PR keeps the side-file disciplined.

Scope (3 files, doc-only):

  - PHASE_STATUS_INFLIGHT.md — 3 header substitutions + this PR's
    own in-flight entry appended per PR #237 side-file convention
  - CLAUDE.md §Phase status pointer refresh
  - AGENTS.md open-issues list #288 status update

Hard constraints honored:

  - No code / scoring / schema / valuation / Rule 16 / Top-5
    invariant touched
  - No new defense flag · No new dep · No new env-var
  - Doc-only diff (Markdown only)
  - Schema version UNCHANGED at 0.10.9-phase4.6 (no Pydantic / TS /
    snapshot change)

PHASE_STATUS_INFLIGHT.md side-file satisfies §Conventions "ship with
every PR" lockstep per PR #237 convention. Same drain template as
PR #286 (post-v1.4.0 cycle).

https://claude.ai/code/session_01AGU8d6pm4u2fQQ5cebg9qa

Co-authored-by: Claude <noreply@anthropic.com>
dackclup added a commit that referenced this pull request May 28, 2026
…ULD-FIX cross-doc drifts (#301)

Comprehensive .md housekeeping closing today's 11-PR session day.
Output of docs-reviewer (sonnet) full Tier 1 + Tier 2 audit on main
(post-PR-#299) — verdict NEEDS-CROSS-REF-FIX with 14 prioritized
findings; this PR applies all 8 MUST-FIX + 6 SHOULD-FIX. 3 NICE-TO-FIX
deferred to follow-up.

Scope (7 files, doc-only):

  - SKILL.md schema-version history table (line 240) — prepend 2 new
    rows: 0.10.9-phase4.6 (PR #297, 4 *_wall_clock_seconds fields +
    195m timeout + cache canary, empirically validated cron Run #71)
    + 0.10.10-phase4.6 (PR #300 in flight — Issue #67 follow-up per-
    sector delta). Closes the canonical-history gap where PR #297 +
    PR #300 were absent.

  - PHASE_STATUS.md §Current state — schema row 0.10.8 → 0.10.9 +
    PR #300 in-flight note; Post-tag production patches row extended
    with PR #295/#296/#297/#298/#299 SHAs + one-liners; Production
    run pointer 0ad1d57 cron #69368dccd cron Run #71 with the
    PR #297 wall-clock empirical numbers + Issue #288 cache-replay
    smoking gun (multi_class_per_class_attempt_count=0 +
    fundamentals_latency_p50_seconds=0.0). Recently merged block
    extended 6 → 11 PRs. Issue closure status updated. Next
    deliverables refreshed: Issue #67 flip removed (PR #294 already
    executed); item 2 now = Issue #287 PR B FORM4 revert; PR #300
    per-sector delta added as item 3. Open issues list refreshed
    (#288 + #289 marked closed; #287 PR A vs PR B split).

  - CLAUDE.md §Phase status Recently merged block — extended 6 → 11
    PRs with full SHA + one-liner per PR. New "In flight" sub-section
    added for PR #300.

  - AGENTS.md §Phase + version state — Production-verified run
    cron #69 (233117a, 13m 16s) → cron Run #71 (368dccd, 14m 32s,
    2026-05-28 08:44 UTC, schema 0.10.7 → 0.10.9-phase4.6); 4 new
    wall-clock field values cited; Issue #288 cache-replay smoking
    gun captured; closed-issue note for #288 + #289 + #287 PR A.

  - CONTEXT.md §Live snapshot — schema 0.10.8 → 0.10.9 + PR #300
    in-flight note; new "Post-tag patches" row listing PRs #292-#299
    + PR #300 in flight; cron status cron #69 2026-05-27 → Run #71
    2026-05-28; Sector-CoE row updated with empirical 132 → 109;
    §Roadmap Stage 0 description refreshed.

  - WORKFLOW.md §Agentic 6-Phase Cadence session-start protocol —
    inline schema 0.10.7-phase4.6 replaced with current 0.10.9-phase4.6
    + pointer guidance to PHASE_STATUS.md §Current state as the
    canonical bump-per-schema-PR target. Closes the recurring inline-
    schema drift pattern.

  - PHASE_STATUS_INFLIGHT.md — this PR's in-flight entry appended per
    PR #237 side-file convention.

docs-reviewer lockstep cross-check after this PR:

  - SCHEMA_VERSION: ALIGNED across all 6 canonical docs at
    0.10.9-phase4.6 with PR #300 in-flight note where applicable
  - Defense layer 33 declared: ALIGNED (was already)
  - USE_SECTOR_COE = True post-PR #294: ALIGNED (was stale in
    AGENTS.md issue #67 framing + PHASE_STATUS.md Next deliverables;
    both fixed)
  - Subagent count 18: ALIGNED (was already)
  - Skill count 45: ALIGNED (was already)
  - Latest cron Run #71 368dccd: ALIGNED (was stale in AGENTS.md +
    PHASE_STATUS.md + CONTEXT.md; all fixed)
  - Issue #288 + #289 closure status: ALIGNED (was stale as open in
    AGENTS.md + PHASE_STATUS.md; both fixed)

3 NICE-TO-FIX deferred:

  - README.md Honest Limitations does not reference Phase 4.6 honest
    re-validation harness (PR #283). Coverage gap, not break.
  - WORKFLOW.md Phase 4.5 row cites v1.2.0; technically closed at
    v1.3.0-phase4.5e. Historical-context only.
  - METHODOLOGY.md USE_SECTOR_COE framing needs verification before
    edit.

Hard constraints honored:

  - No code / scoring / schema / valuation / Rule 16 / Top-5
    invariant touched
  - No new defense flag · No new dep · No new env-var
  - Markdown-only diff (no JSON / YAML / Python / TS change)
  - Schema version UNCHANGED on main at 0.10.9-phase4.6 (PR #300 will
    bump 0.10.10 on its merge)
  - AGENTS.md substance lockstep with CLAUDE.md per the established
    delegation pattern

Verification:

  - ruff check .                          PASS (no Python touched)
  - python -m compute.output.schema_check PASS (no schema touched)
  - pytest tests/ -m "not network"        N/A (no test surface)
  - Cross-reference grep — all 7 anchor strings consistent across
    all 6 docs after fix

https://claude.ai/code/session_01AGU8d6pm4u2fQQ5cebg9qa

Co-authored-by: Claude <noreply@anthropic.com>
dackclup pushed a commit that referenced this pull request May 28, 2026
… instrumentation

Methodology-scientist Mode B Q2 follow-up deferred from PR #294 (sector-
CoE flip, 2026-05-28 05:39 UTC). Adds
`Metadata.value_trap_risk_delta_by_sector: dict[str, int] | None` so
Q3 2026-08-19 quarterly cohort audit has visible per-sector shape
evidence — not just the aggregate `value_trap_risk_count_*_sector_coe`
scalars that landed in PR #204.

Schema PATCH bump 0.10.9 → 0.10.10-phase4.6 (additive Metadata-only).

Methodology context (Damodaran 2019 Ch. 8.4 §"Industry Beta"):

  After `USE_SECTOR_COE = True` per-sector Ke replaces the flat 10%
  baseline at SECTOR_COST_OF_EQUITY (11 GICS sectors, Ke 6%-12%).
  Directional predictions:

  - Lower-Ke sectors (Utilities ~6-7% / Real Estate ~7-8% / Consumer
    Staples ~7-8%): ROE ≥ Ke threshold relaxed → fewer RIM-skipped →
    POSITIVE delta (sector DROPPED flags)
  - Higher-Ke sectors (Information Technology ~11-12% / Energy
    ~10-12%): ROE ≥ Ke tightened → more RIM-skipped → NEGATIVE delta
  - Neutral sectors (6 GICS sectors at ~9-11%): small delta near zero

Cron #69 + Run #71 universe-wide already confirmed the aggregate:
132 → 109 (−23 tickers, −17.4%). This PR breaks the −23 down by sector.

Scope (10 files, additive only):

  - compute/output/schemas.py — new value_trap_risk_delta_by_sector
    field with full docstring (methodology-scientist verdict +
    Damodaran 2019 anchor + direction semantics)
  - frontend/lib/types.ts — mirror TS field as Record<string, number> | null
  - frontend/lib/schema-snapshot.json — regenerated via --update-snapshot
  - compute/config.py — SCHEMA_VERSION = "0.10.10-phase4.6"
  - compute/main.py — 3 surgical edits mirroring existing scalar
    dual-counter pattern (init two dict[str, int] counters / per-sector
    increment co-located with the existing scalar bump in both branches
    / delta computation in Metadata constructor)
  - tests/test_config.py — schema version pin bump + docstring rewrite
  - tests/test_output/test_value_trap_delta_by_sector_schema.py (NEW) —
    2 active GREEN schema-contract tests (mirror test_wall_clock_schema.py
    pattern from PR #297)
  - CLAUDE.md — §Phase status pointer block refresh
  - AGENTS.md — open-issues #67 status: flip landed + per-sector
    follow-up in flight this PR
  - PHASE_STATUS_INFLIGHT.md — full in-flight entry per PR #237
    side-file convention

Implementation note:

  Per-sector dict construction uses
  `sorted(set(without) | set(with))` for stable key ordering;
  `.get(sec, 0)` fallback handles sectors appearing in only one path;
  `{} or None` falls back to None when both dicts are empty (test-mode
  universe). Co-located with the existing scalar bump in both
  `_rim_flat` (flat-Ke) and `_rim_sector` (sector-Ke) branches at the
  same `value_trap_risk_roe_below_cost_of_equity` reason guard — scalar
  and dict always stay in lockstep.

Verification ladder:

  - ruff check .                              PASS
  - python -m compute.output.schema_check     PASS (triple in sync 0.10.10)
  - pytest tests/test_config.py -v            11/11 PASS (pin held)
  - python -m pytest tests/test_output/       2/2 NEW PASS
  - Full offline suite via test-engineer      1367 → 1369 (+2 NEW)

Pre-push 3-reviewer gate:

  - schema-sentinel (sonnet)        PASS (52 fields, triple aligned,
                                    PATCH bump correct, snapshot
                                    alphabetical ordering held)
  - test-engineer (sonnet)          GREEN (2/2 new tests pass,
                                    1367 → 1369, 0 regressions,
                                    0 skipped stubs)
  - quantrank-reviewer (opus)       READY-TO-PUSH (0 FAIL, 4 WARN
                                    all pre-existing PR-#297-era
                                    drift, defer to next housekeeping
                                    PR — incl. SKILL.md/PHASE_STATUS.md
                                    schema-table tops still on 0.10.8)

Empirical validation gate (post-merge, next cron Run #72):

  - metadata.value_trap_risk_delta_by_sector populates as non-null dict
  - Damodaran shape directionally correct: Util/Real Estate/Staples
    POSITIVE, Information Technology/Energy NEGATIVE
  - sum(delta.values()) == without_sector_coe_count - with_sector_coe_count
    (= 23 per Run #71 universe-wide; matches within rounding)

Note: per-sector accumulation runs in the Step 8 per-ticker loop,
INDEPENDENT of cache-v5 cache busting (PR #298). Field populates on
next cron regardless of warm/cold fetch path.

Hard constraints honored:

  - No new defense flag · No scoring formula change · No Rule 16 /
    Top-5 violation
  - Additive-only schema change (PATCH bump)
  - Field nullable per Rule 18 graceful-degradation
  - Phase 4.5e PR 5 (cluster weight promotion) gate-data UNCHANGED —
    independent track

Methodology decision: methodology-scientist verdict NOT re-requested —
this is the EXACT field shape Mode B Q2 verdict from PR #294 explicitly
authorized. Future re-trigger only if post-merge cron shows sector
breakdown contradicting Damodaran prediction OR Q3 2026-08-19 audit
reads ≥ 6 crons of data and per-sector decay pattern needs interpretation.

https://claude.ai/code/session_01AGU8d6pm4u2fQQ5cebg9qa
dackclup added a commit that referenced this pull request May 28, 2026
…ta instrumentation (#300)

Methodology-scientist Mode B Q2 follow-up deferred from PR #294 (sector-
CoE flip, 2026-05-28 05:39 UTC). Adds
`Metadata.value_trap_risk_delta_by_sector: dict[str, int] | None` so
Q3 2026-08-19 quarterly cohort audit has visible per-sector shape
evidence — not just the aggregate `value_trap_risk_count_*_sector_coe`
scalars that landed in PR #204.

Schema PATCH bump 0.10.9 → 0.10.10-phase4.6 (additive Metadata-only).

Methodology context (Damodaran 2019 Ch. 8.4 §"Industry Beta"):

  After `USE_SECTOR_COE = True` per-sector Ke replaces the flat 10%
  baseline at SECTOR_COST_OF_EQUITY (11 GICS sectors, Ke 6%-12%).
  Directional predictions:

  - Lower-Ke sectors (Utilities ~6-7% / Real Estate ~7-8% / Consumer
    Staples ~7-8%): ROE ≥ Ke threshold relaxed → fewer RIM-skipped →
    POSITIVE delta (sector DROPPED flags)
  - Higher-Ke sectors (Information Technology ~11-12% / Energy
    ~10-12%): ROE ≥ Ke tightened → more RIM-skipped → NEGATIVE delta
  - Neutral sectors (6 GICS sectors at ~9-11%): small delta near zero

Cron #69 + Run #71 universe-wide already confirmed the aggregate:
132 → 109 (−23 tickers, −17.4%). This PR breaks the −23 down by sector.

Scope (10 files, additive only):

  - compute/output/schemas.py — new value_trap_risk_delta_by_sector
    field with full docstring (methodology-scientist verdict +
    Damodaran 2019 anchor + direction semantics)
  - frontend/lib/types.ts — mirror TS field as Record<string, number> | null
  - frontend/lib/schema-snapshot.json — regenerated via --update-snapshot
  - compute/config.py — SCHEMA_VERSION = "0.10.10-phase4.6"
  - compute/main.py — 3 surgical edits mirroring existing scalar
    dual-counter pattern (init two dict[str, int] counters / per-sector
    increment co-located with the existing scalar bump in both branches
    / delta computation in Metadata constructor)
  - tests/test_config.py — schema version pin bump + docstring rewrite
  - tests/test_output/test_value_trap_delta_by_sector_schema.py (NEW) —
    2 active GREEN schema-contract tests (mirror test_wall_clock_schema.py
    pattern from PR #297)
  - CLAUDE.md — §Phase status pointer block refresh
  - AGENTS.md — open-issues #67 status: flip landed + per-sector
    follow-up in flight this PR
  - PHASE_STATUS_INFLIGHT.md — full in-flight entry per PR #237
    side-file convention

Implementation note:

  Per-sector dict construction uses
  `sorted(set(without) | set(with))` for stable key ordering;
  `.get(sec, 0)` fallback handles sectors appearing in only one path;
  `{} or None` falls back to None when both dicts are empty (test-mode
  universe). Co-located with the existing scalar bump in both
  `_rim_flat` (flat-Ke) and `_rim_sector` (sector-Ke) branches at the
  same `value_trap_risk_roe_below_cost_of_equity` reason guard — scalar
  and dict always stay in lockstep.

Verification ladder:

  - ruff check .                              PASS
  - python -m compute.output.schema_check     PASS (triple in sync 0.10.10)
  - pytest tests/test_config.py -v            11/11 PASS (pin held)
  - python -m pytest tests/test_output/       2/2 NEW PASS
  - Full offline suite via test-engineer      1367 → 1369 (+2 NEW)

Pre-push 3-reviewer gate:

  - schema-sentinel (sonnet)        PASS (52 fields, triple aligned,
                                    PATCH bump correct, snapshot
                                    alphabetical ordering held)
  - test-engineer (sonnet)          GREEN (2/2 new tests pass,
                                    1367 → 1369, 0 regressions,
                                    0 skipped stubs)
  - quantrank-reviewer (opus)       READY-TO-PUSH (0 FAIL, 4 WARN
                                    all pre-existing PR-#297-era
                                    drift, defer to next housekeeping
                                    PR — incl. SKILL.md/PHASE_STATUS.md
                                    schema-table tops still on 0.10.8)

Empirical validation gate (post-merge, next cron Run #72):

  - metadata.value_trap_risk_delta_by_sector populates as non-null dict
  - Damodaran shape directionally correct: Util/Real Estate/Staples
    POSITIVE, Information Technology/Energy NEGATIVE
  - sum(delta.values()) == without_sector_coe_count - with_sector_coe_count
    (= 23 per Run #71 universe-wide; matches within rounding)

Note: per-sector accumulation runs in the Step 8 per-ticker loop,
INDEPENDENT of cache-v5 cache busting (PR #298). Field populates on
next cron regardless of warm/cold fetch path.

Hard constraints honored:

  - No new defense flag · No scoring formula change · No Rule 16 /
    Top-5 violation
  - Additive-only schema change (PATCH bump)
  - Field nullable per Rule 18 graceful-degradation
  - Phase 4.5e PR 5 (cluster weight promotion) gate-data UNCHANGED —
    independent track

Methodology decision: methodology-scientist verdict NOT re-requested —
this is the EXACT field shape Mode B Q2 verdict from PR #294 explicitly
authorized. Future re-trigger only if post-merge cron shows sector
breakdown contradicting Damodaran prediction OR Q3 2026-08-19 audit
reads ≥ 6 crons of data and per-sector decay pattern needs interpretation.

https://claude.ai/code/session_01AGU8d6pm4u2fQQ5cebg9qa

Co-authored-by: Claude <noreply@anthropic.com>
dackclup added a commit that referenced this pull request May 30, 2026
…#326 §Gotchas (#327)

Full docs-reviewer substance pass on CLAUDE.md → 5 MUST-FIX + 4 SHOULD-FIX, all fixed. CLAUDE.md only (+ PHASE_STATUS_INFLIGHT.md lockstep entry); no code/schema/compute/frontend change.

MUST-FIX: §Phase status "In flight" marked PR #312 (tasteful-motion) as "THIS PR" → merged (e602485); "Recently merged" frozen at #310 → drained #311#326 (16 entries, SHAs verified); "Next deliverables" Issue #67 flip listed pending → DONE (PR #294, USE_SECTOR_COE=True); "Section A-H/A-J" → "A-L" (helper is A-L since PR #221).

SHOULD-FIX: §Stack "Phase 3b on this PR" → "(merged)" + edgartools 5.31→5.32; §Gotchas compute/main.py line refs re-anchored (840→879 · 1965-66→2084-85 · 717→728 · 785→805 · 972→1025); +2 §Gotchas for PR #326 invariants (sidebar data-rail↔globals.css pre-paint lockstep; AreaChart re-park debounce ≥300ms).

Confirmed no drift: schema 0.10.11-phase4.6 · skills 46 · agents 19 · hooks 3. docs-reviewer re-check: DOCS-CLEAN (all 16 SHAs match, 5 line refs accurate, 2 gotchas code-backed). Lockstep via PHASE_STATUS_INFLIGHT.md side-file (PR #237).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants