postNoCodeChangeComment — deterministic post-and-mark service #305
Labels
No labels
batch
bug
chore
documentation
enhancement
pi-loop
ready
resume
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
david/pi-loop#305
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Add the one deterministic function that posts the no-code-change comment through the platform comment client and writes the marker artifact — at most once, with a fatal failure path (ADR-021 §5 + §6).
Background
Depends on: #303, #304
This service is the middle layer between the comment-body builder and the marker artifact module: check marker → build body → post → write marker → report. It is called only from runPipeline's no-code-change short-circuit (wired in a later step) but is designed, compiled, and unit-tested here in isolation with a fake client.
The platform
IssueCommentClient(output of themakeCommentClientseam) already applies bounded retries (3 attempts, backoff) for transient errors, so this function must NOT add its own retry loop. Any post failure here must throw so the pipeline catch turns it intoerror.json+ a non-zero exit — and the marker must not be written on failure, keeping resume's "no marker = not posted" invariant truthful.Implementation Details
Create
src/writeback/services/postNoCodeChangeComment.ts:Logic:
readNoCodeChangeCommentSignal(runDir)returns an artifact → return{ posted: false }(already commented — resume fast-path; do not call the client).buildNoCodeChangeCommentBody(artifact).client.addComment(ref, body)— transient errors already retried by the client.writeNoCodeChangeCommentSignal(runDir, { issueKey: <issue key from ref>, postedAt: now() }), then return{ posted: true, postedAt }.nowdefaults tonew Date().toISOString();logInfodefaults to a no-op.All fs/time access goes through the seams so the service stays deterministic and unit-testable.
Acceptance Criteria
src/writeback/services/postNoCodeChangeComment.tsexports the typed function above.issueKeyandpostedAt; returns{ posted: true, postedAt }.{ posted: false }; client NOT called; marker untouched.nowseam drivespostedAt.src/writeback/services/postNoCodeChangeComment.test.ts(fakeIssueCommentClient+ temp run dir) cover posted / marker-skip / throw.Test Plan
npx vitest run src/writeback/services/postNoCodeChangeComment.test.tsnpm run lintclean.pi-loop opened and merged a pull request for this issue: #315