Issue 1966, a recovery fix (instruction recovery-fixes-merge-and-tell; merged through the gate).
Live case. At 10:1x UTC the take-in m.3539 was refused three times, on merges made on the forge directly: mesh-catalog #638, mesh-sdk #175 and mesh-tools #64. The bridge answered "the forge says the pull request novox/#0 is not merged". The forge bridge read gitea_api's {"result": ...} wrapper as the pull request itself. Its unit fake answered the bare body, so its tests passed. bridge_tags misread the answer the same way, which is why builds were published unnumbered.
Change.
forgeBody is one shared reader of the wrapped answer, used by ForgeMade and Tags. It refuses an answer that has no result, and a pull request with number 0 as "no number", never as "not merged". Live shape checked read-only on mesh-catalog pull 638 and on mesh-sdk's tag list.
The indexer ends a pending merge at or behind its repository's taken merge (takenAlready) without reading its message. If the ancestry cannot be asked, it reads the merge as before.
A lost hold passes the take-in event's check, so it is said on the bus, not only in the journal.
Quick or thorough. Each commit names both. The removal of the kind is a seat for the forge with typed read verbs, so the bridge stops naming gitea.gitea_api and guessing its shape. It is noted on issue 1966 and not built here.
Tests. Rows in existing tables plus one subtest, no new test function. Each fails without its change. gofmt is clean; go vet (plain and -tags integration) and go test ./... pass in the forge bridge, the indexer and the take-in package.
Undo. Revert this pull request's merge commit.
Reviewed-by: mesh-code-reviewer@shanks at af3b678a92 (two rounds)
Issue 1966, a recovery fix (instruction recovery-fixes-merge-and-tell; merged through the gate).
**Live case.** At 10:1x UTC the take-in m.3539 was refused three times, on merges made on the forge directly: mesh-catalog #638, mesh-sdk #175 and mesh-tools #64. The bridge answered "the forge says the pull request novox/<repo>#0 is not merged". The forge bridge read `gitea_api`'s `{"result": ...}` wrapper as the pull request itself. Its unit fake answered the bare body, so its tests passed. `bridge_tags` misread the answer the same way, which is why builds were published unnumbered.
**Change.**
- `forgeBody` is one shared reader of the wrapped answer, used by `ForgeMade` and `Tags`. It refuses an answer that has no result, and a pull request with number 0 as "no number", never as "not merged". Live shape checked read-only on mesh-catalog pull 638 and on mesh-sdk's tag list.
- The indexer ends a pending merge at or behind its repository's taken merge (`takenAlready`) without reading its message. If the ancestry cannot be asked, it reads the merge as before.
- A lost hold passes the take-in event's check, so it is said on the bus, not only in the journal.
**Quick or thorough.** Each commit names both. The removal of the kind is a seat for the forge with typed read verbs, so the bridge stops naming `gitea.gitea_api` and guessing its shape. It is noted on issue 1966 and not built here.
**Tests.** Rows in existing tables plus one subtest, no new test function. Each fails without its change. `gofmt` is clean; `go vet` (plain and `-tags integration`) and `go test ./...` pass in the forge bridge, the indexer and the take-in package.
**Undo.** Revert this pull request's merge commit.
Reviewed-by: mesh-code-reviewer@shanks at af3b678a92f01e5f3e376101202d5309bd92e8e9 (two rounds)
https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
Both ForgeMade and Tags took the tool's wrapper for the pull request / the tag list, so every forge-made merge read
"#0 is not merged" and bridge_tags failed, leaving builds unnumbered.
Quick fix: unwrap "result" in forgeAPI (the one Go reader of gitea_api).
Thorough fix (chosen, the kind was met twice and hid behind a drifted fake): bridge.API answers what the tool answers,
forgeBody is the one reader of that shape and refuses an answer without a result, naming it; ForgeMade refuses number
0 as "no pull request"; the unit fakes answer the tool's real wrapped shape, with rows for the bare body.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
Quick fix: none smaller than this (the bridge fix alone leaves a covered merge needing the bridge).
Thorough fix (chosen): loadNewest asks takenAlready (already used for group members) before loading the newest merge of
a repository; at or behind taken it is marked Covered, said once in the log, and never read. A merge whose ancestry
cannot be asked is read as before. Test: a row pair behind/ahead of taken with a bridge that cannot answer.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh/check failed (2): integration: mesh-delivery-assigner/cmd/mesh-delivery-assigner.TestAProposalIsAnswer…; and 1 more | af3b678a92f0 on 042b8d1fc160
holdLost builds a pending take-in naming neither WaitsFor nor Unknown, which TakeIn's check refused, so the hold stayed
in the journal and the watchman never saw it.
Quick fix: set Unknown on holdLost's event. Thorough fix (chosen): the check accepts a pending revision that names Lost,
the field made for it; one naming nothing is still refused. Tests: a row accepting Lost, the refusal row kept, and the
lost-hold scenario encodes its said event.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
Deliverynovox/mesh-delivery@af3b678a92f0 — merged since 2026-11-09T10:34:58Z
Source — source.main moved to novox/mesh-delivery@042b8d1fc1. Whether it reached the machines is mesh-delivery-view's, derived from source.main, the wants and the haves.
Transitions
2026-11-09 10:33 (new) → proposed (announced): novox/mesh-delivery#187's head announced
2026-11-09 10:33 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false)
2026-11-09 10:34 ready → merged (merged): on the trunk its modules follow: merged there
The commit's note under refs/notes/mesh-plan keeps every transition of this change up to its merge: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-delivery@af3b678a92f0` — **merged** since 2026-11-09T10:34:58Z
**Source** — source.main moved to novox/mesh-delivery@042b8d1fc160. Whether it reached the machines is `mesh-delivery-view`'s, derived from `source.main`, the wants and the haves.
**Transitions**
- 2026-11-09 10:33 (new) → proposed (announced): novox/mesh-delivery#187's head announced
- 2026-11-09 10:33 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false)
- 2026-11-09 10:34 ready → merged (merged): on the trunk its modules follow: merged there
The commit's note under `refs/notes/mesh-plan` keeps every transition of this change up to its merge: `git log --notes=mesh-plan`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Issue 1966, a recovery fix (instruction recovery-fixes-merge-and-tell; merged through the gate).
Live case. At 10:1x UTC the take-in m.3539 was refused three times, on merges made on the forge directly: mesh-catalog #638, mesh-sdk #175 and mesh-tools #64. The bridge answered "the forge says the pull request novox/#0 is not merged". The forge bridge read
gitea_api's{"result": ...}wrapper as the pull request itself. Its unit fake answered the bare body, so its tests passed.bridge_tagsmisread the answer the same way, which is why builds were published unnumbered.Change.
forgeBodyis one shared reader of the wrapped answer, used byForgeMadeandTags. It refuses an answer that has no result, and a pull request with number 0 as "no number", never as "not merged". Live shape checked read-only on mesh-catalog pull 638 and on mesh-sdk's tag list.takenAlready) without reading its message. If the ancestry cannot be asked, it reads the merge as before.Quick or thorough. Each commit names both. The removal of the kind is a seat for the forge with typed read verbs, so the bridge stops naming
gitea.gitea_apiand guessing its shape. It is noted on issue 1966 and not built here.Tests. Rows in existing tables plus one subtest, no new test function. Each fails without its change.
gofmtis clean;go vet(plain and-tags integration) andgo test ./...pass in the forge bridge, the indexer and the take-in package.Undo. Revert this pull request's merge commit.
Reviewed-by: mesh-code-reviewer@shanks at
af3b678a92(two rounds)https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
Delivery
novox/mesh-delivery@af3b678a92f0— merged since 2026-11-09T10:34:58ZSource — source.main moved to novox/mesh-delivery@042b8d1fc1. Whether it reached the machines is
mesh-delivery-view's, derived fromsource.main, the wants and the haves.Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition of this change up to its merge:git log --notes=mesh-plan.