Skip to content

fix(cli): enrich template cardinality error with per-candidate presence and profile hints - #4825

Merged
wpfleger96 merged 9 commits into
mainfrom
wpfleger/channel-template-cardinality-hints
Aug 27, 2026
Merged

fix(cli): enrich template cardinality error with per-candidate presence and profile hints#4825
wpfleger96 merged 9 commits into
mainfrom
wpfleger/channel-template-cardinality-hints

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Aug 5, 2026

Copy link
Copy Markdown
Member

Problem

buzz channels create --template fails with a bare-pubkey duplicate-instance error when a persona has more than one live instance. When duplicate instances share the same display name and avatar, the error gives the operator no signal to identify which instance is stale.

What changed

crates/buzz-cli/src/commands/channels.rs (boundary) + one visibility line in crates/buzz-cli/src/commands/users.rs (fn presence_subjectpub(crate)), plus a relay behavior change in crates/buzz-relay/src/api/bridge.rs and a supporting test in crates/buzz-pubsub/src/presence.rs.

Relay: presence-lookup failure is now surfaced as a failure

synthesize_presence previously collapsed a Redis get_presence_bulk error into unwrap_or_default() → HTTP 200 [], making a backend outage indistinguishable from an authoritative all-offline snapshot. It now returns Option<Result<Vec<Value>, (StatusCode, Json<Value>)>>: None means the request is not a presence query (fall through), Some(Ok) is a real snapshot (an empty vec is an authoritative all-offline result), and Some(Err) is a backend failure surfaced as a non-2xx response. The event tag-parse and sign paths were converted from .ok()? fall-throughs to explicit Some(Err(...)) for the same reason — a silent fall-through would have reintroduced the fake-empty-success anti-pattern. The function takes pubsub and relay_keypair directly rather than the whole AppState, which keeps the Redis-error seam unit-testable without live infrastructure; its single production caller was updated accordingly, and no other caller consumes synthesize_presence.

Hint fetch architecture

assemble_roster_resolution<F, Fut> — post-fetch stage extracted from build_roster_resolution as an injectable-fetcher async generic. It contains: archive-filter-based duplicate detection, the conditional fetch_hints call, and finalize_roster_resolution delegation. Accepting the fetcher as a closure makes the wiring directly testable without a relay.

build_roster_resolution reduces to: gather slugs → tokio::join!(scan, archive) → delegate with the real fetch_candidate_hints closure.

Zero hint queries on the happy path: assemble_roster_resolution only invokes the fetcher when duplicate live instances exist after archive filtering. Untrusted archive snapshot (Err) conservatively treats all found instances as live.

When duplicates exist, fetch_candidate_hints runs the presence (kind:40902) and profile (kind:0) queries concurrently, bounding each independently through join_bounded_queries: a per-query 3-second timeout maps to Err, so a lookup that completes is never discarded because its sibling hung. On total failure or timeout, bare pubkeys are printed promptly.

Trusted-snapshot boundary — hints_from_results

The relay drops the Redis presence key when an identity goes offline, so the bulk presence snapshot never returns an event for an offline instance — precisely the stale duplicate an operator needs flagged. hints_from_results therefore treats a trusted presence snapshot as a complete snapshot for the requested pubkeys: it seeds all of them offline, then overlays returned statuses.

A response is trusted only when trusted_presence_snapshot validates every array element as the actual snapshot contract: each must parse as a complete signed nostr::Event of the presence-update kind carrying exactly one p tag whose subject is one of the requested pubkeys. Requiring the sole p-tag subject — the exact value build_hint_map later reads via presence_subject — is what stops a mixed-tag event ([["p","<unrequested>"],["p","<requested>"]]) from passing the gate yet overlaying a different subject downstream. Any element that is not such an event — a vacuous object like {"pubkey":"…","content":"online"}, [{}], [null], an event of the wrong kind, one for an unrequested subject, or one carrying more than one p tag — makes presence enrichment untrusted: nothing is seeded offline, so absence is never falsely inferred as offline. A failed, timed-out, or non-array presence response is likewise untrusted. In every untrusted case the successful profile sibling still contributes its hints.

Response-to-map conversion — build_hint_map

Sync production function taking the offline seed plus raw presence/profile event slices. Relay-signed presence events carry the agent pubkey in the p tag (not the event author); build_hint_map calls presence_subject from users.rs (now pub(crate)) to resolve the correct key.

