Skip to content

feat(sl-hunting): v4e knowledge + session-state durability fix - #120

Merged
DoRmAmMu1997 merged 6 commits into
mainfrom
feat/sl-hunting-knowledge-v4e
Aug 11, 2026
Merged

feat(sl-hunting): v4e knowledge + session-state durability fix#120
DoRmAmMu1997 merged 6 commits into
mainfrom
feat/sl-hunting-knowledge-v4e

Conversation

@DoRmAmMu1997

@DoRmAmMu1997 DoRmAmMu1997 commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Distils Intraday Hunter's 11 Aug 2026 live session (_JXirKMmI58) into the SL Hunting agent's knowledge. Unlike every prior addendum, this session is a loss ? which is why it is worth encoding.

The lesson

He named the disqualifying fact himself, twice, before entering:

"Around here neither the BUYER's stop losses are available nor the SELLER's."

"Here not many traders were seated."

He then traded a forecast of who would arrive ? a sharp drop tempts intraday sellers in, so the market should rise to take them out ? and the selling simply continued.

Hunting inventory that exists is the strategy. Predicting inventory that might arrive is a weaker activity wearing the same vocabulary. When nobody is seated on either side, the output is HOLD.

Knowledge changes (all prose)

  • OPENING_DRIVE ? WHICH CROWD THE OPEN RECRUITS DECIDES HOW BIG THE TRAP IS: a gap-down recruits positional sellers who hold overnight; a flat open recruits intraday sellers only, so the same-shaped trap is smaller and perishable. A genuine advance on v4d, independent of the outcome. Plus A FORECAST OF WHO WILL ARRIVE IS NOT EVIDENCE OF WHO IS SEATED and A SHARP FIRST SLIDE BAITS; A SLOW ONE MEANS IT.
  • RISK ? NAME THE LAST POINT, NOT ONLY THE STOP and DISCIPLINE IS ASYMMETRIC BETWEEN WINNERS AND LOSERS.

The sharp-slide rule ships as a weak prior with its own counter-example attached ? it is the read that lost him the session, so it is recorded as a tie-breaker and explicitly barred from being a trade premise.

Prompt 96,627 ? 101,087 chars (headroom 18,913).

Tests

Two markers. The second is a drift guard asserting the forecasting rule still resolves to HOLD and still reconciles with v4c's MANUFACTURES MORE, so a later edit cannot quietly turn it into a licence to predict a crowd into existence.

Our agent on the same session

The doc addendum records it: the agent was SHORT all morning ? directionally right where IH was wrong ? and still lost more than any other strategy, because it took four short entries in 47 minutes and released three on premise-stall judgements rather than stops (two held 1 and 2 minutes; a 24400-target trade was let go at 24469?24492 having never been stopped).

That is the inverse of the failure v3y guards against. It is flagged as a lessons-loop candidate, not encoded as IH knowledge, because it is a property of our agent and not of the method.

P&L is marked provisional ? the runner was still live at 13:07 when this was written. SL Hunting's ?2,647.75 cross-checks exactly against its own Result summary; note MIRROR EXIT lines do not contain | EXIT , which under-counted the agent by 948.00 on a first pass.

Gates

SL Hunting pytest 173 passed ? full pytest 1136 passed ? ruff clean.


Bugfix: session state was stalling trading threads

41a78f8 ? unrelated to the knowledge work above, but found by running it.

The crash-durable session state added in #115 rewrote the whole JSON document with fsync on every write, including the 30-second supervisor snapshot. The first live session with it (2026-08-11) measured 223 writes over the 250 ms warning threshold:

n median max >1s
MainThread (30s snapshot) 210 0.830s 8.732s 85
Trading threads 13 0.414s 5.111s 2

The file was only 79 KB, so this is disk contention, not payload size ? shrinking the document would not have helped.

Why the obvious fix is unsafe on its own

Dropping fsync from the snapshot path looks like a one-line win. It isn't: os.replace is atomic for the name, not the data, so a hard kill during an un-fsynced rewrite can publish a present-but-garbage file. Because that single document also held trades[] and the P&L rollup, one torn snapshot could destroy the record ADR-0012 exists to protect ? turning a latency fix into a reintroduction of the original incident.

