Repository navigation
Prerequisite batch: relay tx (#257), Idempotency-Key bound (#258), RFC promotions (#249), governance files (#242), vendor-neutral AI gates (#252) - #259
Merged
Conversation
…EOWNERS (refs #242) - SECURITY.md: report through GitHub private vulnerability reporting (Security tab, "Report a vulnerability"); latest release supported per docs/compatibility.md; acknowledge within 3 days, fix or coordinated disclosure within 90 days, disclosure as a GitHub Security Advisory. - CODE_OF_CONDUCT.md: Contributor Covenant 2.1, enforcement contact is the private report form or the maintainer; no email address. - CONTRIBUTING.md: dev_doctor -> test suite -> RFC process -> PR checklist, including the deterministic and AI gates CI runs. - .github/CODEOWNERS: catch-all first, then impl/lnpl/, rfcs/, .github/, all @choiyounggi (prerequisite for code-owner review in #244). - impl/tests/test_governance_files.py: the four files exist; CODEOWNERS covers the required paths, names only the maintainer, points at existing paths and keeps the catch-all first; parser rejects a missing or non-@ owner and skips comments and blank lines. - impl/tests/mutation_check.py: TREE_CONTENTS copies the three new root files so the mutation harness tree matches what the tests read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qyv3iqsmLFDfctQ6MVdQ8T
`lnpl relay` drained the outbox outside any transaction, so on lnpl-postgres (SELECT ... FOR UPDATE SKIP LOCKED) the row locks ended with the statement and two relays could publish the same row. Both relay loops now route each batch (drain -> publish/POST -> ack) through a new `_relay_batch` helper: begin() before the drain, commit() after the batch, rollback() when an exception escapes it (ack failure, unexpected publisher error, KeyboardInterrupt). A row whose publish fails stays un-acked and the batch still commits. `_relay_drain_once*`, the rc-2 drain-contract guard and `outbox drain`/`outbox ack` are unchanged. docs/backends.md §3 states the delivery guarantee: exactly-once per batch on row-locking drivers, at-least-once across unwrapped drains and end to end, unchanged on sqlite; the batch stays unbounded (follow-up). Tests: RelayBatchTransactionTest (9) pins the call order per batch. Full suite 5404 -> 5413, OK (skipped=1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NgjbKPS63sN3T9ANagQdy1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Th13jVHptQQ1mCLah7XBay
…asing a consume claim (#258) An Idempotency-Key longer than 255 header bytes now gets 400 idempotency-key-too-long (problem+json, M23) in _do_post, before any repository driver is opened, on every backend. Before this, a key of about 4000 characters overflowed lnpl-postgres's btree index on lnpl_idempotency (workflow_id, key) and the request failed with an unhandled 500. The new code is added to wsgi._TITLES and lexer.RESERVED_PROBLEM_CODES. On POST /-/events/<slug>, when the workflow raises an exception that run_workflow does not catch, the open workflow transaction is now rolled back before idempotency_release. The key is free at once and the failed run's partial writes are not committed with the release. If the rollback itself fails, the claim is kept until its TTL. docs/serving.md documents the bound and the D6 release order. The old test that accepted a 4096-character key now asserts the 400 instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHmmWQ9U1LKAF5fPdc7DUH
…ase on consume failure (refs #258) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Th13jVHptQQ1mCLah7XBay # Conflicts: # CHANGELOG.md
Promote the 16 CHANGELOG-cited Draft RFCs after per-RFC implementation evidence (CHANGELOG line + citing test module, no baseline failures; RFC-0053 phase-2 sites present). Status lines read `**Accepted** (RFC-00NN, 2026-10-22)`. - Status sections of 13 RFCs keep their Draft sentence and gain a dated resolution note (R-t249-6). - Updates lines of 0051–0054 name the predecessor updater per RFC-0007 §2.2 rule 5 (nine `(+RFC-NNNN)` notes, R-t249-7/7a). - README.md / README.ko.md: RFC count lines (62 Accepted, 2 Draft) and the 0049–0064 table cells drop the Draft marker. - kb/cloud/cloud-event-delivery.md: RFC-0061 cited as Accepted. Back-links in target RFCs follow in t249a2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvGUpaxKn39SLd9eVtUNge
scripts/rfc_lint.py now scans CHANGELOG.md for `RFC-NNNN` citations, including the slash form `RFC-NNNN/NNNN`. A cited RFC must have a document under rfcs/ (else a §3 finding) and be Accepted or Superseded (else a §2.1 finding naming the number and status). A missing CHANGELOG.md is its own §2.1 finding; a malformed rfcs/ file name stays a §3 finding through main(). 18 new tests (47 in test_rfc_lint). Full suite 5438 -> 5456 OK (skipped=1). One CHANGELOG bullet under Unreleased / Changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FvKDLFWETgQF2SpyPYffgz
…s (refs #249) RFC-0049–RFC-0063 are Accepted, so every target their `- Updates:` lines name now carries the matching back-links, inserted only: - 35 `- Updated-by: RFC-NNNN (§…)` lines at the end of the Status list of 15 target RFCs (0001 0002 0003 0012 0014 0015 0016 0025 0027 0028 0030 0038 0040 0044 0057) - 51 `> 갱신됨: RFC-NNNN` pointers at the head of each named section, appended to any existing pointer block (rule 5), including the RFC-0044 §Open Questions 1 pointer RFC-0051 promised at promotion The (updater, target) pairs re-derived from the merged Updates lines match: 35 pairs, none missing. rfc_lint unchanged (Accepted 62, Draft 2, Superseded 1, no problems); full suite 5438 OK (skipped=1) before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X1JyTUkjyMucgjR46y7hRR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Th13jVHptQQ1mCLah7XBay
The reusable _ai-gate.yml takes a `runner` input (`claude-code` by default, unchanged; or `generic-http`). scripts/ai_gate_http_runner.py (stdlib only) sends the gate prompt and the PR diff to any OpenAI-compatible /chat/completions endpoint and writes the same verdict JSON that scripts/ai_gate_verdict.py checks. Every failure is a named `error: ...` line, the key is masked on every output channel, and a key containing whitespace is rejected before the request. Each AI gate gets an advisory `<gate>-generic-http` caller job that runs only when the repo variable AI_GATE_HTTP_BASE_URL is set, and skips like the Anthropic gates when the AI_GATE_HTTP_API_KEY secret is missing. The four existing jobs are byte-identical. docs/CI-GATES.md documents both runners and how to register generic-http. Tests: impl/tests/test_ai_gate_http_runner.py (30, against a local fake server) and impl/tests/test_ai_gate_workflow.py (44, which run the changed run: blocks under bash -e and LANG=C.UTF-8 and pin the wiring). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DNNdNyUJL7gGcojHmehAYi
… (refs #252) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Th13jVHptQQ1mCLah7XBay
This was referenced Oct 22, 2026
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.
Prerequisite batch from the 2026-10-11 enterprise audit (#255): five issues that must land before the v0.9.0 release (#245) and branch-protection reviews (#244). Run as one orchestration (7 tasks, each planned, reviewed and audited separately).
Closes #257
Closes #258
Closes #249
Closes #242
Closes #252
What changed
lnpl relayruns each batch (drain → publish/POST → ack) inside one driver transaction. A row whose publish fails stays un-acked; the batch still commits the rows that were delivered. Rollback on ack failure, unexpected error or interrupt.docs/backends.md§3 states the delivery guarantee.Idempotency-Keylonger than 255 bytes is refused with 400idempotency-key-too-longbefore any driver is opened. On a failed event consume, the open transaction is rolled back beforeidempotency_release; if that rollback fails, the claim is kept until TTL so no partial write is committed.Updated-by:back-links in the 15 target RFCs.scripts/rfc_lint.pynow fails whenCHANGELOG.mdcites an RFC that is not Accepted or Superseded. README counts updated.SECURITY.md(GitHub private vulnerability reporting, now enabled),CONTRIBUTING.md,CODE_OF_CONDUCT.md(Contributor Covenant 2.1),.github/CODEOWNERS._ai-gate.ymlgains arunnerinput; each AI gate gets ageneric-httpjob (OpenAI-compatible chat completions) that runs only whenvars.AI_GATE_HTTP_BASE_URLis set. The claude-code path is unchanged.Verification
Ran 5530 tests/OK (skipped=1)(5394 at the base commit).rfc_lint,gen_plugin_references --check,check_version_sync,check_doc_snippets: rc 0.ruff check impl/lnpl scripts: clean.Known gaps (filed as follow-up issues)
prose-factcheckdoes not see the PR title/body;docs/CI-GATES.mdroster row forrfc_lintdoes not mention the new CHANGELOG rule.idis not length-bounded; aDriverErrorfromidempotency_releasestill escapes as a raw 500; the OpenAPIIdempotency-Keyheader has nomaxLength; relay batches are unbounded.rfc_lintdoes not check §2.2 back-links; §2.2 rule-7 consolidation candidates.🤖 Generated with Claude Code
https://claude.ai/code/session_01Th13jVHptQQ1mCLah7XBay