feat(prd-1): implement M7 - entry point + mode handler integration

- Tag mode routes to fetchForgejoData vs fetchGitHubData based on platform
- createInitialComment auto-detects platform for Forgejo spinner/URL format
- update-comment-link uses updateForgejoCommentBody + Forgejo PR compare URL
- update-with-branch uses platform-aware branch/job-run link formatting
- Agent mode needed NO changes (token in run.ts, rest uses Octokit REST)
- 11 new integration tests in test/m7-integration.test.ts
- 785 tests pass, typecheck clean, format clean

Progress: 78% complete (7/9 milestones) - M3, M8, M9 remaining

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vlad MocanuandClaude Opus 4.6 committed 2026-02-25 18:22:27 +02:00
1 parent ce1459fe7f
commit 88401255be
7 files changed
+315 -29

No files matched your search

+30 -8
View File
@@ -7,6 +7,11 @@ import {
updateCommentBody,
type CommentUpdateInput,
} from "../github/operations/comment-logic";
import {
updateForgejoCommentBody,
createForgejoPrCompareUrl,
} from "../forgejo/comment-logic";
import { detectPlatform } from "../platform/detector";
import {
parseGitHubContext,
isPullRequestReviewCommentEvent,
@@ -46,6 +51,7 @@ export async function updateCommentLink(
} = params;
const { owner, repo } = context.repository;
const platform = detectPlatform();
const serverUrl = GITHUB_SERVER_URL;
const jobUrl = `${serverUrl}/${owner}/${repo}/actions/runs/${process.env.GITHUB_RUN_ID}`;
@@ -145,13 +151,26 @@ export async function updateCommentLink(
(comparison.files && comparison.files.length > 0)
) {
const entityType = context.isPR ? "PR" : "Issue";
const prTitle = encodeURIComponent(
`${entityType} #${context.entityNumber}: Changes from Claude`,
);
const prBody = encodeURIComponent(
`This PR addresses ${entityType.toLowerCase()} #${context.entityNumber}\n\nGenerated with [Claude Code](https://claude.ai/code)`,
);
const prUrl = `${serverUrl}/${owner}/${repo}/compare/${baseBranch}...${claudeBranch}?quick_pull=1&title=${prTitle}&body=${prBody}`;
const titleText = `${entityType} #${context.entityNumber}: Changes from Claude`;
const bodyText = `This PR addresses ${entityType.toLowerCase()} #${context.entityNumber}\n\nGenerated with [Claude Code](https://claude.ai/code)`;
let prUrl: string;
if (platform === "forgejo") {
// Forgejo doesn't support quick_pull=1
prUrl = createForgejoPrCompareUrl(
serverUrl,
owner,
repo,
baseBranch,
claudeBranch,
titleText,
bodyText,
);
} else {
const prTitle = encodeURIComponent(titleText);
const prBody = encodeURIComponent(bodyText);
prUrl = `${serverUrl}/${owner}/${repo}/compare/${baseBranch}...${claudeBranch}?quick_pull=1&title=${prTitle}&body=${prBody}`;
}
prLink = `\n[Create a PR](${prUrl})`;
}
} catch (error) {
@@ -217,7 +236,10 @@ export async function updateCommentLink(
errorDetails,
};
const updatedBody = updateCommentBody(commentInput);
const updatedBody =
platform === "forgejo"
? updateForgejoCommentBody(commentInput)
: updateCommentBody(commentInput);
try {
await updateClaudeComment(octokit.rest, {
@@ -7,6 +7,11 @@
import { appendFileSync } from "fs";
import { createJobRunLink, createCommentBody } from "./common";
import {
createForgejoJobRunLink,
createForgejoCommentBody,
} from "../../../forgejo/comment-logic";
import { detectPlatform } from "../../../platform/detector";
import {
isPullRequestReviewCommentEvent,
isPullRequestEvent,
@@ -21,9 +26,16 @@ export async function createInitialComment(
context: ParsedGitHubContext,
) {
const { owner, repo } = context.repository;
const platform = detectPlatform();
const jobRunLink = createJobRunLink(owner, repo, context.runId);
const initialBody = createCommentBody(jobRunLink);
const jobRunLink =
platform === "forgejo"
? createForgejoJobRunLink(owner, repo, context.runId)
: createJobRunLink(owner, repo, context.runId);
const initialBody =
platform === "forgejo"
? createForgejoCommentBody(jobRunLink)
: createCommentBody(jobRunLink);
try {
let response;
@@ -10,6 +10,12 @@ import {
createBranchLink,
createCommentBody,
} from "./common";
import {
createForgejoJobRunLink,
createForgejoBranchLink,
createForgejoCommentBody,
} from "../../../forgejo/comment-logic";
import { detectPlatform } from "../../../platform/detector";
import { type Octokits } from "../../api/client";
import {
isPullRequestReviewCommentEvent,
@@ -24,16 +30,26 @@ export async function updateTrackingComment(
branch?: string,
) {
const { owner, repo } = context.repository;
const platform = detectPlatform();
const jobRunLink = createJobRunLink(owner, repo, context.runId);
const jobRunLink =
platform === "forgejo"
? createForgejoJobRunLink(owner, repo, context.runId)
: createJobRunLink(owner, repo, context.runId);
// Add branch link for issues (not PRs)
let branchLink = "";
if (branch && !context.isPR) {
branchLink = createBranchLink(owner, repo, branch);
branchLink =
platform === "forgejo"
? createForgejoBranchLink(owner, repo, branch)
: createBranchLink(owner, repo, branch);
}
const updatedBody = createCommentBody(jobRunLink, branchLink);
const updatedBody =
platform === "forgejo"
? createForgejoCommentBody(jobRunLink, branchLink)
: createCommentBody(jobRunLink, branchLink);
// Update the existing comment with the branch link
try {
+11 -3
View File
@@ -12,6 +12,8 @@ import {
extractOriginalTitle,
extractOriginalBody,
} from "../../github/data/fetcher";
import { fetchForgejoData } from "../../forgejo/data/fetcher";
import { detectPlatform } from "../../platform/detector";
import { createPrompt } from "../../create-prompt";
import { isEntityContext } from "../../github/context";
import type { GitHubContext } from "../../github/context";
@@ -41,7 +43,7 @@ export async function prepareTagMode({
// Check if actor is human
await checkHumanActor(octokit.rest, context);
// Create initial tracking comment
// Create initial tracking comment (auto-detects platform for spinner/URL format)
const commentData = await createInitialComment(octokit.rest, context);
const commentId = commentData.id;
@@ -49,7 +51,9 @@ export async function prepareTagMode({
const originalTitle = extractOriginalTitle(context);
const originalBody = extractOriginalBody(context);
const githubData = await fetchGitHubData({
// Platform-aware data fetching: Forgejo uses REST-only, GitHub uses GraphQL
const platform = detectPlatform();
const fetchParams = {
octokits: octokit,
repository: `${context.repository.owner}/${context.repository.repo}`,
prNumber: context.entityNumber.toString(),
@@ -60,7 +64,11 @@ export async function prepareTagMode({
originalBody,
includeCommentsByActor: context.inputs.includeCommentsByActor,
excludeCommentsByActor: context.inputs.excludeCommentsByActor,
});
};
const githubData =
platform === "forgejo"
? await fetchForgejoData(fetchParams)
: await fetchGitHubData(fetchParams);
// Setup branch
const branchInfo = await setupBranch(octokit, githubData, context);