The split

File Contents Written by fsync
session_state.json trades[], P&L rollup, session date, shutdown flags trade events, clean shutdown, construction yes
session_state.marks.json live counters, open_position with last_mark_ltp the 30s supervisor snapshot no

The supervisor no longer touches the durable file at all, so it cannot corrupt it however it fails, and 210 of the 223 slow writes stop paying fsync ? including the 8.7s outlier. Losing the marks file costs at most one snapshot interval of mark data, which ADR-0012 already documented as acceptable.

load_session_state merges the pair back into the single-document shape, so resumable_open_positions, recorded_realized_pnl and the runner's resume path are unchanged. The merge is deliberately asymmetric: a corrupt durable file means no recovery (None); a corrupt or missing marks file still returns the P&L and simply offers no positions for resume.

Deliberately not done

Moving trade-event writes to a queue and a writer thread. It would remove the remaining 13 stalls, but only by weakening durability from "guaranteed before the call returns" to a sub-second window ? the exact guarantee ADR-0012 was written to provide. At a 0.414s median, 13 times a session, that trade is not worth making.

Two defects found while building it

  • A session that never recorded a trade created no durable file at all, so a process dying before its first trade left no document ? losing the session date, the shutdown flags, and any trade book carried forward from a same-day restart. Caught by two existing tests failing. The durable file is now established at construction.
  • The slow-write warning blamed "the caller's trading loop" for what was usually a supervisor write. Marks now warn separately at a looser 2s threshold with a message that says which one it is, so the 13 that matter are not buried under 210 that do not.

ADR-0012 gains an amendment section and docs/lld/reporting-and-observability.md is updated in the same commit. .gitignore now globs session_state*.json so a future sidecar cannot be committed by accident.

Verification

10 new tests (45 total in the suite), covering fsync-per-path, the durable file staying byte-identical across five snapshots, corrupt/missing/stale marks, and both files archiving under one timestamp.

CI: session_state.py branch coverage 91.6% against its 90% data-safety budget; total 69.6%; coverage policy gate passed.

Note: the fix takes effect on the next runner start. The session that produced these measurements was still running the old single-file path.

Docs: staleness gates over the committed architecture set

A third, unrelated commit rides along here (8c24fb3). It closes the follow-up recorded in ADR-0011 when docs/ was first filled in, and it is worth reading separately from the two changes above ? it touches no runtime code.

docs/ now holds an HLD, 12 LLDs and 12 ADRs. Nothing enforced that any of it stayed true, and stale architecture documentation is worse than none because it is believed. Three gates in Tests/Dependencies/test_repository_policy.py now cover three distinct ways it rots:

Failure mode Gate
A doc describes a roster or agent set the code no longer has docs/hld/system-overview.md joins test_current_architecture_docs_distinguish_core_from_optional_agents
A new ADR/LLD lands unlinked, or the index points at a deleted file test_every_committed_design_document_is_linked_from_the_docs_index ? checked in both directions
A rename breaks a cross-reference test_relative_links_inside_the_committed_docs_resolve ? 97 links today

docs/superpowers/ is excluded from all three: gitignored session working material, not product documentation.

The HLD did not actually pass

Worth calling out, because it is a real documentation gap rather than test plumbing. The HLD named the two optional agents only as class names inside an ASCII diagram (SLHuntingAIWorker) and as file links, and said "two independently opt-in AI agents" without naming either one. A reader of the system overview genuinely could not tell what they were. Section 1 now carries a short table ? each agent, its provider, its default-off flag, and its LLD.

Every gate was proven to fail

Each was verified against a deliberate mutation before being committed, then restored: an unlinked ADR, a dangling-only index link, a renamed cross-reference, and an agent dropped from the HLD. All four were caught, with file and line. A policy test that cannot fail is worse than no test, because it reads like coverage.

One caveat for reviewers

test_current_architecture_docs_distinguish_core_from_optional_agents reads architecture files from the working tree, so it is not safe to run while switching branches ? it will read one commit's docs against another's tests and fail spuriously. It is stable in CI and in any single checkout.

Suite goes 11 ? 13 tests. No runtime code touched.

?? Generated with Claude Code


CPR AI: R2/S2 continuation boundary

