This repository was archived by the owner on Aug 8, 2026. It is now read-only.
Respecify the forced-flow test, and file the copy change it releases - #80
Merged
Conversation
…at cannot answer it A specification correction, explicitly NOT a work order. Section 7 says what would have to change before any of it could be executed, and section 8 states the count executing it would carry. Nothing here changes a published number, a weight, a threshold in src/, or the verdict. The mechanism test's section 8 records four places its specification was wrong. This is a fifth, larger than those four together and invisible until the flow composition was looked at. The outcome variable is Δ pool_net. On the sell side an agreeing pool is long and sells when price falls to F*, while a contradicted pool is short and ADDS shorts at the same level. Both are sell flow, both give Δnet < 0, and only the first is forced. The variable cannot separate a forced exit from a fresh entry in the same direction. This is not a new insight about futures. It is the opening paragraph of futures/flow.py: "Net position change cannot tell them apart, because Δnet = ΔLong − ΔShort is the same either way, and that is the whole reason this module exists." flow.decompose exists for the distinction and flow_state is a published column; the frozen section 5 references neither. Advisory and untested, from the artifact the verdict already commits: on the published flow_state of the week following a crossing, the named pool does what the trigger says and the contradicted pool does the opposite, in all four (report type, side) cells, a 3x to 5x separation the net erases. Disaggregated sell shows long_liquidation at 20.1% agreeing against 3.9% contradicted, and new_shorts at 9.4% against 25.8%. Swapping Δnet for flow_state is NOT the fix and the file says so: the labels are partly mechanical, because a net-long book has a bigger gross long leg and is likelier to be labelled long_liquidation, so the same confound reappears one level down. Section 4 proposes the fractional change in the exposed leg instead (Δlong_pool/long_pool on the sell side), which is a level ratio rather than a category and needs no sign flip. It also moves the primary contrast to crossed vs not crossed WITHIN the agreeing group, gives the falsification a pass criterion testing the difference between contrasts directly, and adds a side-consistency condition: TFF's surviving residual is sell -0.0072 against buy +0.0037. Section 5 lists what carries over unchanged, so a re-specification does not rewrite the parts that worked. Section 6 is a separate presentation consequence that needs no re-run: pool_agrees == False currently SUPPRESSES the reading in report.format_offside and cot-analyzer's damage page, where the measurement says the level is live and only the flow's composition differs. Section 7 also records that waiting does not help. The sample spans 57 blocks of 13 weeks and a further year adds about 4, roughly 7% more data and 3% tighter standard errors. The original's section 1 chose this question partly because its evidence regenerates, which is true in the sense that it is never spent and false in the sense of getting usefully stronger. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two corrections to section 6 of the respecification, both narrowing it, made because an overstated work order is how a copy change becomes a claim the data does not carry: - "Suppressing the row hides a real event" was wrong. The row is not hidden. It is plotted with a hollow marker, named in the legend, and given a grid cell. What is wrong is only the copy: "would force a book that is not there" implies nothing follows, and something does. - The quadrant suppression itself is correct and stays. The quadrant's severe axis is D, a conditional severity for the NAMED pool, so placing a contradicted row in a cell would attach the wrong pool's severity to a real level. Reading instruction 1 of cot-analyzer's damage page has this right. Section 6 also now states that the composition split may not enter user-facing copy. "It arrives as fresh shorts rather than as long liquidation" is the untested part of that file, and a rendered surface asserting it would convert an advisory crosstab into a published claim. New handoff 2026-08-06-trigger-contradicted-copy.md, status open, the only part of this lineage actionable without a re-run. It rests only on what the verdict tested: flow follows a crossing either way (disaggregated sell, within-group, -0.0190 agreeing against -0.0184 contradicted) and the crossing-specific difference is small (-0.0014 and -0.0027). Its section 5 is the reason it is a handoff rather than a three-line patch. The phrase "pool on the other side" is authored locally in cot-analyzer's damage.py in two places and is NOT in test_damage_vocabulary.py's FRAGMENTS, even though it carries crowdmon's reading exactly as the QUADRANT phrases do. A session that changes only crowdmon's copy ships a producer and a page saying different things with every test green. So the work is: crowdmon first (named constant, COLUMN_DEFINITIONS, manifest), cot-analyzer second (read it, delete both local copies, extend the guard). Section 4 names five things that must not change while doing it, including that SCHEMA_VERSION must not be bumped, since publish.py records that a bump ahead of a consumer release loses the whole /damage page rather than the new key. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #79, which closes the mechanism test. This files the correction beside the result rather than leaving it in a session's memory.
This is a specification correction, not a work order. §7 says what would have to change before any of it could be executed, and §8 states the count executing it would carry. The register row says the same, loudly, because a handoff without a completion status gets executed by a future session and this one must not be.
Nothing here changes a published number, a weight, a threshold in
src/, or the verdict.The defect
The mechanism test's §8 records four places its specification was wrong. This is a fifth, larger than those four together, and invisible until the flow composition was looked at.
The outcome variable is
Δ pool_net. On the sell side an agreeing pool is long and sells when price falls toF*; a contradicted pool is short and adds shorts at the same level. Both are sell flow, both giveΔnet < 0, and only the first is forced.This is not a new insight about futures. It is the opening paragraph of
src/crowdmon/futures/flow.py:flow.decomposeexists for exactly this distinction andflow_stateis a published column. The frozen §5 references neither.What the composition shows
Advisory and untested, from the artifact the verdict already commits. Share of the week following a crossing carrying each state:
long_liquidationnew_shortsshort_coveringnew_longsAll four cells: the named pool does what the trigger says, the contradicted pool does the opposite, a 3x to 5x separation that the net erases.
The obvious fix is not the fix
Swapping
Δnetforflow_statewould be a better test with the same structural flaw. The labels are partly mechanical: a net-long book has a bigger gross long leg, so its moves are likelier to dominate the classification and be labelledlong_liquidation. The confound §8 found in the sign ofpool_netreappears one level down.§4 proposes the fractional change in the exposed leg instead —
Δlong_pool / long_poolon the sell side — a level ratio rather than a category, scale-free, and needing no sign flip. Plus three closures: a within-group primary contrast, a falsification with a pass criterion testing the difference between contrasts directly (the missing criterion is what produced the original verdict), and a side-consistency condition, since TFF's surviving residual is sell −0.0072 against buy +0.0037.§5 lists what carries over unchanged, so a re-specification does not rewrite the parts that worked: §3.1's vectorisation, the universe rule, the lookbacks and window, the block bootstrap, §5.9's pinning, and §3.2's scope refusal.
Two things worth reading even if this is never executed
§6, the presentation consequence, needs no re-run. When
pool_agrees == False,report.format_offsideand cot-analyzer's damage page both say the level "would force a book that is not there". That is half right: the forced book is not there, but price reaches the level and flow still follows, only slightly smaller. The row itself is rendered and named — what is wrong is the claim attached to it. See the correction below, which narrows this.§7 records that waiting does not help. The sample spans 57 blocks of 13 weeks and a further year adds about 4 — roughly 7% more data and 3% tighter standard errors. The original's §1 chose this question partly because its evidence regenerates, which is true in the sense that it is never spent and false in the sense of getting usefully stronger on any horizon worth waiting for.
Also here: §6 corrected, and the work order it releases
Two corrections to §6, both narrowing it, because an overstated work order is how a copy change becomes a claim the data does not carry:
D, a conditional severity for the named pool, so a contradicted row must not be given a cell. Reading instruction 1 of cot-analyzer's damage page has this right.§6 now also states that the composition split may not enter user-facing copy. "It arrives as fresh shorts" is the untested part of this file.
New handoff:
2026-08-06-trigger-contradicted-copy.md, statusopen— the only part of this lineage actionable without a re-run. It rests only on what the verdict tested: flow follows a crossing either way (Disaggregated sell, within-group, −0.0190 agreeing against −0.0184 contradicted) and the crossing-specific difference is small.Its §5 is why it is a handoff and not a three-line patch. The phrase
pool on the other sideis authored locally in cot-analyzer'sdamage.py, in two places, and is not intest_damage_vocabulary.py'sFRAGMENTS— even though it carries crowdmon's reading exactly as theQUADRANTphrases do. Change crowdmon's copy alone and you ship a producer and a page saying different things, with every test green. So: crowdmon first (named constant,COLUMN_DEFINITIONS, manifest), cot-analyzer second (read it, delete both copies, extend the guard). §4 names five things that must not change while doing it, including thatSCHEMA_VERSIONmust not be bumped.Plain-language bottom line
The mechanism test asked whether a book that is about to be forced out actually leaves, and measured it by watching the book's net position. But a net position falls both when longs leave and when fresh shorts arrive, and those are opposite situations — one is forced, one is voluntary. Looking instead at which leg actually moved, the two groups behave completely differently, and in the direction the original claim predicted. So the question is more alive than the verdict makes it look.
That is not licence to redo the test today. The obvious repair carries a subtler version of the same bias, the better repair needs data the published panel does not carry, and re-running on the same history is a second look that has to be priced as one. Filed so the next person starts from the corrected design rather than the flawed one.
🤖 Generated with Claude Code