Hint display — format_candidate

Appends [online/offline, profile updated YYYY-MM-DD] (or subset) to each candidate pubkey in the error. profile_updated_at names the field correctly: kind:0 is replaceable state that desktop republishes on rename and profile reconciliation, so created_at reflects the last profile update, not provisioning time. Date formatted via chrono::DateTime::from_timestamp; out-of-range timestamps omit the date. Missing entries fall back to bare pubkeys.

Cardinality rule

apply_cardinality_rule remains pure and relay-free; zero/one/many semantics unchanged.

…oned-at hints

When buzz channels create --template fails with a duplicate-instance
error (persona has N > 1 live instances), the error listed bare pubkeys
only — indistinguishable at a glance for agents whose kind:0 metadata
looks identical (same name, same avatar).

Add best-effort hint decoration to the error output:
- presence status (online/offline) from kind:40902
- provisioned-at date (YYYY-MM-DD) from kind:0 created_at

In the incident that surfaced this defect, the stale instances were
precisely the offline ones, making presence the highest-signal field for
deciding which to archive.

Design constraints preserved:
- apply_cardinality_rule stays pure: hints are fetched by the async
  caller (build_roster_resolution) and passed in, so the rule remains
  directly unit-testable without relay I/O.
- Fail-open: if either lookup fails, the error prints with bare pubkeys
  rather than failing in a new way. Absent hint entries are silently
  omitted per candidate.
- Zero-instance and single-instance paths are unchanged.
- format_candidate is a pure helper, separately testable.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 requested a review from a team as a code owner August 5, 2026 02:58
- Rename provisioned_at -> profile_updated_at: kind:0 is replaceable
  state (desktop republishes on rename/reconciliation), so created_at
  reflects last profile update, not provisioning time. Output changes
  from 'provisioned YYYY-MM-DD' to 'profile updated YYYY-MM-DD'.

- Make hint fetching operationally fail-open: happy path (no duplicate
  live instances after archive filtering) performs zero hint queries.
  When duplicates exist, the two relay lookups (presence + profile) run
  concurrently via tokio::join! and the whole enrichment phase is bounded
  by a 3-second timeout; on expiry the error prints promptly with bare
  pubkeys. scan_managed_agents and fetch_archived_snapshot also run
  concurrently now. Fixes the 'fire-and-forget' comment that was false.

- Extract build_hint_map as a sync production function taking raw
  presence/profile event slices, so it is directly unit-testable without
  a relay. fetch_candidate_hints becomes a thin async wrapper: query
  concurrently, parse, delegate. Five boundary tests added:
    - p-tag beats author for relay-signed presence events
    - presence failure does not suppress profile hints
    - profile failure does not suppress presence hints
    - malformed entries are skipped without panic
    - both failures yield empty map (bare pubkeys in error)
  Mutation check: deleting p-tag selection fails 1 test; gutting
  build_hint_map fails 3 tests.

- Reuse presence_subject from users.rs (pub(crate)) instead of
  re-implementing the same p-tag/author fallback inline.

- Replace hand-rolled Gregorian arithmetic with chrono::DateTime
  (already a direct buzz-cli dep); out-of-range timestamp omits the
  hint rather than computing garbage.

- Fix kind-40902 comment: relay-synthesized on demand, not
  parameterised-replaceable.

333/333 buzz-cli tests pass. fmt + clippy clean.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96 wpfleger96 changed the title fix(cli): enrich template cardinality error with presence and provisioned-at hints fix(cli): enrich template cardinality error with per-candidate presence and profile hints Aug 5, 2026
npub1g8493u0xfsjrvflg4n08ezd7vec99mnwzlv0qgwpr9d7gvjwhuzqx59rhw and others added 2 commits August 5, 2026 00:24
Extract assemble_roster_resolution<F, Fut> from build_roster_resolution
containing duplicate detection, conditional fetch_hints call, and
finalize_roster_resolution delegation.

build_roster_resolution reduces to: gather slugs, tokio::join! scan +
archive, delegate with the real fetch_candidate_hints closure.