97f9ac6 adds one conservative CPR-agent rule: never enter a bullish TRENDING_VWAP_CONTINUATION above R2 and never enter a bearish continuation below S2.

The rule is enforced in both places that matter:

  • Codex knowledge: prompt version cpr-srsi-vwap-context-v3 tells the adviser to return HOLD / NONE instead of chasing price beyond the final CPR boundary.
  • Host safety: CPRHostPolicy independently rejects those proposals with continuation_outside_r2_s2, so model reasoning cannot waive the rule.

The comparisons are deliberately strict (close > R2 for longs and close < S2 for shorts). Existing milestone, final-target, stop-width, and minimum-1R geometry remain unchanged, and no sideways, reversal, sizing, order, or broker behavior was modified.

Verification

TDD RED first showed the missing prompt knowledge and generic geometry rejection. GREEN verification: CPR AI 70 passed; master 508 passed / 52 skipped; market health 26 passed; repository suites 1,142 passed; branch coverage 70.1% with every threshold passing; compileall, Ruff, mypy, Bandit, pre-commit, fake order-free smoke, and all four pinned dependency audits passed.

Implemented with Codex; the commit includes the required co-author trailer. No authenticated model or broker call was made.


CPR AI bugfix: master lazy imports

6f29e86 fixes the production-master failure that recorded ModuleNotFoundError: No module named 'cpr_ai_prompt' before Codex or MCP could run.

The standalone smoke and focused CPR tests could import sibling modules because Python kept the CPR AI source folder on sys.path. The master loader exposed that spaced-name folder only while each startup module executed, then removed it. The first completed-bar turn therefore could not perform the agent's intentionally lazy prompt/schema import; the delayed Codex runner had the same boundary and could also create incompatible duplicate result classes if loaded naively.

The fix retains only the already collision-checked CPR AI source directory after startup and aliases canonical cpr_ai_agent to the exact module object the master already loaded. Two production-style master tests prove that a delayed turn reaches its injected runner and that the Codex runner reuses the master's exact CPRAgentRunResult and CPRToolCallRecord types.

Combined-tree verification

The import-boundary tests passed 2/2; CPR AI passed 70/70; master passed 510/510 with 52 expected skips; market health passed 26/26; repository suites passed 1,142/1,142. Branch coverage is 70.1% and every threshold passed. Compileall, Ruff, mypy, Bandit, pre-commit, fake order-free smoke, and all four pinned dependency audits passed.

The change does not authenticate Codex, call a broker, or alter execution/risk behavior. Implemented with Codex; the commit retains its co-author trailer.

DoRmAmMu1997 and others added 3 commits August 11, 2026 14:26
Source: Intraday Hunter live session, 11 Aug 2026 (_JXirKMmI58, 9:25).
This one is a LOSS, and it is encoded because it is one -- every prior
addendum distilled a winning session, and a losing session shows which
part of the method was load-bearing and which part was rationalisation.

He named the disqualifying fact himself, twice, before entering:
"neither the BUYER's stop losses are available nor the SELLER's" and
"here not many traders were seated." He then traded a FORECAST of who
would arrive -- a sharp drop tempts intraday sellers in, so the market
should rise to take them out -- and the selling simply continued.

Knowledge changes (all prose):
- OPENING_DRIVE: WHICH CROWD THE OPEN RECRUITS DECIDES HOW BIG THE TRAP
  IS (gap-down recruits POSITIONAL sellers who hold overnight; a flat
  open recruits INTRADAY sellers only, so the same-shaped trap is
  smaller and perishable -- a genuine advance on v4d, independent of
  the outcome); A FORECAST OF WHO WILL ARRIVE IS NOT EVIDENCE OF WHO IS
  SEATED; A SHARP FIRST SLIDE BAITS, A SLOW ONE MEANS IT.
- RISK: NAME THE LAST POINT, NOT ONLY THE STOP; DISCIPLINE IS
  ASYMMETRIC BETWEEN WINNERS AND LOSERS.

The sharp-slide rule ships as a weak prior with its own counter-example
attached: it is the read that lost him the session, so it is recorded
as a tie-breaker and explicitly barred from being a trade premise.

