Skip to content

docs(fiqh): the cash posture residual is recorded, not merely acknowl… - #713

Merged
eaitbrahim merged 2 commits into
mainfrom
feat-691-fiqh-and-brokers
Sep 3, 2026
Merged

docs(fiqh): the cash posture residual is recorded, not merely acknowl…#713
eaitbrahim merged 2 commits into
mainfrom
feat-691-fiqh-and-brokers

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

…edged (#691, part 2 of 2)

Closes #691. The last two acceptance boxes: keel brokers list and the docs/fiqh-basis.md open question.

THE PIN DID NOT FAIL WHEN IT SHOULD HAVE, AND THAT IS THE FINDING. test_the_unprovable_half_of_the_cash_posture_is_stated_not_hidden promised in its own docstring that "closing that needs a human attestation, not another adapter read -- and if one is ever built, this fails again". #691 built one. The pin passed, and the issue's own acceptance criterion predicted a failure that never came.

Nothing in the pin observed the attestation, so it repeated its FIRST failure mode exactly: that form pinned _sell_base_size's docstring as a proxy and held while the paragraph it guarded went false. A promise in a docstring is not a pin, and prose that matches is not prose that is true.

So this re-pointing reaches for the MECHANISM rather than for sentences. Four assertions that each go false if something real is removed:

  • CashPostureState must carry no CONFIRMED -- adding one would mean keel believes something can AFFIRM a spot cash account, which is the claim the doc spends a section refuting.
  • ATTESTATION_TTL_SEC > 0 -- without expiry, "the operator states it and keel records it" degrades to "keel remembers what someone said once".
  • cash_posture must appear in guards.py -- with no rail reading the record, "an unattested posture vetoes live entries" is a sentence about nothing.
  • the stale "a human attestation this repository has not yet built" must be GONE -- the specific prose regression, caught by string rather than hoped about.

THE DOC. Two passages were wrong on their facts, not merely dated: one said keel "has no cash-account posture check on Coinbase", which #666 added, and the other said the attestation was unbuilt. Both are corrected, and the section now states the three load-bearing properties (no confirmable state, a 90-day expiry, a claim bound to a credential) followed by the sentence to keep if only one survives: keel still cannot verify this, and neither can the venue. What changed is that the trust is now dated, revocable and written down, rather than assumed.

THE BLOCK. keel brokers list gains a THIRD block after declarations and readiness, which follows this codebase's own argument rather than a preference: venue_readiness renders separately because merging two questions "would re-blur exactly the distinction #233 exists to draw". Posture is a third question -- readiness asks whether this CREDENTIAL may trade, posture asks whether this ACCOUNT can borrow. It ends on its own honesty line, and a test forbids the words "verified", "confirmed", "checked" and "proven" anywhere in it: every other readiness surface reports something it checked, and this one cannot.

Read-only and best-effort, _readiness_rows' discipline -- a display command must not create a database, and a pre-v18 file renders an empty block rather than failing.

Tests written first: 9 on the block, plus the re-pointed fiqh pin.

Mutation-verified, 6 mutants. One SURVIVED: replacing sorted with reversed produced identical output because the fixture had only two venues in reverse alphabetical order. Three venues now, in an order where reversing is not sorting.

Closes #691

Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL

What & why

Tests-first evidence

  • Tests written first, seen failing for the right reason

Gates (all must pass)

  • uv run ruff check clean
  • uv run mypy clean
  • uv run pytest -q green

Scope check

  • This PR touches a rail or a default classification — checked means it DOES;
    leave checked only if true, and if so: cite the source and open the discussion
    BEFORE review (CONTRIBUTING.md, "Governance: rulings vs. machinery").
  • New dependency added (needs discussion first)

eaitbrahim and others added 2 commits September 3, 2026 18:28
…edged (#691, part 2 of 2)

Closes #691. The last two acceptance boxes: `keel brokers list` and the
`docs/fiqh-basis.md` open question.

THE PIN DID NOT FAIL WHEN IT SHOULD HAVE, AND THAT IS THE FINDING.
`test_the_unprovable_half_of_the_cash_posture_is_stated_not_hidden` promised in its
own docstring that "closing that needs a human attestation, not another adapter
read -- and if one is ever built, this fails again". #691 built one. **The pin
passed**, and the issue's own acceptance criterion predicted a failure that never
came.

Nothing in the pin observed the attestation, so it repeated its FIRST failure mode
exactly: that form pinned `_sell_base_size`'s docstring as a proxy and held while
the paragraph it guarded went false. A promise in a docstring is not a pin, and
prose that matches is not prose that is true.

So this re-pointing reaches for the MECHANISM rather than for sentences. Four
assertions that each go false if something real is removed:

  * `CashPostureState` must carry no `CONFIRMED` -- adding one would mean keel
    believes something can AFFIRM a spot cash account, which is the claim the doc
    spends a section refuting.
  * `ATTESTATION_TTL_SEC > 0` -- without expiry, "the operator states it and keel
    records it" degrades to "keel remembers what someone said once".
  * `cash_posture` must appear in `guards.py` -- with no rail reading the record,
    "an unattested posture vetoes live entries" is a sentence about nothing.
  * the stale "a human attestation this repository has not yet built" must be GONE
    -- the specific prose regression, caught by string rather than hoped about.

THE DOC. Two passages were wrong on their facts, not merely dated: one said keel
"has no cash-account posture check on Coinbase", which #666 added, and the other
said the attestation was unbuilt. Both are corrected, and the section now states
the three load-bearing properties (no confirmable state, a 90-day expiry, a claim
bound to a credential) followed by the sentence to keep if only one survives:
**keel still cannot verify this, and neither can the venue.** What changed is that
the trust is now dated, revocable and written down, rather than assumed.

THE BLOCK. `keel brokers list` gains a THIRD block after declarations and
readiness, which follows this codebase's own argument rather than a preference:
`venue_readiness` renders separately because merging two questions "would re-blur
exactly the distinction #233 exists to draw". Posture is a third question --
readiness asks whether this CREDENTIAL may trade, posture asks whether this
ACCOUNT can borrow. It ends on its own honesty line, and a test forbids the words
"verified", "confirmed", "checked" and "proven" anywhere in it: every other
readiness surface reports something it checked, and this one cannot.

Read-only and best-effort, `_readiness_rows`' discipline -- a display command must
not create a database, and a pre-v18 file renders an empty block rather than
failing.

Tests written first: 9 on the block, plus the re-pointed fiqh pin.

Mutation-verified, 6 mutants. One SURVIVED: replacing `sorted` with `reversed`
produced identical output because the fixture had only two venues in reverse
alphabetical order. Three venues now, in an order where reversing is not sorting.

Closes #691

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL
…tabase (#691)

Three findings from the review of #713. The first two were both already argued,
in a docstring one function away from the code that violated them.

1. `_cash_posture_records` used `keel.data.db.connect` -- the read-WRITE opener.
   `venue_readiness._read_only_trade_scope` carries a marked paragraph saying
   "**Not `keel.data.db.connect`, and that is the whole point of this function**",
   because `connect` runs `PRAGMA journal_mode = WAL` on whatever it opens. That is
   a WRITE, from a read-only informational command, and it can leave `-wal`/`-shm`
   sidecars behind. The `Path.exists()` guard stopped file CREATION and did nothing
   about the write. Now the `mode=ro` URI shape (#610's seam), with the existence
   check still in front of it because `mode=ro`'s own refusal is an exception and
   this path wants an answer.

   `test_reading_the_records_never_writes_to_the_database` opens the file in DELETE
   journal mode, reads, and asserts the mode is unchanged and no sidecar appeared --
   the observable, rather than an assertion about which function was called.

2. It returned `[]` for BOTH "nothing is attested" and "could not read this
   database", so the block would advise `keel posture attest --spot-cash` about a
   record that was fine and merely unread. That harm is named verbatim in the same
   docstring, and it is WORSE here than for trade scope: re-attesting resets
   `attested_ts` and `attest_due_ts`, and the TTY gate would ask the operator to
   affirm a cash account they may not have re-checked. A display bug would become a
   prompt to make an unverified claim.

   Now `(records, unreadable)`, the shape that function already uses, and the
   unreadable block deliberately does NOT print the attest command -- withholding
   that prompt is the entire point of separating the two answers. "No database at
   all" stays NOT-unreadable: that is a true statement about the machine rather
   than an admission of ignorance.

3. `_utc_day` duplicated `posture.py::_utc_date` byte for byte. Imports the
   existing one -- two formatters for one record type drift the day either gains a
   timezone or a width.

Tests written first, red before green: 5 new, all failing for the right reasons.

Mutation-verified, 4 mutants, all killed: the read-write opener restored; the
unreadable flag collapsed to False; a missing database reported as unreadable; the
unreadable block advising an attestation anyway.

Refs #691

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL
@eaitbrahim
eaitbrahim merged commit fc3969a into main Sep 3, 2026
4 checks passed
@eaitbrahim
eaitbrahim deleted the feat-691-fiqh-and-brokers branch September 3, 2026 22:55
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.

Stage 2 of #666: an operator attestation for the cash posture no venue can affirm

1 participant