1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! End-to-end coverage of `git push` to a `nostr://` remote, organised
//! as one scenario per submodule.
//!
//! Each scenario builds its own [`test_harness::Harness`], captures a
//! per-scenario snapshot via a [`tokio::sync::OnceCell`]-backed
//! `#[fixture]`, and then asserts on that snapshot from one
//! `#[rstest] #[tokio::test]` per property. The OnceCell is module-local
//! so scenarios never share state, and `cargo test --test git_push_state
//! <scenario>::<case>` still exercises the full setup path for just the
//! case you care about.
//!
//! ## Layout
//!
//! - [`fresh_repo`] — pushing a brand-new repo for the first time (manual
//! kind-30617 announcement, no `ngit init`). Asserts that the single pushed
//! `main` branch lands on both grasps + the vanilla relay, the state event
//! names it as HEAD, and both clone surfaces reproduce it.
//! - [`add_branch`] — builds on [`fresh_repo`]'s end state, then pushes an
//! additional `vnext` branch. Asserts `main` is preserved, HEAD stays on
//! `main`, the new branch shows up everywhere, and the state event now lists
//! both refs.
//! - [`delete_branch`] — builds on [`add_branch`]'s end state, then issues `git
//! push origin --delete vnext`. Asserts `main` is preserved, HEAD stays on
//! `main`, the deleted branch disappears from every observable surface
//! (publisher remote-tracking, both clones, both grasps, state event), and
//! the local branch + its upstream config are not collateral damage.
//! - [`push_tag`] — pushes a lightweight *and* an annotated tag through the
//! nostr remote. Asserts (negatively) that no `refs/remotes/origin/<tag>` ref
//! is written on the publisher or a fresh nostr clone — git's remote-tracking
//! *branch* namespace, where a stray tag entry shows up as a remote branch in
//! `git branch -r` — and (positively) that both tags reach the publisher's
//! `refs/tags/*`, both grasps' bare repos, a nostr clone, and the kind-30618
//! state event (annotated tags as a tag object with the `^{}` peel;
//! lightweight tags as a bare commit oid). Regression cover for `fix: tag
//! pushed via nostr remote appeared as remote branch`.
//! - [`clone_interact_tag`] — a fresh user clones over `nostr://` *after* the
//! tags were pushed, then exercises them end-to-end: `git fetch --tags
//! --prune` keeps both tags, `git cat-file -t` confirms the annotated tag is
//! a real tag object that peels to the seed commit, and a maintainer pushes a
//! brand-new tag back from the fresh checkout (reaching the state event and
//! the grasp's bare repo without a stray remote-tracking ref). The tight pin
//! on the annotated tag's `^{}` peel lives in [`push_tag`]; this scenario
//! covers the cloner-consumes-and-pushes side.
//! - [`invited_push_requires_acceptance`] — a user listed in another
//! maintainer's announcement, but without their own kind-30617 yet, clones
//! the repo and attempts to push a normal branch. Asserts the push is
//! rejected until explicit acceptance and publishes neither an announcement
//! nor state.
//! - [`maintainers_yaml`] — changing and pushing the legacy coordinate file
//! advances Git state without replacing the signed maintainer roster.
//! - [`vanilla_server_noop`] — a no-op push against a vanilla (non-GRASP) git
//! server whose bare repo can be mutated out-of-band: a tag already pushed to
//! the server directly produces an empty per-server plan, and the nostr push
//! must succeed and still publish the updated state event.
//! - [`force_with_lease`] — two maintainer checkouts diverge on `main`; a stale
//! guarded force push is rejected without changing kind-30618 state, then
//! succeeds after fetch advances the lease to the published winner.
//!
//! When adding a new scenario file, declare it as another `mod` below
//! and follow the same fixture / case shape so failures stay
//! pinpoint-named in `cargo test` output.