Four tokio::test cases against the production function pin both mutations:
- duplicate pair -> fetcher invoked with exactly those pubkeys (mut a fails)
- single instance -> fetcher never called / panic fires (mut b fails)
- trusted archive archives one of a pair -> fetcher suppressed (mut b fails)
- untrusted archive with pair -> fetcher called conservatively (mut a fails)

Mutation (a) replace conditional fetch with HashMap::new(): 2 tests fail
Mutation (b) remove emptiness gate / always fetch: 2 tests fail

337/337 buzz-cli tests pass. fmt + clippy clean.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…late-cardinality-hints

Co-authored-by: Wes <wesbillman@users.noreply.github.com>

Co-authored-by: Carl <9d00794d3df50972eb8b615511783cab12a77a8fd5dd5edd58073ec73b54bd8b@buzz.block.builderlab.xyz>

Signed-off-by: Wes <wesbillman@users.noreply.github.com>

Signed-off-by: Carl <9d00794d3df50972eb8b615511783cab12a77a8fd5dd5edd58073ec73b54bd8b@buzz.block.builderlab.xyz>
Duncan and others added 2 commits August 27, 2026 12:10
…endently

The duplicate-instance error omitted the `offline` label on the stale instance that operators most need flagged: the relay drops the Redis presence key when an identity goes offline, so the bulk snapshot never returns an event for it. Treat a successful, parseable presence response as a complete snapshot for the requested pubkeys — seed all of them `offline`, then overlay returned statuses. A failed, timed-out, or malformed response seeds nothing, so absence is never falsely inferred as offline.

The shared `timeout(join!(..))` also discarded a completed lookup whenever its sibling hung past 3s. Bound each query independently and join the outcomes so a completed presence or profile result survives a hung sibling.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…late-cardinality-hints

