Release overview
ngit v3 is its biggest release yet. With CI, private repositories, software
releases, and plenty more, ngit, powered by GRASP, is quickly becoming a fully
fledged development solution. It launches in tandem with ngit-grasp v3,
GitWorkshop v4, and the new ngit-ci 0.1 as one coordinated release across the
ngit family of tools. These are the changes that define the release. Read the
full launch story to see how all four releases fit
together; the detailed entries below record every feature, compatibility
change, and fix.
- CI is here: One of the biggest gaps holding projects back from ngit is
now closed. Discover maintainer-selected coordinators, request, trigger, and
stop runs, follow workflows down to individual job logs and trust evidence,
and optionally require a trusted CI result before merging. - Private repositories without surrendering identity: Clone, fetch, push,
and collaborate on GRASP-08 private repositories using scoped Nostr and Git
authentication. The repository remains a signed Nostr identity instead of
becoming an account owned by its server. Basic Buzz support extends clone,
pull-request, and lifecycle-status workflows to Buzz repositories. - Maintainers and repository authority: Introduce an explicit lead,
role history, and non-maintainer moderators, with clearer invitations,
handovers, departures, roster changes, and historical authorization. These
substantial improvements are backwards compatible for existing repositories
and confirmed maintainer relationships. The one narrow breaking change is
that an invited maintainer has no Git-state authority until they accept. That
pending-invitation boundary is the SemVer reason for the v3 major version
bump. - Pull requests that fit real projects: Target non-default branches, build
inferred or explicit pull-request stacks, check out contributor branches on
demand, record issue-resolution provenance, and merge with stronger safety
checks. - Software releases without the platform: Think GitHub Releases without
GitHub, made resilient through Blossom replication. Publish signed NIP-82
applications, releases, and assets with Zapstore-compatible metadata, then
update ngit itself from its verified releases.
Additional ngit highlights
- Credential protection: Move
nsecand bunker credentials out of Git
config by default and into the OS credential store, with an ngit-specific,
user-only file as fallback. This reflects a changed threat model: coding
agents and other tools now routinely read Git config, making inadvertent
disclosure much more likely. - Nsite and container publishing: Publish nsites and OCI container images
through Nostr and Blossom. - Accounts and automation: Add portable local and remote signer selection,
deliberate credential export, global JSON output and repository selection,
plus a versioned agent skill installer and upgrader. - Repository addresses: Resolve path-scoped NIP-AD mappings from memorable
bare domains, with NIP-65 relay discovery when the repository announcement is
not already cached. - Everyday Git compatibility: Support guarded force pushes with
--force-with-lease, raw object IDs in refspecs, no-op pushes, Git-managed
tracking refs, and installed remote helpers for additional server protocols. - Safer upgrades and recovery: Update from exact signed NIP-82 releases,
preserve staged, unstaged, and untracked work through merges, and provide an
actionable merge recipe when synchronized refs have diverged. - Private-network access: Connect opportunistically to
.onionrelays and
clone URLs through Tor, and optionally trust host-installed certificate
authorities for private or development infrastructure.
Added
- Bare-domain
nostr://repository URLs can resolve path-scoped NIP-AD
mappings, including protocol and SSH-key prefixes. NIP-AD mappings and the
existing hint-lessnostr://<npub>/<identifier>form now bootstrap missing
repository announcements through the author's NIP-65 write relays. ngit release publishcan derive its version and source commit from one
exact Git tag, so tagged CI builds need no positional arguments. Schema-1
manifests accept Zapstore-compatible local APKrelease_source; ngit
extracts package/version, SDK, certificate, and ABI metadata from the stable
Blossom snapshot and rejects conflicts with declarative assertions.- Schema-1 release manifests can declare Zapstore-style application metadata.
Tracked local icons and screenshots publish through Blossom, while existing
HTTP(S) image URLs remain direct references and are never downloaded. - Add
ngit update,ngit update --check, and exact-version selection backed
by ngit's signed repository state and trusted NIP-82 release assets. Only
receipted standalone Unix installations are replaced automatically; Nix,
Cargo, and unreceipted installations receive non-mutating guidance. The
canonical website installer template now shares this update path. - Release manifests can set
release_notes: CHANGELOG.mdto publish the
matching Keep a Changelog version section. Missing, duplicate, and empty
sections fail rather than falling back to the complete changelog. - Add
ngit nsite publish <DIRECTORY>for publishing an already-built static
site as a root or named NIP-5A manifest. The command snapshots files
deterministically, confirms every unique blob on every selected Blossom
server with batched BUD-11 authorization, then signs and publishes the
manifest with local or remote signers. Blossom servers may be supplied
explicitly, read with site metadata, fallback routing, and relay hints from
nsyte's.nsite/config.json, or discovered from the account's kind-10063
server list. - Add
ngit container publish <OCI_LAYOUT>for publishing verified OCI image
layouts through Blossom and repository-bound Nostr kind-30624 state. The
command uploads every reachable blob, preserves existing remote tags by
default, publishes through repository relays, and supports NIP-42 and
structured CI output. - Private repositories via GRASP-08: discover private repositories through
encrypted kind-10318 relay lists, then clone, fetch, push, and collaborate
using NIP-42 relay authentication and repository-scoped NIP-98 Git HTTP
credentials. Private repository events stay on repository relays instead of
leaking through indexers, fallback relays, or account relay fanout. Copied
repository URLs can also be classified as private from GRASP-08 NIP-11
metadata before discovery begins. - Basic Buzz support: clone Buzz repositories, view pull requests and their
lifecycle status, and push new or updated pull requests and status changes
through authenticated Buzz relay and Git transport. Normal branch and tag
pushes are not supported, and Buzz pull-request comments cannot be viewed or
published because Buzz uses kind 1 while ngit uses NIP-22 kind 1111. - Stored accounts can be selected for one ngit command with global
--signer <npub|alias|profile-name>, or for one Git command with
git -c nostr.signer=<account>, without changing the configured login.
ngit account login <account>reactivates retained credentials and
--aliasadds a portable signer name. An explicit selector that is missing,
invalid, or ambiguous fails closed. - Add portable one-shot and export paths for both signer types:
--nsec-filereads a local key, while interoperable--nbunksecand
--nbunksec-filereuse an established NIP-46 session. Secret-file targets
must be small regular files and, on Unix, use mode0400or0600.
ngit account export-keysreturns the selected account's npub plusnsec
for a local signer ornbunksecfor a remote signer. --jsonis now a global option for all ngit commands. Machine-readable
results are written to stdout only after command completion, diagnostics and
progress stay on stderr, and mutating commands return useful event IDs and
metadata. JSON output cannot be combined with interactive mode.- Pull requests can target a non-default branch with
git push -o target-branch=<branch>orngit send --target-branch <branch>. Root PR events expose the target as an indexedbtag, and listing, viewing, updating, merging, and applied-status detection honor the immutable target; omitting the option retains default-branch behavior.ngit mergeresolves an explicit target against the latest Nostr repository state, fetching the target commit without mutating tracking refs, so a stale local clone cannot merge onto old target history. - Pull requests automatically select the unique most-advanced tip of the author's other open or draft PRs when it is in the new proposal's history and ahead of the target branch. Existing children follow later authorized parent updates after they are rebased, while stale children and ambiguous unrelated parents fail closed.
git push -o base=<commit|branch|event>andngit send --base <commit|branch|event>override inference for that publication; PR roots select their latest authorized update, specific PR-update events select their historical commit, and unique event-ID prefixes are accepted. Repeat an explicit historical base on later child updates to keep that deliberate pin instead of following the open parent lineage. - Issue-resolution status events now identify the triggering commit and, when
attribution is unambiguous, the proposal and merge commit that caused the
status change. - Add a multi-stage
Containerfilefor building a minimal Alpine-based ngit image, plus a CI smoke test that builds the image and runsngit --version. - Add an opt-in
native-tls-rootsbuild feature that trusts certificate authorities installed on the host alongside WebPKI roots, enabling WSS connections to relays and GRASP servers using private, corporate, or development CAs. ngit repo --jsonnow exposesselected_maintainer,confirmed_maintainers,invited_maintainers,lead_maintainer, and the directionalmaintainer_edgesalongside the backward-compatible fullmaintainersset.- Add
ngit skill install,upgrade, andstatuscommands plus local and global reminder opt-outs for repository-managed coding-agent guidance. Installs add a slim versionedSKILL.mdand eight on-demandreference/*.mdguides to both Codex and Claude discovery paths, including static-site publication withngit nsite, and append a compact pointer only to existingAGENTS.mdorCLAUDE.mdfiles that do not already mention ngit. Installs and upgrades preserve supported symlinks, protect modified or newer copies unless forced, and create distinct guidance-only commits; non-maintainers are advised to push the commit as a pull request, whilengit initleaves installation as an explicit suggested follow-up. - Expand
--repo-relay-onlyto all ngit commands that publish nostr events. - Git server clone URLs can use installed
git-remote-<scheme>helpers for listing, fetching, and pushing. Installing a helper is treated as consent for signed repository announcements to invoke it, subject to Git's protocol policy; recursivenostr, internalfd, and GRASP-reservedws/wssschemes are not delegated. - Global
--repo <REMOTE|NADDR|NOSTR-URL>argument selects the target repository for repo-scoped operations (send,issue,pr,repo,sync, and every other command that resolves a repository coordinate). Available at any command position (ngit --repo upstream issue create,ngit issue --repo upstream create,ngit issue create --repo upstream). Value is first matched against configured remote names, then parsed as an naddr, then as anostr://URL. - Repo-coordinate resolution now prints a
target repository: <naddr> (source: ...)diagnostic when publishing repo-scoped events, so an incorrect target is visible before the event is signed. - Opportunistic Tor support for
.onionrelays and clone URLs. ngit uses an available SOCKS5 proxy fromNGIT_TOR_PROXYor probes the common system Tor and Tor Browser ports (127.0.0.1:9050and127.0.0.1:9150). Unavailable onion entries fail immediately so they do not delay clearnet alternatives. Seedocs/onion.md.
Changed
- The bundled coding-agent skill is rewritten around the guides published at
https://ngit.dev.SKILL.mdkeeps the rules agents get wrong and points each
task slice at its bundled reference, the matching guide, and
ngit <command> --help; the reference files drop material the guides cover
better, describe capabilities instead of choosing workflow policy, and gain a
rule to preserve choices the user or repository already made. The skill now
states that it documents ngit v3 and how to install or update an older host,
mergesreference/repo-settings.mdintoreference/repositories.md, and
corrects thesetup-ngitaction tag (v3), the issue auto-resolution
keywords, and the canonicalngit pr mergebehaviour. ngit skill installandupgradedelete reference files that a later ngit
no longer bundles, resolving the same canonical symlinks as bundled files,
and stage the deletion in the guidance commit. A lingering retired file is
reconciled even when the skill version is already current.- The top-level
ngit mergecommand is now a compatibility alias for the
canonicalngit pr mergecommand. Both spellings create the same local
no-ff merge on the PR's declared target (or repository default), share
conflict handling and options, and refuse closed or already-applied PRs
before changing Git state. Preparing the local merge no longer requires a
maintainer identity; the later Git push enforces repository authority and
publishes the Nostr applied status. Ungated JSON keeps the PRid,entity,
andaction(mergedorconflicted) while omitting the unrequested CI
projection and unpublished event. - JSON command-result envelopes now use top-level
command_status: "ok" | "error"instead of the ambiguousstatusfield orokboolean. Nested
fields continue to describe domain results, so a successfulci status
query can paircommand_status: "ok"withci.conclusion: "failure".
Release, nsite, and container publication envelopes advance to format
version 2 for this breaking schema change. ngit mergenow accepts--require-ci-trust, matchingngit pr merge.- Repository hosting flags now distinguish grasp-derived infrastructure from
deliberate additions.ngit inituses--additional-relayand
--additional-clone;ngit repo editreplaces whole-list
--grasp-server,--relay,--clone, and--hashtagflags with repeatable
--add-*and--remove-*actions. Repository identifiers can no longer be
changed throughrepo editbecause doing so creates a new coordinate. - GRASP service URLs may include a non-root base path. Repository announcements,
nostr://relay hints, Git push/fetch, and explicit GRASP-06 PR endpoints preserve the configured path. ngit account whoaminow inventories every usable stored account from local, global, and system Git config,credentials.json, and the OS credential store; groups identities by npub; lists distinct local-key and remote-signer connections with their npub/alias selectors and connection-specific scope badges; and prints shared guidance for one-shot ngit or Git use, local/global activation, alias creation, and removing a local override.ngit account listis a visible alias, whilengit account login <account>adds a concise activation form alongside the existing--signerspelling. A non-secret account index makes newly stored OS-keyring identities discoverable without relying on platform-specific keyring enumeration.- Logged-in accounts answer NIP-42 authentication challenges from repository
relays, and from the account's inbox or outbox relays while publishing, but
decline challenges from unrelated relays such as indexers and fallbacks. - Now that ngit-grasp repository-relay synchronization has matured, repository state and collaboration events are fetched exclusively from relays declared by the repository. This makes repository relays the authoritative collaboration view and allows grasp servers to provide moderation in the future without filtered events being restored from user relays. URL hints, fallback relays, and announcement indexers are limited to repository announcements; user relays are limited to profile metadata, relay lists, and user GRASP lists. Publishing still fans out to relevant user relays unless
--repo-relay-onlyornostr.repo-relay-onlyis set. - Open and draft PRs from other users are no longer downloaded as branches by
default.ngit pr checkoutopts an individual PR back in with its familiar
shorthand-suffixed branch name and keeps later fetch, pull, and push tracking
intact. The new default applies to fresh and existing clones; existing clones
keep previously downloaded tracking refs untilgit fetch --prune. Set
nostr.auto-pr-branches=trueexplicitly to restore automatic downloading. - Global event caching now falls back to an in-memory cache when persistent storage is unavailable, allowing ngit to operate in restricted or sandboxed environments. Set
NGIT_CACHE_DIRto select a writable persistent cache directory; repository caches remain strict and require the Git common directory to be writable. - Upgrade NostrDevKit dependencies from the
0.45.0-alpha.2prerelease series to the stable0.45.0release. - Align maintainer terminology with gitworkshop: every pubkey in the directional maintainer graph has maintainer rights, while "invited" identifies an unreciprocated relationship rather than reduced authority. Reciprocal graph membership confirms co-maintainers, and a unique highest-listed confirmed maintainer is shown as a coordination-only lead.
ngit repodescribes whom each confirmed maintainer lists and, when informative, who invited an unconfirmed maintainer. Acceptance defaults now reciprocate the sole confirmed maintainer or unique lead, retaining the selected maintainer only for ambiguous non-interactive cases. - Accepting co-maintainership (
ngit repo accept, and the auto-accept that runs during push and status commands) no longer rewritesnostr.repoor theoriginremote to point at the accepter's own coordinate. The coordinate a repository resolves from is the root of trust; re-rooting it on your own announcement — which always lists you as a maintainer — would make it impossible to observe the inviter removing you later. Resolution stays on the inviter's coordinate, so a removal surfaces naturally (for example as a refused push); onlyngit repo edit/ngit initchange the resolved coordinate deliberately. Whenoriginis not anostr://remote,ngit repo acceptnow prints how to add a nostr remote for the inviter's coordinate instead of claiming pushes will work. ngit account loginandngit account createnow store local keys and typed remote-signer records in the OS credential store, falling back to a user-only file store in ngit's data directory when no OS store is available. With credential-backed storage, Git config keeps only public account-selection and alias metadata. Plaintext values in Git config remain supported indefinitely and are never rewritten by reads; runngit account loginto move an existing plaintext login into a credential store. Thenostr.secret-storageGit config item,NGIT_SECRET_STORAGEenv var, or--secret-storageflag onngit account login/createselectsauto(OS store then file store),file, orgit-config(plaintext, the previous behaviour); when a secret cannot be stored, login fails with guidance instead of silently saving plaintext.ngit account logoutkeeps the stored secret — the store may hold the only copy of the key — and prints thengit account forget-keys <entry>command that removes it;ngit account logout --forgetdoes both in one step. Generated keys are no longer printed byngit account create; usengit account export-keyswhen the secret needs to be revealed deliberately. Seedocs/credential-storage.md.- Repository-coordinate resolution now follows a documented priority: (1) explicit
--repo, (2)git config nostr.repo, (3) current branch's tracked upstream if anostr://remote, (4)originif anostr://remote, (5) sole remaining distinct nostr coordinate. When multiple distinct coordinates remain and none of the earlier rules match, ngit errors by default and prints how to disambiguate, instead of silently picking one at HashMap-iteration random. Interactive selection is offered only when-iis explicitly requested and uses deterministic (name-sorted) ordering. ngit initfirst-time use now recreates the existingoriginas a remote named after the git server's domain (e.g.githubfor github.com; deeper hosts drop the public suffix and dash-join the rest, likegit-fiatjaffor git.fiatjaf.com; name collisions get a numeric suffix) instead of discarding its URL entirely whenoriginis repointed at the nostr URL. Branch upstreams and existing tracking refs are untouched.ngit initnow pushes git data and publishes the repository state in-process instead of spawninggit push/ngit syncsubprocesses. The state is cached and broadcast only after a Git server accepts the data and a relay accepts the event. A failure while pushing or establishing the state is a real error that reports that the announcement was already published and names the follow-up command (git push -u origin <branch>orngit sync), instead of being downgraded to a warning.- Repeat
ngit initon a repository that already has a state event republishes it as a fresh event (identical refs, new event id) through the same acceptance-gated flow as a push, so relays and git servers newly added to the announcement receive the repository state immediately instead of only on the nextgit push. Establishing the state during init now requires at least one reachable git server. ngit initon a repository with a pre-existing reachableoriginnow recordsrefs/remotes/origin/*remote-tracking refs for the branches covered by the published state, so ahead/behind reporting against the repointed nostroriginis correct before the first push.- The remote helper no longer creates, updates or deletes
refs/remotes/<remote>/*tracking refs itself: git's own transport layer performs those updates for every ref the helper reportsok, mapping the destination throughremote.<name>.fetch. The helper's only remaining local ref bookkeeping is deleting legacy tag tracking refs written by old ngit versions. Two behaviours deliberately change to match vanilla git semantics: a remote whoseremote.<name>.fetchrefspec has been narrowed no longer receives tracking refs for pushed branches outside that refspec, andgit push <nostr-url>with no configured remote now completes without the helper's previous bookkeeping error, writing no tracking refs.
Removed
- Remove the former
ngit pr merge --squashoption so the canonical command
and its top-level alias expose one identical no-ff merge interface. Use Git's
manual squash workflow when a single-parent result is desired.
Fixed
- Invalid repository self-
deferrole records are now author-scoped health
problems instead of repository-wide failures. A strictly later signed
self-role restores current authority without rewriting the malformed
history; otherwise only that signer is gated and can explicitly repair the
record withngit repo edit --repair-self-deferor accept a fresh role. A
numeric repair now merges a same-role successor into one multi-interval
record so the signed replacement does not retain a duplicate-role conflict. - Unparseable repository role records, including records with non-hex
subjects, no longer abort repository parsing or read as a signed departure.
They remain byte-for-byte on the source announcement but never grant
authority or enter copied history. An author whose own role records are
exclusively malformed is blocked —
excluded from authority as an author-scoped health problem that gates only
that signer's announcement edits (no automated repair exists yet) — while
the repository stays readable through the selected coordinate instead of
suggesting a follow-lead redirect that cannot resolve. A valid numeric
departure still departs, and still redirects, even beside malformed tags. - The
nostr://Git remote helper now accepts raw commit object IDs on the
source side of push refspecs, matching Git's normal behavior for commands
such asgit push origin <oid>:refs/heads/recovery. Branch and lightweight
tag destinations are recorded in repository state without requiring a
temporary local ref. - Blossom presence checks and upload responses now treat a server's MIME type
as representation metadata rather than blob identity. Content-addressed bytes
can be reused by files with different media types, so an existing empty blob
labelledinode/x-emptyno longer blocks publication of an empty CSS file;
hash, size, and descriptor URL validation remain strict. ngit updatenow recognizes signed prerelease events whose NIP-82 channel
matches the first SemVer prerelease identifier (rc.7usesrc,beta.2
usesbeta) for both automatic and exact-version updates, while continuing
to accept backward-compatiblemain-channel events. Stable releases remain
restricted tomain, and pending-release warnings now use the correct
singular or plural verb.- Remote-signer login no longer overwrites a different NIP-46 connection for
the same npub before failing to persist Git config. A bare npub retains its
default signer, while--alias <name>stores and selects additional signer
sessions independently for login, push, andaccount export-keys.
Credential-store alias values remain raw npubs so older ngit versions can
continue reading them. If only one session remains and it was stored for an
alias, either the npub or alias can still select it; multiple sessions with
no default require an alias. ngit account export-keys --secretprints only the selected account's nsec
or nbunksec, providing a direct human-readable export without a JSON wrapper
or interactive menu.ngit repo editnow refreshes the maintainer's current announcement from
every NIP-65 write relay before deriving a replacement. A cold cache can no
longer let a stale indexer announcement make a targeted--add-*edit drop
existing grasp servers, relays, clone URLs, hashtags, or membership data;
incomplete account-relay reads fail before anything is signed or published.ngit mergenow preserves staged, unstaged, and untracked changes across
the merge commit and branch switch, including the staged/unstaged boundary.
If those changes conflict with the merged target, ngit rolls the merge back
and restores the original branch and worktree. Linked worktrees are
supported when the command runs from the worktree that owns the target
branch; if another worktree owns it, ngit refuses before changing either
worktree or the shared target ref.ngit init --defaultsno longer drops grasp hosting when--additional-clone
or--additional-relayis supplied. Additional infrastructure supplements the
account's preferred grasp servers (or ngit's defaults) instead of silently
replacing them, so the announcement keeps its grasp-derived clone URLs and
relays. Publishing without any grasp server is now stated explicitly with an
empty value,--grasp-server "", which also requires an additional relay and
clone URL of its own. Republishing an announcement that genuinely declares no
grasp servers no longer grafts the defaults onto it.ngit initandngit repo editrefuse to publish a repository announcement
whose relay or clone field would be empty, naming--grasp-server,
--additional-relayand--additional-cloneas the ways to supply the
missing half. The check runs on the resolved announcement before anything is
signed, so it covers every flag shape and repository configuration, including
a metadata-only edit of an announcement that already lacks hosting — which
previously republished the unusable announcement and then failed while
pushing git data with no git server to connect to.- Prevent TLS client initialization from panicking after Reqwest 0.13 selected
AWS-LC alongside rust-nostr's Ring provider. Reqwest remains
provider-neutral while ngit explicitly installs Ring before constructing
either its application or library HTTP clients. - Repository-conditioned global signer identities, aliases, and secret-storage
policies selected through GitincludeIfgitdirconditions are now
resolved in repository context. Conditional signers work for
ngit account whoamiand ordinary signed commands, while
nostr.secret-storageand legacynostr.credential-storesettings control
login storage and plaintext hints. - ngit now honours
GIT_CONFIG_GLOBAL,GIT_CONFIG_SYSTEMandGIT_CONFIG_NOSYSTEMwhen resolving Git config scopes outside the repository. libgit2 does not apply these to the config ngit opens, so a login stored, read or removed with--global(or any global-scope read, such as the secret-storage policy) previously went to~/.gitconfigregardless of the redirect, silently overwriting the real global login of anyone who sandboxes ngit with the documented variables. - Keep
--jsonoutput parseable by sending relay-fetch summaries such asno updatesandupdates: ...to stderr instead of stdout. git push --force-with-leasenow works withnostr://remotes: matching leases authorize guarded non-fast-forward updates, while stale leases reject the push before a conflicting repository state can be published.git pushof apr/branch alongside branch or tag changes now reports the proposal ref as failed when no git server accepts the pushed git data, matching the branch/tag refs. Proposal events are broadcast to the repository and user relays only after a git server accepts the pushed data; previously the helper told gitokand recorded arefs/remotes/<remote>/pr/<branch>tracking ref in that total-failure case even though the proposal events were never broadcast.git pushto a nostr remote now treats a git server that already has every requested change as a successful push target, so no-op pushes (re-pushing a tag that is already present, deleting an already-deleted branch) succeed instead of erroring, including undernostr.nostate. Git data is no longer pushed to a GRASP server whose paired relay did not accept the staged state event, and the locally cached repository state is only updated after a git server accepted the pushed data and a relay accepted the state event, so a failed or interrupted push leaves the previous state authoritative instead of caching an unpublished replacement.- Git pushes that encounter libgit2's internal protocol assertion now retry
through the system Git transport, allowing affected SSH servers such as
tangled.org to accept the same push. - Make ahead/behind commit walks topology-complete so merged side-branch commits with equal timestamps are not skipped, restoring every issue-resolution status generated from a multi-merge push.
- Fast successive repository and proposal updates now order reliably despite Nostr's whole-second timestamps. Repository state, announcements, and statuses use bounded nonce grinding with a timestamp fallback; GRASP now honors the lower-event-ID tie-break for same-second state replacements. Patch revisions and pull-request upgrades or updates remain strictly ordered by timestamp.
ngit initfirst-time use no longer fails to publish git data for existingoriginrefs that were never downloaded locally (e.g. tags after a--no-tagsor single-branch clone): the missing objects are now fetched from the origin by ref name before the repository state is signed, and refs whose objects still cannot be obtained are excluded from the state event instead of being advertised as oids no git server holds.- Fix silent mis-targeting of repo-scoped events (
ngit send,ngit issue create,ngit pr *,ngit repo, etc.) when a repository had multiplenostr://remotes with disagreeing coordinates. Previously the resolver iterated aHashMapand picked the first key it saw, ignorednostr.repo, and printed no diagnostic; the effect was that PRs and issues could be published against the wrong repository coordinate without warning. See the documented priority under "Changed". ngit mergerun with no argument on a barepr/<name>branch now falls back to matching the branch's tip commit against the published tips of open and draft PRs when the logged-in-author mapping finds zero or several candidates. A maintainer merging a contributor's PR from a hand-made bare branch, and a logged-out user merging their own, now resolve the PR instead of erroring; when several open PRs share both the branch name and the tip commit, merge still asks for an explicit event-id.