Benchmark-sourcing Discipline Package — STAGED (revised, tighter)
This package fixes the recurring index-close transcription error documented in audit-log entries #003, #005, #006, #007, #008, #009, #010 — seven of the last ten entries, the only recurring fault pattern in the autonomous run.
What's broken — and why the obvious fix doesn't work
The portfolio-daily, PM scan, and AM scan tasks each pull benchmark closes (S&P, Dow, Nasdaq, VIX, oil, pipeline-name prices) independently from web sources. Three independent pulls disagree more often than they agree because each pull happens at a slightly different time, against a slightly different aggregator tile, with slightly different staleness. The agent has been writing the disagreement into the artifacts and the optimization task has been catching it the next morning.
The obvious fix is "be more careful" — add discipline rules, tell the agent to cross-verify, tell it to cite timestamps, tell it to sanity-check signs. That was the original version of this proposal. It is the same lever as sources-policy.md, which the audit log shows has not been enough. Discipline rules that ask the agent to "be more careful" do not bind. The error recurs every other day.
The real fix is structural: stop pulling the same data from three places. Pull it once, write it to a canonical file, have the other tasks read it.
The fix
One new framework file, one new artifact file pattern (canonical closes file), three SKILL.md edits. The PM scan becomes the single writer of benchmark closes. Portfolio-daily and AM scan become readers — they no longer pull closes from the web.
The four changes
Change 1 — New framework file 08-Frameworks/benchmark-sourcing-discipline.md
Content:
---
tags:
- framework
- meta
- data-quality
---
# Benchmark-sourcing discipline
US equity index closes (S&P, Dow, Nasdaq, Russell, VIX), commodity closes (WTI, Brent, gold), rate closes (10Y, 2Y, DXY), and pipeline-name closing prices live in **one** place per trading day: `13-Research/Daily-Scans/YYYY-MM-DD-closes.md`.
The PM scan writes the file. The portfolio-daily and the next-morning AM scan read it. No other task pulls benchmark closes from the web independently.
This rule exists because the audit log shows seven recurring failures (entries #003, #005, #006, #007, #008, #009, #010) when multiple tasks pulled the same data independently and disagreed. One source of truth removes the surface where the disagreement lives.
## The closes file
Path: `13-Research/Daily-Scans/YYYY-MM-DD-closes.md`
Written by: `alphasteve-daily-deep-value-scan-pm` as its **first action**, before the Market close context section.
Read by:
- `alphasteve-portfolio-daily` for SPY close, pipeline-name closes, alpha computation
- `alphasteve-daily-deep-value-scan` (next morning) for prior-day closes in the Market context section
Structure:
```
---
date: YYYY-MM-DD
status: settled | partial | not-yet-settled
written_by: alphasteve-daily-deep-value-scan-pm
retrieved_at: HH:MM ET
sources_used: [source-A-name, source-B-name]
---
# Closes — YYYY-MM-DD
| Instrument | Close | Day Δ | Day Δ % | Source A value | Source B value | Status | Notes |
|---|---|---|---|---|---|---|---|
| S&P 500 | 7,563.63 | +43.27 | +0.58% | 7,563.63 (Yahoo) | 7,563.63 (CNBC) | settled | |
| Nasdaq | 26,917.47 | +242.73 | +0.91% | 26,917.47 (Yahoo) | 26,917.47 (CNBC) | settled | |
| ... | | | | | | | |
## Pipeline names (watchlist + portfolio + recent thesis folders)
| Ticker | Close | Day Δ % | Source A | Source B | Status |
|---|---|---|---|---|---|
| SPY | 754.66 | +0.56% | 754.66 (Yahoo) | 754.66 (Google) | settled |
| PLTR | 141.51 | -1.39% | 141.51 (Yahoo) | 141.51 (Google) | settled |
| CAG | 12.68 | +0.79% | 12.68 (Yahoo) | 12.68 (Google) | settled |
| ... | | | | | |
## Discipline used
- Each row cross-verified against two independent sources (within 0.05%)
- Sign of day's change checked against today-vs-yesterday arithmetic in the same source
- Pulled at HH:MM ET, after 4:30 PM cash settlement
- Status `partial` if only one source available; status `not-yet-settled` if pulled before 4:30 PM ET
```
## The two rules for the writer (PM scan)
### 1. Cross-verify against two independent sources
Every row needs two independent values that agree within 0.05%. If they disagree, the row gets status `partial`, both values are logged, and an explanatory note names what conflicted.
Acceptable source pairs:
- Yahoo Finance + CNBC same-day market wrap
- Trading Economics + Investing.com daily close
- WSJ market data + Yahoo Finance
- Official CME settlement + TradingEconomics
Not acceptable as a source: live aggregator widgets without date confirmation, social media reports.
### 2. Direction sanity check before publishing each row
For every instrument, compute `today_close - yesterday_close` explicitly and verify the sign matches the % change shown in the source. If they disagree, the source has stale data — find a different source.
## The two rules for readers (portfolio-daily, AM scan)
### 3. Do not pull benchmark closes from the web independently
If the closes file exists for today, read it. Do not duplicate the work. Do not "double-check" with a fresh web pull — that re-introduces the disagreement the closes file exists to prevent.
### 4. Handle missing or partial data explicitly
If the closes file is missing for the date you need, or a row is marked `partial` or `not-yet-settled`, use the previous trading day's close as the reference value and explicitly note the gap in your output. Do NOT fabricate today's close from a fresh web pull.
## Audit-log entries this closes
Entries #003, #005, #006, #007, #008, #009, #010 — all the same fault, all on the surface where multiple tasks pulled the same data independently. One canonical closes file removes that surface.
## Linked
- [sources-policy](/brain/sources-policy) — citation tiers (this file extends the tier policy to benchmark closes)
- [voice-and-style](/brain/voice-and-style) — sentence-level discipline
- [audit-log](/brain/audit-log) — the failure record this file is designed to close
Change 2 — alphasteve-daily-deep-value-scan-pm SKILL.md edit
Two edits to this file:
2a — Add the framework file to the read-first list as the new item #3, immediately after voice-and-style:
3. `08-Frameworks/benchmark-sourcing-discipline.md` — benchmark-sourcing discipline. The PM scan is the single writer of today's closes file. Read this framework file to understand the writer's two rules (cross-verify against two independent sources; sign sanity check) and the output format for the closes file.
(Renumber subsequent items.)
2b — Add a new mandatory first step at the top of the "Six screens to run" section. Insert this section BEFORE the "Six screens to run" section:
## Step 0 — write the canonical closes file (mandatory, FIRST action)
Before doing any scanning or screen work, write `13-Research/Daily-Scans/YYYY-MM-DD-closes.md` per the structure in [benchmark-sourcing-discipline](/brain/benchmark-sourcing-discipline). This file is the source of truth that the portfolio-daily task (firing in ~30 minutes) and tomorrow's AM scan will read.
Steps:
1. List every instrument to cover: indices (S&P, Dow, Nasdaq, Russell), volatility (VIX), commodities (WTI, Brent, gold), rates (10Y, 2Y, DXY), and every ticker in `11-Watchlist/Watchlist.md`, `12-Portfolio/Portfolio.md`, and the past 5 days of scan files (recent pipeline names).
2. For each instrument, pull the close from two independent sources per the framework. Verify within 0.05%. If agreement: status `settled`. If single-source only: status `partial` with note. If pulled before 4:30 PM ET: status `not-yet-settled`.
3. For each instrument, do the direction sanity check: compute today − yesterday explicitly and confirm the sign of the change matches the source's % change.
4. Write the file. Set frontmatter `status: settled` only if every instrument row is `settled`. Otherwise `partial` (one or more rows partial) or `not-yet-settled` (premature run).
5. Use the closes-file values in the Market close context section of this scan. Do not re-pull.
Change 3 — alphasteve-portfolio-daily SKILL.md edit
Two edits:
3a — Add the framework file to the citation discipline section. After the existing "Citation discipline" paragraph (around line 19-21), insert:
**Benchmark-sourcing discipline (mandatory).** Read `08-Frameworks/benchmark-sourcing-discipline.md`. The portfolio-daily task does NOT pull benchmark closes from the web. It reads today's canonical closes file at `13-Research/Daily-Scans/YYYY-MM-DD-closes.md`, which was written by the PM scan ~30 minutes earlier. If the closes file is missing or has rows marked `partial` or `not-yet-settled`, use the previous trading day's close as the reference and explicitly note the gap. Do NOT do a fresh web pull to "double-check" — that defeats the purpose of the canonical file.
3b — Replace step #1 of Path B entirely. Current text:
1. **Pull current prices** for every position in `12-Portfolio/Portfolio.md` (use WebSearch or financial data sources). Also pull current SPY level.
Replace with:
1. **Read today's closes** from `13-Research/Daily-Scans/YYYY-MM-DD-closes.md`. This file is written by the PM scan ~30 minutes before this task fires. Extract: SPY close, every portfolio-position close, every pipeline-name close needed for the watchlist check. Check the frontmatter `status` field — if `settled`, proceed. If `partial`, note which rows are unsettled and use prior-day closes for those rows. If `not-yet-settled` or the file is missing, log a discipline failure (Backlog item P1: "closes file missing or unsettled at portfolio-daily run time YYYY-MM-DD HH:MM"), use yesterday's closes throughout, and explicitly note in today's portfolio note that current-day closes were not available. Do NOT pull from the web as a fallback.
Change 4 — alphasteve-daily-deep-value-scan (AM) SKILL.md edit
4a — Add the framework file to the read list. In the "Key skill files for this scan" list, immediately after voice-and-style:
- `08-Frameworks/benchmark-sourcing-discipline.md` — benchmark-sourcing discipline. The AM scan reads the prior trading day's closes from the canonical closes file at `13-Research/Daily-Scans/<prior-trading-day>-closes.md`. The AM scan does NOT pull prior-day closes from the web.
4b — Modify the Market context section instructions to read from the closes file. In the "Market context (top of the scan)" section near the bottom of the SKILL.md, add this line at the top of the section's instructions:
**Source for prior-day closes:** read `13-Research/Daily-Scans/<prior-trading-day>-closes.md`. Pull the closes used in this section from that file. Do not re-pull from the web. If the file is missing for the prior trading day, log a Backlog P1 item ("closes file missing for <prior-trading-day>") and use the most recent available closes file with explicit note of the date gap.
Test rubric — how to know it worked
Read the verification counter in _FROZEN-2026-05-28.md and the audit log entries for 5 trading days post-execution:
- Pass: 5 consecutive clean verification runs. No new entries in
audit-log.mdmatching the benchmark-close-transcription pattern. The closes file exists for every trading day withstatus: settled. - Soft pass: 1 new entry in 5 days OR the closes file occasionally lands at
partialstatus (single source agreement only). The pattern is mostly closed but the cross-verification rule fires edge cases. - Fail: ≥2 new entries matching the pattern, OR portfolio-daily / AM scan are caught pulling closes from the web independently. The architectural fix didn't land and we need a harder lever (e.g., scheduled task that aborts if it detects benchmark numbers in its output that weren't sourced from the closes file).
What's different in this revision
The original version of this proposal had four discipline rules that asked the agent to "be more careful" — same lever as sources-policy.md, which the audit log shows hasn't been enough. This revision replaces "be more careful" with "remove the surface where the fault lives." Three tasks pulling the same data independently produced disagreement. One task writing the data and two tasks reading it cannot disagree.
The two writer rules (cross-verify, sign sanity check) and the two reader rules (don't pull independently, handle missing data explicitly) are still discipline rules. But they apply to one task each, in one place each. The audit can check one file instead of three. The fix surface is one location instead of three.
Execution order
- Change 1 first — write the framework file. No behavior change yet.
- Change 2 — wire and modify PM scan. Effect visible at the next PM scan run (the closes file appears in
Daily-Scans/). - Change 3 — wire and modify portfolio-daily. Effect visible at the next portfolio-daily run (reads from the closes file instead of pulling from web).
- Change 4 last — wire and modify AM scan. Effect visible the next morning.
Total execution time: ~7 minutes.
Reversibility
If the architecture misbehaves (PM scan can't reliably get two-source agreement, downstream tasks fail on missing closes file):
- Revert the three SKILL.md edits to their prior versions
- Delete
08-Frameworks/benchmark-sourcing-discipline.md - The closes files created in
Daily-Scans/stay — they are real research artifacts and remain useful as historical records
Total revert time: ~3 minutes.
What this proposal does not change
01-Soul/*— all soul files- Every existing framework file (the new file is an addition only)
- The verdict enum, the bundle convention, the vault folder structure at any level
- All scheduled tasks except the three named (portfolio-daily, PM scan, AM scan)
- The intraday monitor task — it reads only delta events, not closes; no edit needed
- The research-AM and research-PM tasks — they cite market context but it's narrative, not the canonical source; no edit needed (but if they cite a close, the discipline says they should read it from the closes file too — a follow-up edit if violations surface)
Linked
- Backlog — pointer entry updated to reflect this revision
- Rules — Tier 2 procedure followed
- sources-policy — citation tiers (this proposal extends the tier policy)
- voice-and-style — sentence-level discipline (same staging pattern)
- audit-log — the failure record this proposal closes (entries #003, #005, #006, #007, #008, #009, #010)