Phase C · PRD §5, SRD §8. Blocked by #575. The most important issue in this milestone.
The unit tests in #573 prove the adapter maps fields correctly today. They prove nothing about tomorrow. These pins prove that a later change — by anyone, for a good-sounding reason — cannot quietly wire an assessment into admission, into sizing, or into a cycle.
Follow the existing pattern: test_console_thinness.py, RULE5_IMPORT_ALLOWLIST, test_capabilities.py, test_service_isolation.py. Every pin must be mutation-verified — write the pin, break the thing it guards, watch it fail, restore.
The scans
1. The trading loop cannot reach the feed. AST scan: no module reachable from agent.run_once imports keel.analysis.feed, transitively. Mutation: add the import to any module in the cycle's reach and this fails.
2. Nothing under keel/analysis/ can attest. No set_state on an attestation key. Attestation is an operator act with a named source (docs/fiqh-basis.md); an assessment is not a qualified Shariah source and must never be recorded as one.
3. Nothing under keel/analysis/ writes the allowlist. assets propose admits nothing today and continues to admit nothing.
4. Nothing under keel/analysis/ places an order. No place_order, no preview_order, no broker construction.
5. The gate's input never widens. screen_fn is called with exactly (repo, product, quote). Mutation: pass the rationale as a fourth argument and this fails.
6. The feed is never a capability. It appears in no keel/capabilities.py row, because it increases nothing — it cannot attest, promote, arm, spend or place. Assert the absence. If a future change gives it any of those powers, that change must add the row and the gate, and this pin is what forces the conversation.
7. Sources are recorded, never fetched. keel stores citation URLs and does not retrieve them. Rendering a remote document would be an injection surface for no gain. Scan: no HTTP call takes a URL originating from a frame.
Done when
Seven pins, each mutation-verified, each with the mutation recorded in the commit message. A pin that has never been seen to fail is not a pin.
Phase C · PRD §5, SRD §8. Blocked by #575. The most important issue in this milestone.
The unit tests in #573 prove the adapter maps fields correctly today. They prove nothing about tomorrow. These pins prove that a later change — by anyone, for a good-sounding reason — cannot quietly wire an assessment into admission, into sizing, or into a cycle.
Follow the existing pattern:
test_console_thinness.py,RULE5_IMPORT_ALLOWLIST,test_capabilities.py,test_service_isolation.py. Every pin must be mutation-verified — write the pin, break the thing it guards, watch it fail, restore.The scans
1. The trading loop cannot reach the feed. AST scan: no module reachable from
agent.run_onceimportskeel.analysis.feed, transitively. Mutation: add the import to any module in the cycle's reach and this fails.2. Nothing under
keel/analysis/can attest. Noset_stateon an attestation key. Attestation is an operator act with a named source (docs/fiqh-basis.md); an assessment is not a qualified Shariah source and must never be recorded as one.3. Nothing under
keel/analysis/writes the allowlist.assets proposeadmits nothing today and continues to admit nothing.4. Nothing under
keel/analysis/places an order. Noplace_order, nopreview_order, no broker construction.5. The gate's input never widens.
screen_fnis called with exactly(repo, product, quote). Mutation: pass the rationale as a fourth argument and this fails.6. The feed is never a capability. It appears in no
keel/capabilities.pyrow, because it increases nothing — it cannot attest, promote, arm, spend or place. Assert the absence. If a future change gives it any of those powers, that change must add the row and the gate, and this pin is what forces the conversation.7. Sources are recorded, never fetched. keel stores citation URLs and does not retrieve them. Rendering a remote document would be an injection surface for no gain. Scan: no HTTP call takes a URL originating from a frame.
Done when
Seven pins, each mutation-verified, each with the mutation recorded in the commit message. A pin that has never been seen to fail is not a pin.