Files
buzz/desktop/src/features/projects/useHealProjectHomeRepositories.ts
thomaspblock de188ebf06 feat(projects): add agent and CLI project-home support (#6590)
## Summary
- inject bounded project-home identity and repository context into
managed agent sessions
- add project-aware CLI flows for creating projects, repositories,
issues, and related channels
- match project homes through the existing relay query surface, then
filter channel metadata client-side

This is Part 1 of the channel-first Projects stack. Part 2 contains
project creation and model foundations.

## Testing
- `cargo fmt --all -- --check`
- `cargo clippy -p buzz-cli -p buzz-acp --all-targets -- -D warnings`
- `cargo test -p buzz-cli -p buzz-acp` — 1,184 tests passed, 1 doc test
ignored
- full pre-push gate passed

## Post-Deploy Monitoring & Validation
- validate project-home agent context and project-aware CLI commands
against a staging relay
- healthy signals: project context matches the active channel, explicit
repo coordinates remain stable, and normal channels receive no project
block
- failure signals: cross-channel project context, duplicate project
creation, or commands targeting an unrelated repository; mitigate by
reverting this PR

---------

Signed-off-by: Thomas Petersen <thomasp@squareup.com>
Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
2026-08-26 12:09:06 -07:00

63 lines
2.2 KiB
TypeScript

import * as React from "react";
import { homeRepositoriesToBind } from "@/features/projects/lib/projectCollection";
import type { Project } from "@/features/projects/projectModels";
import { useAttachProjectRepositoryMutation } from "@/features/projects/useAttachProjectRepository";
import { relayClient } from "@/shared/api/relayClient";
import { KIND_PROJECT_ANNOUNCEMENT } from "@/shared/constants/kinds";
import { normalizePubkey } from "@/shared/lib/pubkey";
/**
* When the signed-in user owns this project, bind absorbed home-channel
* repositories onto the `kind:30621` so Overview, other clients, and NIP-MP
* agree. Agents can announce a repo with `--channel` but cannot edit the
* owner's project event.
*/
export function useHealProjectHomeRepositories(
project: Project,
identityPubkey?: string,
) {
const attachMutation = useAttachProjectRepositoryMutation();
const attemptedRef = React.useRef(new Set<string>());
const mutateAsync = attachMutation.mutateAsync;
React.useEffect(() => {
if (!identityPubkey) return;
if (normalizePubkey(identityPubkey) !== normalizePubkey(project.owner)) {
return;
}
if (project.repositories.length === 0) return;
let cancelled = false;
void (async () => {
const liveHeads = await relayClient.fetchEvents({
authors: [project.owner],
kinds: [KIND_PROJECT_ANNOUNCEMENT],
limit: 1,
"#d": [project.dtag],
});
if (cancelled) return;
const liveHead = liveHeads[0];
if (!liveHead) return;
const signedAddresses = liveHead.tags
.filter((tag) => tag[0] === "a" && tag[1])
.map((tag) => tag[1] as string);
const pending = homeRepositoriesToBind(project, signedAddresses);
for (const repository of pending) {
const key = `${project.projectAddress}:${repository.repoAddress}`;
if (attemptedRef.current.has(key)) continue;
attemptedRef.current.add(key);
try {
await mutateAsync({ project, repository });
} catch {
// Already bound, raced, or not owner-writable this session.
}
}
})();
return () => {
cancelled = true;
};
}, [identityPubkey, mutateAsync, project]);
}