agent/php/Pipeline/PRMeta.php
Snider e83c3d811d feat(pipeline): add MetaReader contract + Forgejo-backed implementation
Introduce a pipeline metadata surface that enforces "no body content
ever reaches pipeline decisions". MetaReader is an interface with four
methods (getPRMeta, getEpicMeta, getIssueState, getCommentReactions),
each returning a readonly DTO carrying only structural fields —
state, mergeability, SHAs, branches, reaction counts, child linkage.
ForgejoMetaReader projects raw Forgejo API payloads into these DTOs
and drops body/description/review text before the caller can see it.

Unit test mocks rich Forgejo payloads containing body, description,
review_text, and comment_body, then asserts the DTO toArray output
never exposes those keys — the regression fence for the RFC rule.

Downstream callers (ScanForWork, ManagePullRequest) still use the
raw ForgejoService today; that refactor lands under Mantis #90.

Closes tasks.lthn.sh/view.php?id=89

Co-authored-by: Codex <noreply@openai.com>
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-23 18:09:54 +01:00

45 lines
1.3 KiB
PHP

<?php
// SPDX-License-Identifier: EUPL-1.2
declare(strict_types=1);
namespace Core\Mod\Agentic\Pipeline;
final readonly class PRMeta
{
/**
* @param array<int, array{name: string, conclusion: string|null, status: string|null}> $checkStatuses
*/
public function __construct(
public string $state,
public string $mergeability,
public ?string $headSha,
public ?string $headDate,
public ?string $baseBranch,
public ?string $headBranch,
public array $checkStatuses,
public int $reviewThreadsTotal,
public int $reviewThreadsResolved,
public bool $hasEyesReaction,
) {}
/**
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
'state' => $this->state,
'mergeability' => $this->mergeability,
'head_sha' => $this->headSha,
'head_date' => $this->headDate,
'base_branch' => $this->baseBranch,
'head_branch' => $this->headBranch,
'check_statuses' => $this->checkStatuses,
'review_threads_total' => $this->reviewThreadsTotal,
'review_threads_resolved' => $this->reviewThreadsResolved,
'has_eyes_reaction' => $this->hasEyesReaction,
];
}
}