Two test markers, the second a drift guard asserting the forecasting
rule still resolves to HOLD and still reconciles with v4c's
MANUFACTURES MORE, so a later edit cannot turn it into a licence to
predict a crowd into existence.

Prompt 96,627 -> 101,087 chars (headroom 18,913).

The doc addendum also records how our own agent traded the same
session. It was SHORT all morning -- directionally RIGHT where IH was
wrong -- and still lost the most of any strategy, because it took four
short entries in 47 minutes and released three of them on premise-STALL
judgements rather than stops (two held 1 and 2 minutes; a 24400-target
trade was let go at 24469-24492 having never been stopped). That is the
inverse of the failure v3y guards against, and it is flagged as a
lessons-loop candidate rather than encoded as IH knowledge, because it
is a property of our agent and not of the method.

Session P&L is marked provisional: the runner was still live at 13:07
when this was written. SL Hunting's -2,647.75 is cross-checked against
its own Result summary and matches exactly -- note MIRROR EXIT lines do
not contain "| EXIT ", which under-counted the agent by 948.00 on a
first pass.

Gates: SL Hunting pytest 173 passed, full pytest 1130 passed, ruff
clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Closes the follow-up recorded in ADR-0011. Three gates in
Tests/Dependencies/test_repository_policy.py, each answering a different way
documentation rots.

1. docs/hld/system-overview.md joins the existing architecture gate, so the HLD
   must keep both optional agents visible and must not let the ~27 core roster
   count read as the enabled total.

   The HLD did not actually pass that check as written: it named the agents only
   as class names in an ASCII diagram (SLHuntingAIWorker) and as file links, and
   said "two independently opt-in AI agents" without naming either. That is a
   real gap, not a test-matching problem -- a reader of the system overview
   could not tell what the two agents were. Section 1 now carries a short table
   naming both, their provider, their default-off flag and their LLD.

2. Every committed ADR and LLD must be linked from docs/README.md, and the index
   must not link a file that does not exist. Checked in BOTH directions: an
   orphaned document is never read and quietly goes stale, and a link left by a
   rename sends readers to a 404 and makes the whole index untrustworthy.

3. Every relative link inside docs/ must resolve. 97 links today. Renames are
   the normal way these break, and a broken link is invisible until somebody
   follows it, so it is checked mechanically rather than by review.

docs/superpowers/ is excluded from all three -- gitignored session working
material, not product documentation.

Each gate was verified to FAIL on a deliberate mutation before being committed:
an unlinked ADR, a dangling-only index link, a renamed cross-reference, and an
agent dropped from the HLD. A policy test that cannot fail is worse than no test
because it reads like coverage.

Suite goes 11 -> 13 tests, all green; ruff clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first live session with crash-durable state (2026-08-11) measured
223 writes over the 250ms warning threshold. Split by thread:

  MainThread (30s snapshot)  n=210  median 0.830s  max 8.732s  85 >1s
  trading threads            n=13   median 0.414s  max 5.111s   2 >1s

The file was only 79 KB, so this is disk contention rather than payload
size and no amount of shrinking the document would have helped. The
supervisor writes are the overwhelming majority and the worst outliers.

Dropping fsync from the snapshot path is the obvious fix, and on its own
it is UNSAFE. os.replace is atomic for the NAME but not for the DATA: a
hard kill during an un-fsynced rewrite can publish a present-but-garbage
file. Because that single document also held trades[] and the P&L
rollup, one torn SNAPSHOT could destroy the record ADR-0012 exists to
protect -- turning a latency fix into a reintroduction of the original
incident.

So the state is now two files:

  session_state.json        trades[], P&L rollup, session date, shutdown
                            flags. Written on trade events, on clean
                            shutdown, and once at construction. fsync.
  session_state.marks.json  live counters and open_position with
                            last_mark_ltp. Written every 30s. No fsync.

The supervisor no longer touches the durable file at all, so it cannot
corrupt it however it fails, and 210 of the 223 slow writes stop paying
fsync. Losing the marks file costs at most one snapshot interval of mark
data, which ADR-0012 already documented as acceptable.

load_session_state merges the pair back into the single-document shape,
so resumable_open_positions, recorded_realized_pnl and the runner's
resume path are unchanged. The merge is deliberately asymmetric: a
corrupt DURABLE file means no recovery and returns None; a corrupt or
missing MARKS file still returns the P&L and simply offers no positions.

Two things found while building it:
- a store that had only ever snapshotted never created the durable file,
  so a session dying before its first trade left no document at all --
  losing the session date, shutdown flags and any carried-forward trade
  book. The durable file is now established at construction.
- the slow-write warning blamed "the caller's trading loop" for what was
  usually a supervisor write. Marks now warn separately, at a looser 2s
  threshold, with a message that says which one it is.

Rejected: moving trade-event writes to a queue and writer thread. It
would remove the remaining 13 stalls, but only by weakening durability
from "guaranteed before the call returns" to a sub-second window, which
is the guarantee ADR-0012 was written to provide. At a 0.414s median,
13 times a session, that trade is not worth making.

ADR-0012 gains an amendment section and the reporting LLD is updated in
the same commit. .gitignore now globs session_state*.json so a future
sidecar cannot be committed by accident.

Gates: session-state 45 passed (10 new, covering fsync-per-path, the
durable file being untouched by snapshots, corrupt/missing/stale marks,
and both files archiving under one timestamp); master 508 OK;
market-data-health 26 OK; pytest 1136 passed; ruff and mypy clean;
module branch coverage 91.6% from its own suite alone against its 90%
budget.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@DoRmAmMu1997 DoRmAmMu1997 changed the title feat(sl-hunting): v4e knowledge from the 11 Aug live session feat(sl-hunting): v4e knowledge + session-state durability fix Aug 11, 2026
DoRmAmMu1997 and others added 3 commits August 11, 2026 15:14
Co-authored-by: Codex <codex@openai.com>
Keep the collision-checked CPR AI source directory importable after master startup and bind the canonical agent name to the already-loaded module so delayed prompt/schema/runner imports resolve without duplicate dataclass types.

Co-authored-by: Codex <codex@openai.com>
…ideo

Source: Intraday Hunter, "Prediction For 12 AUG 2026" (CoxS77NfnsI,
uploaded 2026-08-11, 2:00).

The starting condition differs from every note in this series so far: the
seller crowd is described as SPENT rather than seated. "Sellers would
certainly have entered on the retracement, but the market would have hit
their SLs. So if it has already taken the sellers out, we can go WITH the
market."

He then explains why nobody carried size overnight either -- "it did not
cross the round number, so not many people would have held their selling
quantity" -- which is v4e's recruitment rule applied to the close. No
round-number breach, no follow-through, so the session opens with thin
positioning on BOTH sides.

Plan: SELL-side setups on flat-to-gap-down, stated separately for all
three indices; a moderate gap-up keeps broadly the same plan.

Recorded faithfully rather than smoothed:
- the series' SECOND explicit escape hatch, this time for a large gap-up
  ("maybe the market has just made a trap... in a big gap-up we cannot
  make such a plan for now"), kept as stand-aside rather than a guessed
  branch, exactly as the 10 Aug note handled its missing branch;
- one genuine AMBIGUITY left unresolved: on NIFTY he also says a mild
  gap-up can be followed WITH the market "if not many sellers are seated
  the market may not find SLs", which cuts against the sell-side line.
  v4e's A FORECAST OF WHO WILL ARRIVE rule says an unclear read is not
  something to force into a direction, so the note carries the tension.

One BankNIFTY support arrived as "5710", read as 57100 alongside 56960 --
the same dropped-trailing-zero artefact seen on 4, 7 and 10 Aug. Noted in
the doc; advisory candidate levels only.

test_shipped_note_matches_august_12_intraday_hunter_plan replaces the
11 Aug equivalent and asserts the escape hatch and the ambiguity line
survive verbatim, because those are the two things a copy-forward or a
tidy-up would silently remove.

Gates: SL Hunting pytest 173 passed, ruff clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@DoRmAmMu1997
DoRmAmMu1997 merged commit 7e45a80 into main Aug 11, 2026
8 checks passed
@DoRmAmMu1997
DoRmAmMu1997 deleted the feat/sl-hunting-knowledge-v4e branch August 11, 2026 16:22
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.

1 participant