* origin/main: (145 commits)
  chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663)
  chore(deps): update dependency vitest to v4.1.11 (#6667)
  chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666)
  chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664)
  fix(projects): allow owners to delete agent projects (#6533)
  Fade expanded video controls on hover (#6926)
  fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822)
  fix(client): resurface hidden DMs from live activity (#6885)
  fix(desktop): keep the draft space when typing right after a mention pick (#6875)
  broker: define the agent-to-broker action contract (#6742)
  fix(desktop): keep project sheets independent from threads (#6901)
  Add gated security reviews (#6816)
  fix(desktop): accent-colored mention badges that count thread mentions (#6900)
  Add Buzz benchmark evaluation layers (#6823)
  fix(desktop): show edited head content in thread panel (#6887)
  fix(desktop-tooltip): increase surface contrast (#6897)
  Deduplicate ACP thread prompt context (#6706)
  Apply access policy when reusing channel agents (#6838)
  feat(sidebar): prioritize unread DMs in overflow navigation (#6842)
  feat(projects): add agent and CLI project-home support (#6590)
  ...

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
… lookup failures

The offline-seeding boundary trusted any presence body that parsed as a JSON array, so `[{}]`, `[null]`, or an event with unreadable `content` was accepted as an authoritative snapshot and seeded every candidate `offline`. Now a snapshot is trusted only when every element is a well-formed presence event (readable subject + string content); any malformed element makes presence enrichment untrusted (seed nothing, keep the profile sibling's hints).

On the relay, `synthesize_presence` converted a `get_presence_bulk` error into an empty HTTP 200, so a Redis outage was indistinguishable from an authoritative all-offline snapshot. It now returns the lookup failure (and internal build/sign faults) as an error response instead of a fake-empty success.

Adds a production-wiring seam test that drives fetch_candidate_hints through a controlled query server where presence completes and profile hangs, plus malformed-element, relay-error, and Redis-connection-failure boundary tests.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The trust boundary accepted any array element with a non-empty subject and
string content, so a vacuous object or a fully-shaped event for an unrequested
subject counted as an authoritative snapshot and re-seeded every requested
candidate offline. trusted_presence_snapshot now parses each element as a
complete signed nostr::Event, requires kind KIND_PRESENCE_UPDATE, and requires
its p-tag subject to be one of the requested pubkeys; any failure makes presence
untrusted while the profile sibling survives.

Narrow synthesize_presence to take (pubsub, relay_keypair) so its Redis-error
seam is unit-testable without live infrastructure; add a CI-runnable relay test
that a failing Redis lookup yields HTTP 500, not a fake-empty 200.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The trust predicate accepted an event when any p tag was requested
(event.tags.public_keys().any(...)), but build_hint_map consumes the first p
tag via presence_subject. A mixed-tag event like
[["p","<unrequested>"],["p","<requested>"]] passed the gate, then overlaid the
unrequested subject and left the requested candidate falsely seeded offline —
the exact false-label class this boundary exists to prevent.

Extract one canonical subject with sole_p_tag_subject, which reads p tags the
same way the consumer does and requires exactly one; require that sole subject
to be requested. Since a trusted event now carries exactly one p-tag subject,
build_hint_map cannot reinterpret it differently.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 merged commit 0808ab4 into main Aug 27, 2026
58 of 62 checks passed
@wpfleger96
wpfleger96 deleted the wpfleger/channel-template-cardinality-hints branch August 27, 2026 18:40
brow added a commit that referenced this pull request Aug 27, 2026
…ifications-pr

* origin/main:
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)
  fix(db): disable heartbeat vacuum truncation (#6898)

Signed-off-by: Tom Brow <tomb@block.xyz>
wpfleger96 pushed a commit that referenced this pull request Aug 27, 2026
…arer-auth

* origin/main:
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
salman1993 added a commit that referenced this pull request Aug 27, 2026
…cp-sessions

* origin/main:
  test(db): use canonical channel roster fixtures (#6819)
  preserve channel description paragraph breaks (#6946)
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)
  fix(db): disable heartbeat vacuum truncation (#6898)
  chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663)
  chore(deps): update dependency vitest to v4.1.11 (#6667)
  chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666)
  chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664)
  fix(projects): allow owners to delete agent projects (#6533)
  Fade expanded video controls on hover (#6926)
  fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822)
  fix(client): resurface hidden DMs from live activity (#6885)
  fix(desktop): keep the draft space when typing right after a mention pick (#6875)
  broker: define the agent-to-broker action contract (#6742)
  fix(desktop): keep project sheets independent from threads (#6901)
  Add gated security reviews (#6816)

Signed-off-by: Salman Mohammed <smohammed@squareup.com>
wpfleger96 pushed a commit that referenced this pull request Aug 27, 2026
…-history

* origin/main:
  feat(desktop): implement 30178 team catalog backend (#5112)
  feat(model-capabilities): humanize Databricks UC model families (#6955)
  feat(agent): discover Databricks Unity Catalog models (#6918)
  test(db): use canonical channel roster fixtures (#6819)
  preserve channel description paragraph breaks (#6946)
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
jrobotham-square added a commit that referenced this pull request Aug 28, 2026
…age-rw

* origin/main: (21 commits)
  fix(desktop): resolve exact typed mentions on space (#6862)
  perf(desktop): restore project context during startup (#6939)
  fix(desktop): lift right auxiliary pane above shared header backdrop (#6966)
  fix(ci): bump Codex CLI to 0.150.1 to unhang security review jobs (#6962)
  feat(desktop): implement 30178 team catalog backend (#5112)
  feat(model-capabilities): humanize Databricks UC model families (#6955)
  feat(agent): discover Databricks Unity Catalog models (#6918)
  test(db): use canonical channel roster fixtures (#6819)
  preserve channel description paragraph breaks (#6946)
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)
  fix(db): disable heartbeat vacuum truncation (#6898)
  chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663)
  chore(deps): update dependency vitest to v4.1.11 (#6667)
  chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666)
  chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664)
  fix(projects): allow owners to delete agent projects (#6533)
  Fade expanded video controls on hover (#6926)
  fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822)
  fix(client): resurface hidden DMs from live activity (#6885)
  ...

Signed-off-by: Joel Robotham <jrobotham@squareup.com>
wpfleger96 pushed a commit that referenced this pull request Aug 28, 2026
…agent-edit

* origin/main:
  feat(auth): add NIP-FI canonical assertion verifier and contracts (#6776)
  fix(desktop): resolve exact typed mentions on space (#6862)
  perf(desktop): restore project context during startup (#6939)
  fix(desktop): lift right auxiliary pane above shared header backdrop (#6966)
  fix(ci): bump Codex CLI to 0.150.1 to unhang security review jobs (#6962)
  feat(desktop): implement 30178 team catalog backend (#5112)
  feat(model-capabilities): humanize Databricks UC model families (#6955)
  feat(agent): discover Databricks Unity Catalog models (#6918)
  test(db): use canonical channel roster fixtures (#6819)
  preserve channel description paragraph breaks (#6946)
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)
  fix(db): disable heartbeat vacuum truncation (#6898)
  chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
wpfleger96 pushed a commit that referenced this pull request Aug 28, 2026
…etection

* origin/main: (24 commits)
  feat(auth): add NIP-FI canonical assertion verifier and contracts (#6776)
  fix(desktop): resolve exact typed mentions on space (#6862)
  perf(desktop): restore project context during startup (#6939)
  fix(desktop): lift right auxiliary pane above shared header backdrop (#6966)
  fix(ci): bump Codex CLI to 0.150.1 to unhang security review jobs (#6962)
  feat(desktop): implement 30178 team catalog backend (#5112)
  feat(model-capabilities): humanize Databricks UC model families (#6955)
  feat(agent): discover Databricks Unity Catalog models (#6918)
  test(db): use canonical channel roster fixtures (#6819)
  preserve channel description paragraph breaks (#6946)
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)
  fix(db): disable heartbeat vacuum truncation (#6898)
  chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663)
  chore(deps): update dependency vitest to v4.1.11 (#6667)
  chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666)
  chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664)
  fix(projects): allow owners to delete agent projects (#6533)
  Fade expanded video controls on hover (#6926)
  fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822)
  ...

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
TheSentinel454 added a commit that referenced this pull request Aug 28, 2026
…edia-layout-migration

* commit 'e76c81968b65b0755b83efdd59dc3375c59ddf40': (159 commits)
  refactor(db): split channel membership store (#6782)
  feat(auth): add NIP-FI canonical assertion verifier and contracts (#6776)
  fix(desktop): resolve exact typed mentions on space (#6862)
  perf(desktop): restore project context during startup (#6939)
  fix(desktop): lift right auxiliary pane above shared header backdrop (#6966)
  fix(ci): bump Codex CLI to 0.150.1 to unhang security review jobs (#6962)
  feat(desktop): implement 30178 team catalog backend (#5112)
  feat(model-capabilities): humanize Databricks UC model families (#6955)
  feat(agent): discover Databricks Unity Catalog models (#6918)
  test(db): use canonical channel roster fixtures (#6819)
  preserve channel description paragraph breaks (#6946)
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)
  fix(db): disable heartbeat vacuum truncation (#6898)
  chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663)
  chore(deps): update dependency vitest to v4.1.11 (#6667)
  chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666)
  chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664)
  fix(projects): allow owners to delete agent projects (#6533)
  Fade expanded video controls on hover (#6926)
  ...

# Conflicts:
#	crates/buzz-deletion/src/lib.rs
#	crates/buzz-media/Cargo.toml
#	crates/buzz-media/src/lib.rs
#	crates/buzz-media/src/storage.rs
wpfleger96 pushed a commit that referenced this pull request Aug 28, 2026
…c-agent-commit-identity

* origin/main:
  feat(desktop): add team sharing to community catalog (#3995)
  Refresh mobile utility surfaces and theme picker (#6944)
  fix(desktop): complete project empty and context states (#6980)
  Fix mobile jump-to-latest flicker (#6807)
  refactor(relay): NIP-98 admin auth with Operator/Moderator roles and NIP-11 discovery (#3777)
  refactor(db): split channel membership store (#6782)
  feat(auth): add NIP-FI canonical assertion verifier and contracts (#6776)
  fix(desktop): resolve exact typed mentions on space (#6862)
  perf(desktop): restore project context during startup (#6939)
  fix(desktop): lift right auxiliary pane above shared header backdrop (#6966)
  fix(ci): bump Codex CLI to 0.150.1 to unhang security review jobs (#6962)
  feat(desktop): implement 30178 team catalog backend (#5112)
  feat(model-capabilities): humanize Databricks UC model families (#6955)
  feat(agent): discover Databricks Unity Catalog models (#6918)
  test(db): use canonical channel roster fixtures (#6819)
  preserve channel description paragraph breaks (#6946)
  fix(cli): enrich template cardinality error with per-candidate presence and profile hints (#4825)
  Fix Codex security review authorization (#6913)
  fix(db): disable heartbeat vacuum truncation (#6898)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants