mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-14 06:47:28 +00:00
Add AgentGit M1: agent-native git layer over a Forgejo backend
AgentGit is a thin, DID-gated source-collaboration layer over a backend forge (default Forgejo at git.profullstack.com, BBS-members-only) — not a new git host. M1 implements the contract and engines: - forge/adapter.ts: ForgeAdapter interface (only forge-specific surface) - forge/forgejo.ts: ForgejoAdapter over Forgejo/Gitea REST v1 (injectable fetch, typed errors), incl. ensureUser for member provisioning - access.ts: gateAccess DID membership gate (owner/role/visibility) - merge-policy.ts: evaluateMergePolicy pure engine (reviews, reputation floor, checks, escrow, merge method, agent-merge toggle) - service.ts: AgentGitService ties gate + policy to the adapter; refuses policy-failing merges; provisionMember hook for AgentBBS - schemas: logicsrc-repo + logicsrc-pull-request, registered in @logicsrc/validators with fixtures - docs/agentgit.md spec; plugin wired into root build (default/disabled) 27 vitest tests pass; full monorepo build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
14fe9d608f
commit
bf046ae280
25 changed files with 1776 additions and 3 deletions
67
plugins/agentgit/src/merge-policy.ts
Normal file
67
plugins/agentgit/src/merge-policy.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import type { MergeMethod, MergePolicy, PullRequest } from "./domain.js";
|
||||
|
||||
export interface MergeEvaluationInput {
|
||||
policy: MergePolicy;
|
||||
pr: Pick<PullRequest, "status" | "reviews" | "checks">;
|
||||
method: MergeMethod;
|
||||
actor: { did: string; isAgent: boolean };
|
||||
/** Whether a funded escrow exists for the linked task; resolved by the caller. */
|
||||
escrowFunded?: boolean;
|
||||
}
|
||||
|
||||
export interface MergeEvaluation {
|
||||
satisfied: boolean;
|
||||
reasons: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure evaluation of a repo's merge policy against a pull request. Returns
|
||||
* whether the PR may be merged and, if not, every blocking reason. The actual
|
||||
* merge (pr.merge) refuses unless `satisfied` is true.
|
||||
*/
|
||||
export function evaluateMergePolicy(input: MergeEvaluationInput): MergeEvaluation {
|
||||
const { policy, pr, method, actor, escrowFunded } = input;
|
||||
const reasons: string[] = [];
|
||||
|
||||
if (pr.status === "merged" || pr.status === "closed") {
|
||||
reasons.push(`pull request is ${pr.status}`);
|
||||
return { satisfied: false, reasons };
|
||||
}
|
||||
if (pr.status === "draft") {
|
||||
reasons.push("pull request is a draft");
|
||||
}
|
||||
|
||||
if (pr.reviews.some((review) => review.decision === "request_changes")) {
|
||||
reasons.push("changes requested by a reviewer");
|
||||
}
|
||||
|
||||
const qualifyingApprovals = pr.reviews.filter(
|
||||
(review) => review.decision === "approve" && (review.reputation ?? 0) >= policy.reviewer_reputation_min
|
||||
).length;
|
||||
if (qualifyingApprovals < policy.min_reviews) {
|
||||
reasons.push(
|
||||
`needs ${policy.min_reviews} approving review(s) at reputation >= ${policy.reviewer_reputation_min}, has ${qualifyingApprovals}`
|
||||
);
|
||||
}
|
||||
|
||||
if (policy.require_passing_checks) {
|
||||
const notPassing = pr.checks.filter((check) => check.status !== "passing");
|
||||
if (notPassing.length > 0) {
|
||||
reasons.push(`checks not passing: ${notPassing.map((check) => `${check.name}(${check.status})`).join(", ")}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (policy.escrow_required && escrowFunded !== true) {
|
||||
reasons.push("escrow required but not funded");
|
||||
}
|
||||
|
||||
if (!policy.allowed_merge_methods.includes(method)) {
|
||||
reasons.push(`merge method "${method}" not allowed (allowed: ${policy.allowed_merge_methods.join(", ")})`);
|
||||
}
|
||||
|
||||
if (actor.isAgent && !policy.allow_agent_merge) {
|
||||
reasons.push("agent merges are disabled for this repo");
|
||||
}
|
||||
|
||||
return { satisfied: reasons.length === 0, reasons };
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue