tls: first-party contexts inherited an unasserted suite list (#1317), repair main's census tests, file #1319 and #1322 - #525
Merged
Conversation
…iminate its own mutation under load Recovered from a session that was measuring repo health when its Claude account was cancelled mid-command. It had found the CI failure and never reported it. THE OBSERVED FAILURE. tests/test_adr0157_demote_teardown.py:106 asserts elapsed < 1.5 and reported 1.92s on main at 2d1c89e, CI run 32580332076, leg test (ubuntu-latest, py3.14). That commit was docs-only, so nothing in the tree under test moved the number. WHAT MAKES IT MORE THAN A FLAKE, and it is measured rather than argued. Four implementations, 200 sources at 0.4s under a 3.0s budget: shipped, max-shaped 0.40s 200/200 finished timing PASS MUTANT sequential 3.01s 7/200 finished timing FAIL MUTANT semaphore(8) 3.00s 56/200 finished timing FAIL MUTANT semaphore(64) 1.63s 200/200 finished timing FAIL The semaphore(64) row is the item. Every source finishes, so all(stop_finished) passes and _pending_source_stops is empty -- the wall-clock bound is the ONLY assertion that catches it. So the threshold cannot simply be raised: the discriminating band is (0.40, 1.63) and the bound sits at 1.50. CI measured 1.92s for the SHIPPED implementation, which is above the 1.63s the mutant produces. On that run the correct code was slower than the defect the assertion exists to detect, so no threshold in the band could have separated them. That is the same class as #1290 -- an instrument that goes silent on its own subject exactly when it is under stress. LOCAL CONTROL. Seven consecutive runs on Windows while the full suite ran concurrently: 0.40 0.41 0.40 0.41 0.41 0.41 0.41. The floor is the 0.4s sleep plus ~10ms, so CI's 1.92s is runner latency, not the tree. The item records the fix direction (_Source already carries stop_started, and concurrency width separates all four rows with no timing dependence) and states plainly what is NOT established: this is at least one observed failure, with no rate measured and no same-head re-run recorded. Number allocated through scripts/coord/alloc.ps1. Backlog parser clean at 567 items, each declaring exactly one status.
…serted suite list (BACKLOG #1317) Closes the first-party half of the residual #1317 recorded as open. That item covered the operator-facing knob and the shipped context builder; it did not enumerate every SSLContext the engine constructs. RECOVERED, NOT REDONE. This was built by a workflow whose parent session's Claude account was cancelled on 2026-08-22 at 16:56Z while its full-suite run was in flight. The tree was left uncommitted in a locked worktree, three commits behind. It is replayed onto current main -- which had moved two commits, including #1317's own build -- and re-verified there. The claim on #1317 was taken over from that dead seat via claim.ps1 -Force, recorded in claims/.history. THE DEFECT IS INHERITANCE WITHOUT ASSERTION, not a missing context. Every hop below always had a TLS context; the engine simply never held a reference to it, so harden_cipher_suites never ran on it. Sites now asserted: auth/oidc_http.py identity provider token + JWKS hop logging_setup.py syslog TLS forwarder, BOTH arms incl tls_verify=False store/postgres.py pinned-CA and verification-disabled arms transports/soap.py mutual-TLS opener transports/rest.py shared REST/FHIR/DICOMweb opener family transports/fhir.py digest-auth rebuilt opener pipeline/alert_sinks.py webhook opener IT ASSERTS ON URLLIB'S OWN CONTEXT RATHER THAN SUBSTITUTING ONE, and that is load-bearing. Measured on CPython 3.14.6 / OpenSSL 3.5.7: urllib's context adds set_alpn_protocols(["http/1.1"]) and post_handshake_auth=True, which a hand-built ssl.create_default_context() has neither of. Passing a look-alike would silently drop ALPN and TLS 1.3 post-handshake auth from every default HTTP-family hop -- a handshake change on a control whose whole point is to change nothing about the connection. build_asserted_https_handler reads the handler's private _context and FAILS CLOSED if absent, rather than shrugging and reporting success forever. TWO FIRST-PARTY SITES ARE DELIBERATELY NOT ASSERTED, each with its reason in the code so a later reader does not "fix" them. The TLS floor probe builds ALL:@SECLEVEL=0 on purpose -- asserting there would empty the offer and turn a probe that can fail into one that cannot. And the Postgres ssl=True default arm hands asyncpg the job, so no engine object exists to assert on; grading a look-alike would grade an object the connection never uses. THE INSTRUMENT THAT GUARDED THIS RESIDUAL COULD NOT SEE IT, which is why the new test file is the other half rather than more of the same. test_tls_policy.py derives its call-site list from the presence of harden_kex_groups( in a file and its guard is `if kex and assertions < len(kex)`, so a file with ZERO kex-pin sites is skipped entirely. Every site above called neither helper, so the scan passed over all of them in silence. test_tls_cipher_assertion_sites.py names each construction and proves the assertion is REACHED, not merely present: contexts that are built are checked by patching _is_forward_secret to report every suite weak and requiring a ValueError naming that site's connector; contexts handed through an opener are checked by requiring the context the opener will actually use to be the SAME OBJECT the assertion ran on. It carries its own positive control, so a test seeing no raise reports a missing call rather than an inert instrument. VERIFICATION, stated exactly. ruff check, ruff format --check and mypy --strict all clean. 141 passed across test_tls_cipher_assertion_sites, test_tls_policy and test_soap_wssecurity -- run against current main, so the work is confirmed compatible with #1317's newer three-property harden_cipher_suites (forward secrecy plus encryption plus peer authentication), which landed after it was written. THE FULL SUITE IS STILL RUNNING and its result is NOT in this message; it is committed now rather than held because the pool that killed the first attempt is running hot again, and a branch commit is recoverable where an uncommitted worktree is not. CI is the authority.
…d only a skipped leg hid it NOT A DEFECT IN THIS BRANCH. #514 (BACKLOG #1187, merged as fdd89b4) added a `masked` key to the summary_access audit detail and updated the coalescer, but not the Postgres or SQL Server twins of the census test. This branch merely ran the legs that hid it. api/app.py _emit, on main: detail=json.dumps({"count": count, "masked": masked, "window_start": hour*3600}) tests/test_postgres_store.py:3409 asserted {"count": 5, "window_start": 0} tests/test_sqlserver_store.py:3435 asserted the same MAIN IS NOT RED, IT IS BLIND -- which is the worse half and the reason this needs saying. Both DB legs were SKIPPED on main's CI at fdd89b4 and at ae72f58 before it, so main reports green while carrying two failing tests. They run on a pull request, so the first PR to touch anything after #514 inherits three red required- adjacent legs it did not cause. This one did: postgres store, sql server 2022 and sql server 2025. WHY THE LEG THAT DID RUN STAYED GREEN, and it is not luck. The SQLite twin at tests/test_api.py:587 asserts `'"count": 5' in detail` -- a SUBSTRING containment check, which cannot see an added key. The two store twins assert DICT EQUALITY, which can. So the weaker assertion survived a change the stronger ones caught, and the stronger ones were the ones not being run. VERIFIED AT RUNTIME, not read off the source. Driving the real _SummaryAuditCoalescer end to end against a live store: ACTUAL detail: {'count': 5, 'masked': 0, 'window_start': 0} OLD assertion holds : False FIXED assertion holds: True The coalescer is backend-agnostic -- it calls store.record_audit and nothing in the shape is per-backend -- so the SQLite run is evidence for the Postgres and SQL Server paths, which is exactly the substitution that makes this checkable here. WHAT THIS RUN DOES NOT PROVE, stated because a local pass would be misleading: this repo SILENTLY SKIPS both DB legs locally. Measured on this tree, 152 skipped and zero run. CI is the only authority for the two lines themselves. LEFT ALONE DELIBERATELY: test_api.py:587's substring assertion. Tightening it to equality is the right change and it belongs to #1187's owner, not to a branch recovering unrelated TLS work.
wshallwshall
enabled auto-merge (squash)
August 22, 2026 17:48
…ot on the sources they assert against Root cause of PR #525's three red DB legs. Found by the liaison; every claim below re-verified against origin/main by this seat before filing. NOT "MAIN SKIPS THE LEGS". That is deliberate and filing it would be filing a billed-minutes decision: ci.yml:1521 is `schedule || workflow_dispatch || serverdb=='true'` and its own comment names the no-per-merge-run guard. The defect is one level down, in the PR arm -- the only arm that can catch a change BEFORE it lands -- whose producer set has a hole. THE HOLE. ci.yml:1358's alternation lists messagefoundry/store/, three pipeline modules, config/(settings|wiring), a transports list, a tests/test_(...) list and ci.yml. It does not list messagefoundry/api/. THE INVARIANT IS WRITTEN ONE LEVEL TOO NARROW. ci.yml:1348 requires the alternation list "every file the sqlserver-store / postgres-store pytest steps below run" -- the TEST files. Not the SOURCE those tests assert against. test_postgres_store.py asserts on a dict built by api/app.py::_emit, so the rule cannot see this class. IT HAS ALREADY FIRED. #514 touched api/app.py, serverdb evaluated false, the legs never ran on its PR, push never runs them, and it merged green leaving two store tests asserting a stale shape. PR #525 selected the legs and inherited three reds it did not cause. SECOND WEAKNESS NAMED ON THE ROW, not folded into the fix: the SQLite twin at test_api.py:587 asserts substring containment and is blind to an added key. The assertion strong enough to catch the change was the one not being run; the one being run was too weak to notice. Tightening it belongs to #1187's owner. Severity bounded in the same line that causes it -- the schedule arm runs these legs nightly, so the blind window is about a day. What it does not do is stop the merge. Number allocated and claimed through scripts/coord. Backlog parser clean at 568 items, each declaring exactly one status.
wshallwshall
added a commit
that referenced
this pull request
Aug 22, 2026
…only #525 landed 1319 and 1322 at the same append point this branch adds 1318, 1320 and 1321 to, so both sides grew the BACKLOG tail. Kept both, main's side first, no re-sorting. A second smaller conflict in one banner block kept main's SHIPPED-BUT-OPEN note above the Verdict and Closing-act fields this branch added. The merge routes here rather than to the lander because 1318, 1320 and 1321 are allocated to this worktree and the ledger gate accepts a BACKLOG.md carrying them only from the tree that holds the allocation. Result is 335 items, not the 334 forecast: main carries 332, this branch 333, and the three unique here are 1318, 1320 and 1321 against 1319 and 1322 there. The forecast predates the 1321 filing. Verified as a set union rather than an arithmetic guess. Line endings verified rather than assumed. The file is CRLF throughout, 13386 of 13386, zero bare LF introduced. My first check reported it as all-LF, which was a false zero from a broken shell quote, and acting on that would have rewritten every line. Conflict markers checked anchored at line start, because the file legitimately quotes one in item prose and a bare substring test fails on a correctly resolved file.
wshallwshall
added a commit
that referenced
this pull request
Aug 22, 2026
Two seats filed the same root cause within minutes. #1322 landed on main first via #525; #1321 is mine and arrives by merge, so neither the ledger gate nor either author could see the collision. #1322 is the better record and carries everything #1321 does, including the substring-versus-equality point about the SQLite twin. The lander caught it before the merge was pushed, not me. I filed #1321 after correcting its headline twice and never checked whether the defect was already on main. The banner is deliberately not flipped. Closing is the lander's act per BUILDER.md:253 and :148, so the row says so and the closure is handed over. Until then it is an open duplicate and the row warns a reader who reaches it first. CRLF preserved, zero bare LF, item count and every status asserted unchanged.
wshallwshall
added a commit
that referenced
this pull request
Aug 22, 2026
… refuses (#524) * backlog: file #1318 -- init writes a config the loader rejects messagefoundry/scaffold.py emits an uncommented host key under [api]. That key is in _RELOCATED_TO_SECURITY, and _reject_relocated_keys runs during load_settings. So the product generates a file the loader that reads it refuses, and the first serve after the first init fails. Present in the published release at v0.3.2, not only on main. The test gap is the part worth keeping: the two scaffold test modules call load_settings zero times, against a positive control of 58 test files that do. They assert string presence in the generated TOML, so a test asserting a string the loader rejects certifies the defect rather than catching it. Three sibling keys sit commented in the same template with instructions to uncomment them, each of which becomes this same failure when an operator follows the line beside it. Measured by the ASVS Tracker, verified independently by the Liaison, re-verified here before filing. One citation corrected in that chain: the emitting file is messagefoundry/scaffold.py, not messagefoundry/config/scaffold.py -- my own first read returned empty against the cited path, which is what surfaced it. Conditional per CLAUDE.md section 0: zero deployments, so nobody is hitting this today. A new adopter would hit it on their first two commands. * backlog: file #1320 and amend #1318's writer-set framing #1320: messagefoundry check catches ValueError from load_settings at three sites -- posture, build-check, alert-smtp-tls -- and returns ok with skipped. So the gate loads a refused config, receives the refusal, prints it, and exits zero. The existing test asserts rc == 0 and therefore passes on a config the loader rejects. That is larger than #1318 and independently true: fix the scaffold template and no config error of this class is failable. The fix is a distinction rather than a catch list -- absent is a legitimate skip, present-but-refused is not, and the except clause renders them identically. Same two-states-one-signal shape this repo already records for goalPromptedAt. #1318 amended: I filed it as though scaffold.py wrote one template. It writes three. The other two carry zero relocated keys for a structural reason -- they are flat env() value files, not settings sections, so no (section, key) pair can match. Population is 1 active and 3 armed over the complete writer set. The one-line diagnosis in the amendment is a builder's: the scaffold did not change, the loader did. ADR 0118's relocation swept the docs and the settings and never swept the one place that writes a config. Both found by builders while sizing work I had scoped narrowly. Conditional per CLAUDE.md section 0 throughout. * backlog: correct #1320 to five catch sites, and name the fifth as a different defect Filed as three. A builder found a fourth. Reading every catch of the tuple in messagefoundry/checks.py finds five. The fifth is worse in kind, not just one more of the same. Four return CheckResult with skipped=True and detail "settings did not load", so the reason survives even though the exit code discards it. The fifth returns PipelineSettings().snapshot_on_send -- a shipped default substituted for a config that was refused, with no CheckResult, no detail, and nothing printed. A reader cannot tell it fired. Also corrects the file: messagefoundry/checks.py at 1761 lines, not messagefoundry/verify/checks.py at 251, which holds none of them. My first read went to the wrong path and returned an empty result, which is the same wrong-path trap that #1318 already carries. The count moving 3 to 4 to 5 across three seats in twenty minutes is recorded in the item as the lesson: each measured honestly and each stopped at the first population their instrument could see. * backlog: correct #1320 to four checks, scoping the fifth out as a resolver I amended this item to five sites and said fix all five. Two seats independently classified the fifth as a value resolver rather than a check: the builder fixing it and a second seat measuring the same file, neither prompted by the other. This ledger was the outlier, so it moves. A check owes a CheckResult; a resolver owes a value. Widening the resolver's contract is a different change with a different blast radius, and with the four checks now failing on a refused config the gate fails anyway. The resolver still swallows silently and the item now says so explicitly, so that "four" is not read as the whole surface. * backlog: promote Verdict and Closing-act into the banner block on 192 open items The field that decides whether a seat can finish an item has never been readable by any tool. Verdict sits below the line where parse_items stops, so nothing has ever read it, and a 93-item wave went out whose every item carried a verdict that has closed zero times in 330 closed items. It closed zero. This moves the machine-readable state into the banner blockquote, the only region the parser reads, in the exact form the new field parser matches: a blockquote line of key, colon, value, restricted to verdict, research and closing-act. Closing-act is derived only where the derivation is evidenced. Verdict build means the closing act is code. Verdict research means a vault scorecard re-score, which is what the zero-closure measurement actually showed. The 26 demand-gate items and the 20 with no declaration are deliberately left alone: a missing field reads as a refusal, which is the safe direction, and inventing a closing act for them would be the same guess that caused this. 192 items carry the fields now, 98 closing by code and 94 by re-score. Verified by asserting the item count, the item numbers and every open or closed status are unchanged across the rewrite, and that the diff is 384 insertions with no other line touched. * backlog: record two owner rulings on the items they govern, and stop #1243 dispatching Both rulings were made today and lived only in the owner queue record, so the items they govern did not carry them. A builder found the first one the expensive way, while about to take the item. #1243 is blocked pending a real FHIR server. It is #1107 clause 3, and the encoding question cannot be settled against our own suite because that suite pins %7C in five places and so cannot disagree with itself. Its Closing-act moves from code to blocked. I set it to code an hour ago in the field migration, which would have let a dispatch gate hand it to a builder. The migration derived the closing act from the verdict, and a verdict cannot see a block. The item also carries an OWNER-RULED banner for a different ruling of 2026-08-13, so a search for the phrase already hits and returns a reader who then stops looking. The note says so, because that is what nearly sent this item out twice in one hour, once from this seat. #332 now carries the sigstore ruling: pin sigstore==4.4.0 and hash-lock it, not 4.5.0. That row already names release.yml:255 and the OIDC identity it runs under. Verified by asserting the item count, numbering and every status are unchanged. * backlog: file #1321 -- main skips the two DB legs that would catch a break A change can merge to main breaking the Postgres and SQL Server suites and main still reports green, because neither leg runs on a push. Their if: has no push case and the guard comment above them says so outright. The first pull request afterwards inherits the red. It has already fired. #1187 added a masked key to the summary-access coalescer. Both database twins assert dict equality and break on it; the SQLite twin asserts substring containment and cannot see an added key at all. The generalisable half is the assertion strength rather than the skip. The leg that ran passed honestly because its assertion was too weak to observe the change, and the two assertions strong enough to catch it were the two not being run. A skipped strong check and a running weak check produce the same green and only one is evidence. Verified at origin/main rather than this worktree, which was one commit behind and initially showed no masked key at all. Whether the SQLite twin should assert equality is #1187's call and is named as out of scope here. * backlog: correct #1321 -- the defect is the producer set, not the push skip I filed this an hour ago with the wrong headline. That the container legs do not fire on a push is intended, and ci.yml:1317-1319 says so in as many words. Filing that would have been filing a decision as a bug. A peer refuted it and I re-measured at origin/main. The real hole is that the serverdb path alternation at ci.yml:1358 does not list messagefoundry/api/, so a change confined to api/ selects those legs on neither a pull request nor a push. Counted in that one line with a control: messagefoundry/api appears zero times, messagefoundry/store once. The break did not slip past the legs; they were never selected. The invariant is already written one level too narrow. ci.yml:1348 requires the alternation to list every file the server-DB pytest steps run, which covers the test files and not the sources they assert against. test_postgres_store.py:3409 asserts on a dict produced by api/app.py::_emit. Severity is bounded and now says so: the nightly runs these legs unconditionally, so the blind window is about a day. * backlog: mark the 21 demand-gate items with an owner-ruling closing act These declare Verdict: demand-gate and none carried a machine-readable field, so a dispatch gate saw nothing and a missing field refuses by default. That was the safe answer but not an informative one. Their closing act is an owner ruling: a demand-gated item is finished by deciding to build it or to drop it, not by writing code, and the standing protocol is to pause and ask before building one. Recording owner-ruling makes the gate refuse them for the stated reason rather than for an absent field. The 20 items with no verdict declaration anywhere are deliberately left alone. They need a per-item read, not a derivation, and guessing a closing act for them is the error this whole migration exists to stop. * backlog: classify the last 20 undeclared items, and refuse the one that is contested These 20 declared no verdict anywhere, so nothing was derivable and each needed a read. Ten agents read them in five batches and an independent pass re-read every one and tried to refute the classification. It changed five: 320, 1038, 1072, 1309, 1311. Nineteen are applied as returned. #320 is not. #320 is the only low-confidence result and it moved toward code, which is the one direction that costs something. A wrong code hands an unfinishable item to a builder with a machine-readable blessing on it, which is what a derivation did to #1243 earlier today. The argument for the change is real and is recorded on the item: it mentions ASVS and scorecard zero times against a control of 112 items that mention both, so there is no cell to re-score. That is good enough to doubt the old verdict and not good enough to assert the new one, so the item carries the verdict, no closing act, and the reason. A gate refuses it until someone reads it. Every open item now resolves: 107 close by code, 94 by a vault re-score, 28 by an owner ruling, 4 are blocked, and 6 carry no act and therefore refuse. Verified by asserting the item count, numbering and every status unchanged. * backlog: mark #1321 superseded by #1322 -- I filed a duplicate Two seats filed the same root cause within minutes. #1322 landed on main first via #525; #1321 is mine and arrives by merge, so neither the ledger gate nor either author could see the collision. #1322 is the better record and carries everything #1321 does, including the substring-versus-equality point about the SQLite twin. The lander caught it before the merge was pushed, not me. I filed #1321 after correcting its headline twice and never checked whether the defect was already on main. The banner is deliberately not flipped. Closing is the lander's act per BUILDER.md:253 and :148, so the row says so and the closure is handed over. Until then it is an open duplicate and the row warns a reader who reaches it first. CRLF preserved, zero bare LF, item count and every status asserted unchanged. * backlog: file #1323 -- the crypto-inventory gate has a store-only seam set The required crypto-inventory gate is green while structurally unable to see a first-party TLS seam. All five entries in CRYPTO_SEAM_MODULES are messagefoundry.store.*, and pipeline/alert_sinks.py imports smtplib and config.tls_policy, so no import it makes can trigger a review. The file is correctly inventoried in the doc, so a reader checking the record finds it present. The gate is what cannot see it, and a merge-blocking context blind to a surface reports the same green whether that surface is sound or not. The one-line fix newly implicates at least 26 importers, each needing an inventory row or the gate reds the build. That backlog is the work, which is why this is filed rather than fixed in passing. Stated as a floor: a seat measured 26 by import statement, a broader pattern here finds 28. Scoped so it does not absorb the prose correction on the two ASVS cells, which is a separate authorised act belonging to the tracker. Found by a builder sizing #1164, routed here by the liaison carrying the owner ruling. * backlog: file #1327 and #1328 -- the two items this seat owed Both were deferred to this seat to number and neither can be built quickly, so they go to the ledger rather than staying in a handoff nobody is required to read. #1327: settings models carry extra=ignore on 35 of 38, so a deleted setting passes silently and the test named after it establishes nothing. The row states the hazard and refuses the population claim behind it. One seat said the suite is full of these; another swept and found zero beyond the single instance already fixed. The honest form is that the next deletion will do this silently. The sweeping seat's own blind spots are recorded beside that zero, because a zero from an instrument that cannot see the failing shape is worth less than the shape itself. #1328: nothing maps an ASVS cell to the items it governs, so a re-score cannot be handed to the seat that must flip the banner. Three re-scores in one day produced zero flips. The row also records that re-scores are not one-directional: one moved a cell from pass to partial, so any item closed on that earlier pass must re-open, and a closed banner resting on a withdrawn pass is a control on a false premise. Item count asserted +2 and bare-LF asserted zero BEFORE the write, after an earlier commit today checked afterwards and shipped one bare LF. * backlog: put the #1227 design on its own row so nobody re-derives it A builder decided the shape, refused two alternatives with reasons, and wrote it to a handoff rather than half-building it under a live stop rung. That work is only useful if the next seat finds it, and a handoff is not where anyone looks first. The row now carries the pointer, the chosen shape, and the refusal that most needs recording: the bounded-exception option is out because the item's own premise shows nothing enforces the arrival path, so documenting it harder does not make it true. The deciding argument is on the row too, because it is the part a re-reader would otherwise relitigate. Stash-and-replay would store a message body across a re-auth, creating PHI at rest in a new place with a new deletion question, to save one click. The confirm page's own URL is the stash instead. Structure asserted unchanged and bare-LF asserted zero before the write. * backlog: mark #1327 superseded by #1326 -- my second duplicate this evening A builder and I filed the same defect within minutes. They had deferred it to me to number and then filed it themselves, as the seat whose own commit contained the only instance. Theirs is the better row. The lesson is about the tool I have been trusting. Both numbers came from alloc.ps1, which is doing its job: it guarantees two seats never take the SAME number. It cannot notice that two numbers describe one defect. Atomic allocation prevents a collision, not a duplicate, and I have now hit the second failure mode twice in one evening after citing the first at other people all day. #1326 carries what this row does not: these models also load from TOML and MEFOR_ env, so extra="forbid" turns an unknown config key into a load refusal. That makes it a posture change rather than test hygiene, which is a decision rather than a one-line edit. Banner not flipped; closing is the lander's act. * backlog: reverse my #1327 supersede -- we cross-superseded and neither row survived A builder and I filed one defect as #1326 and #1327. Then each of us marked our own row superseded by the other's: they withdrew #1326 to a stub pointing here, I wrote a supersede note pointing there. For a few minutes both rows pointed at each other and a reader following either went in a circle. Mutual deference produced the duplicate and then nearly destroyed both records of it. That is the sharper failure and it is now recorded on the row, because the duplicate is ordinary and this is not. Theirs is already committed as a withdrawn stub, so this row is the survivor and the supersede note is removed. Lifted from #1326 before it went to a stub, at their request: these models also load from TOML and MEFOR_ env, so extra="forbid" turns an unknown config key into a load refusal rather than a test failure. That makes it a posture change and a decision, not a one-line edit. Structure asserted unchanged, bare-LF asserted zero before the write. * backlog: #1327 is the stub, #1326 the survivor -- the lander's call, complied with The lander holds the closure call and made it. I had reversed my own supersede fifteen minutes earlier and told the fleet the opposite, so this is a compliance, not a concurrence, and the measurement that changed my mind is on the row. #1327 never carried the two named blind spots in the population sweep, including that the direct scan would not have found the bug that prompted it. #1326 does. That makes theirs the fuller body regardless of which was handed over first, which was the lander's stated ground. It also removes a hazard I created. My previous note said THIS ROW SURVIVES A CROSS-SUPERSEDE, which contains the word supersede in a sentence meaning the opposite. Three seats had already read this row by grepping for that word. A marker that reverses its own meaning in context is worse than no marker. The near-miss stays on the row because it is worth more than the duplicate: two seats each marked their own row superseded by the other's, two seconds apart, and briefly left the defect filed nowhere. Mutual deference has no fixed point unless somebody states a direction instead of yielding one. * backlog: #1327 lands live -- matching the lander's landing plan, not overruling it The lander re-armed #524 on the basis that #1327 lands live as its own row, and decided #1326 is in no PR tonight. They measured 10f8ab5; I had pushed 73eb78d after it, which stubbed #1327. With their plan and my pushed state combined, #524 would have merged with #1327 a stub pointing at a row that never lands, and the defect would have been filed nowhere. That is the zero-row outcome three cycles of this had been trying to avoid, and it was one armed auto-merge away. This is compliance with the deciding seat's stated intent rather than a fourth reversal of my own. They hold the closure call by position, being the only seat that sees both branches at merge time. The row now records the whole structure, because it generalises past this item: mutual deference has no fixed point and neither does mutual assertion. Stating a direction only converges if exactly one seat states it, and neither seat can tell whether it is the second. It also records the near-miss that nearly shipped: the deciding seat read SUPERSEDED BY in this row's prose and took it for a status. That is presence-equals-meaning, the exact misreading CLAUDE.md section 11 forbids for banner glyphs, reproduced with a phrase instead of a pictograph. A status marker must not be a word that also appears in narration.
wshallwshall
added a commit
that referenced
this pull request
Aug 22, 2026
…tranded sentence in #1327 (#528) * backlog: close #1317 -- the TLS cipher gate now refuses NULL and anonymous suites Fixed on main by PR 519 and PR 525. Closed here because the LANDER performs the closing act; a builder may not conclude an item closed. VERIFIED BY RUNNING THE SHIPPED CODE, which is the item's own stated method and the bar roles/LANDER.md sets -- a re-read, not a prose match. Against main at 76ee9a7, both functions the item names: validate_tls_ciphers harden_cipher_suites ECDHE-RSA-NULL-SHA REFUSE REFUSE does not encrypt ADH-AES256-GCM-SHA384 REFUSE REFUSE does not authenticate the peer ECDHE-RSA-AES256-GCM-SHA384 ACCEPT ACCEPT POSITIVE CONTROL The positive control is the part that makes this a measurement. Without it a validator that refused everything reads identically to one that discriminates. The item warned that its own heading invites the wrong fix -- tightening the prefix match on _is_forward_secret, which is not the bug. The landed fix did what the item asked instead: it added the missing PAIR of predicates, _is_encrypting and _is_peer_authenticated, and left _is_forward_secret alone. WHY THIS ONE AND NOT THE THREE BESIDE IT. Today merged 31 PRs, filed 13 items and closed none; open went 225 to 238 while the closed count never moved off 94. Seven items were named in merged code-PR titles, but a title mixes "fixes #N" and "files #N" freely: #486 FILED #1306, and #525 FILED #1319 and #1322 while fixing only #1317. Of the rest, #1166, #1179 and #1187 carry Verdict research, whose closing act is a vault re-score and cannot complete here. One genuine candidate, verified, closed. Open 244 to 243, closed 94 to 95, total unchanged at 338 and no item lost. * backlog: delete a stranded sentence in #1327 that invites closing the only live row docs/BACKLOG.md:13466 read, directly beneath the heading: > assigns it). *Until it is flipped this is an open duplicate.* An unmatched paren, and it asserts the row is a duplicate awaiting a flip while its own heading four lines above now reads THIS IS THE LIVE ROW FOR THIS DEFECT. IT WAS NOT INTRODUCED BY THE REVERT. Present at 73eb78d, fa98579 and 3f35be8 alike, with a nonsense-token negative control returning zero and "THIS ROW IS A STUB" as a positive control that goes 1 to 0 across the same span, so the grep discriminates and the heading really did move. Under the old STUB heading the sentence was COHERENT. fa98579 flipped the heading and left it. The sentence never moved; its context moved out from under it. WHY IT HAD TO GO NOW. #1326 is the same finding and is on no origin remote -- ls-remote returns zero heads against a control branch returning one -- so it cannot land and #1327 is the only row this defect has. A leftover sentence reading "until it is flipped this is an open duplicate" is a standing invitation to whoever next runs a reconcile to close the only live row, which is the zero-row outcome six seats spent the evening avoiding, reached by a new route. THE PLACEMENT IS THE WHOLE LESSON. It sat three lines under the row's own rule: "A STATUS MARKER MUST NOT BE A WORD THAT ALSO APPEARS IN NARRATION." The row states the rule and then breaks it. A note describing a trap does not protect a reader already inside it. Found while verifying the merge of PR 524; no pre-merge edit was legal, since the ledger gate keys on the allocating worktree. Amended on main instead. Status unchanged: #1327 stays open, which is the point. * backlog: correct #1317 from CLOSED to PARTIAL -- it declares part of itself open I closed this item two commits ago and that was wrong. Correcting it here rather than force-pushing, so the error and its cause stay in the record. WHAT I MISSED. #1317 runs 105 lines. I read the first 26, verified the two functions its HEADING names by running them against main, and closed it. Further down, the item says of itself: The library half is unchanged and still open: ldap3, hvac and ODBC Driver 18 choose their own suites and no engine object exists to assert on. An item that declares part of itself open must not be closed. Closing it would have deleted the only open record of that half, which is the half-a-record defect 7e names. THE CODE VERIFICATION WAS SOUND AND IS UNCHANGED. Both functions still refuse both named suites with a positive control accepting the good one; the founding claim is genuinely false in the code now. That is why this is PARTIAL and not a revert. The build shipped and the residual is real. THE LESSON, and it is narrower than "read more". A code re-read is NECESSARY AND NOT SUFFICIENT. I applied the bar roles/LANDER.md sets -- verify against the code, not the prose -- and skipped the prose entirely. The item's own scope statement outranks a green measurement of the part it named first. SO TODAY STILL CLOSES ZERO. My earlier "first closure of the day" was wrong. The count is 31 PRs merged, 13 filed, 0 closed, open 225 to 244 -- and this PR leaves open unchanged at 244 rather than moving it to 243. Surfaced because builder-1 mailed about PR 458 conflicting under this very item and quoted a BUILT paragraph I had not read. I went to check their claim and found my own error instead.
wshallwshall
added a commit
that referenced
this pull request
Aug 23, 2026
…d not take #1321 and #1322 record one root cause: the `serverdb` path alternation at `ci.yml:1358` does not list `messagefoundry/api/`, so an api-only change deselects the SQL Server and Postgres legs on the pull request that would catch it. Two seats filed it within minutes. #1322 landed on `main` first via PR #525; #1321 was filed on a branch and arrived by merge, so neither the ledger gate nor either author could see the collision. #1321's own row already declared itself the duplicate and handed the closure over, because `BUILDER.md:253` forbids a filer from closing their own row and `:148` assigns it here. This discharges that hand-over. Verified before flipping rather than relayed: #1322 carries every point #1321 does, including the `tests/test_api.py:587` substring-versus-equality half, and adds a fired-in-practice case (#514 / BACKLOG #1187, `fdd89b49`) and the nightly-arm severity bound. THE GLYPH IS A DELIBERATE CHOICE WITH NO PRECEDENT TO FOLLOW. The live ledger carried no prior close-as-duplicate-of-an-OPEN-item, so the alphabet had to be read rather than copied. The other two closed banners would each assert something false: the check would say the gate hole is fixed, and it is not, it is open at #1322; the no-entry would say an owner declined the work, and none did. The tombstone says this ROW is void, which is the true statement, and the banner text says so in words so no reader has to infer it from a pictograph. parse_items before 341 items / 246 open, after 341 / 245. The status gate reports 577 items across both files, each declaring exactly one status. 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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Work recovered from a cancelled account, plus a repair to main that this branch was the first to hit. Four commits, four layers.
bd37e2333fad32ee2b6dc1besummary_accesscensus assertion is stale on two backends748675a6This PR repairs main
The three database legs were red on arrival and not caused by this branch.
#514 added a
maskedkey to thesummary_accessaudit detail and updated the coalescer, but not the Postgres and SQL Server twins of the census test. It merged green, and every PR afterward that runs those legs inherits the break. This one was first; #516 was second.Why it merged green is the root cause, and it is filed as #1322 in this branch.
ci.yml's serverdb path-gate alternation listsstore/, three pipeline modules,config/, transports, atests/test_(...)list andci.ymlitself — but notmessagefoundry/api/. Verified independently here: zero occurrences ofmessagefoundry/apiin the filter region against a positive control of one formessagefoundry/store. So a change toapi/app.pyselects those legs on neither a pull request nor a push. They were never chosen, rather than skipped past.The stated invariant is one level too narrow.
ci.ymlsays the alternation must list every file the store pytest steps run — the test files. It says nothing about the source files those tests assert against, andtest_postgres_store.pyasserts on a dict produced byapi/app.py::_emit.Not filed as "main skips the legs on push": that is a deliberate billed-minutes decision stated in
ci.yml, and the nightly runs them unconditionally, so the blind window is a day rather than open-ended.The detail worth keeping: the SQLite twin stayed green because it asserts
'"count": 5' in detail— substring containment, which cannot see an added key. The two store twins assert dict equality, which can. The weaker assertion survived the change the stronger ones caught, and the stronger ones were the ones not being run.What #1317 closes, and what it does not
Its residual said the earlier work covered the operator knob and the shipped context builder, did not enumerate every
SSLContextconstruction, and does not reach suite sets chosen insideldap3,hvacor ODBC Driver 18.This closes the first-party enumeration half — the OIDC identity-provider opener, the syslog TLS forwarder on both arms including
tls_verify=False, the Postgres store, and the REST/SOAP/FHIR transports. The library half stays open and the item now says so.The change also records a residual rather than papering over it: on the default store path
Truehands asyncpg the job of building the context, so no context exists in engine code to assert on. Asserting a look-alike built locally would grade an object the connection never uses.Verification
ruff check,ruff format --check,mypy --strictclean; 141 tests across the TLS and SOAP files.3fad32ee, so it validates the TLS commit as written and covers neither the later merge nor the two commits after it. The green CI on the current head is what covers those.Provenance
3fad32eewas built by a workflow child of theasvs-honest-passseat, whose account was cancelled at 16:56Z mid-verification, leaving 680 lines uncommitted in a worktree locked by a dead pid. Themercycare-account-cleanupseat recovered it, replayed it onto a main that had moved two commits underneath, and re-verified against the newer three-propertyharden_cipher_suitesrather than the one it was written against.