You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
packages/gittensory-miner/lib/event-ledger.js (#2290) is a general, append-only local event ledger with an open type vocabulary — any string type plus a JSON payload (event-ledger.js:41-46,76-90). manage-status.js already shows the established pattern for layering a specific, typed event on top of it: it defines its own event type constant (MANAGE_PR_UPDATE_EVENT = "manage_pr_update", manage-status.js:5) plus a payload normalizer (normalizeManageUpdatePayload, manage-status.js:28-39) and a thin writer (recordManagePollSnapshot in manage-poll.js:114-160) that calls the ledger's generic appendEvent. There is no equivalent for PR outcomes yet — pr_outcome does not appear anywhere under packages/gittensory-miner/.
Note this is a different layer from the server-side pr_outcome concept: src/review/outcomes-wire.ts:285 (recordPrOutcome) already writes pr_outcome rows to the HOSTED backend's D1 review_audit/audit_events tables on a pull_request.closed webhook. That's the gittensory server recording ground truth for every contributor's PRs, from the App's own webhook stream. This issue is the miner's own local record of the outcomes of its own PRs, written to the miner's local SQLite via event-ledger.js — same concept name, different codebase layer, no shared code (a laptop-mode miner may not have a webhook relay at all). Pick a distinct local constant name (e.g. MINER_PR_OUTCOME_EVENT) to avoid implying it's the same code path as recordPrOutcome.
Deliverables
packages/gittensory-miner/lib/pr-outcome.js exporting an event-type constant (e.g. MINER_PR_OUTCOME_EVENT = "pr_outcome") and a payload normalizer, mirroring manage-status.js's MANAGE_PR_UPDATE_EVENT pattern
recordPrOutcomeSnapshot(input, options) — a thin writer taking { repoFullName, prNumber, decision: "merged"|"closed", closedAt } plus an optional reason bucket (reuse REJECTION_REASONS from rejection-templates.js:19 when the PR was closed-not-merged, so this writer and the rejection-state-machine sibling issue share one vocabulary), that calls eventLedger.appendEvent(...) — same dependency-injection shape as recordManagePollSnapshot (manage-poll.js:114-160) so it's unit-testable without a real ledger file
readPrOutcomes(eventLedger, filter) — read-side helper mirroring indexLatestManageUpdates (manage-status.js:42-53) to reconstruct current-outcome-per-PR from the ledger's append-only event stream
Unit tests in test/unit/miner-pr-outcome.test.ts for the writer (both merged and closed decisions), the payload normalizer's validation, and the read-side reduction over a multi-event history
CLAUDE.md/README note distinguishing this from the server-side recordPrOutcome (src/review/outcomes-wire.ts:285) so future contributors don't conflate the two
References
packages/gittensory-miner/lib/event-ledger.js:41-46,76-90,148-166 (normalizeEventType, serializePayload, appendEvent — the generic primitive this builds on)
packages/gittensory-miner/lib/manage-status.js:4-6,28-53 (MANAGE_PR_UPDATE_EVENT, normalizeManageUpdatePayload, indexLatestManageUpdates — the pattern to mirror)
packages/gittensory-miner/lib/manage-poll.js:114-160 (recordManagePollSnapshot — the thin-writer-over-ledger shape to mirror)
packages/gittensory-miner/lib/event-ledger.js(#2290) is a general, append-only local event ledger with an open type vocabulary — any stringtypeplus a JSONpayload(event-ledger.js:41-46,76-90).manage-status.jsalready shows the established pattern for layering a specific, typed event on top of it: it defines its own event type constant (MANAGE_PR_UPDATE_EVENT = "manage_pr_update", manage-status.js:5) plus a payload normalizer (normalizeManageUpdatePayload, manage-status.js:28-39) and a thin writer (recordManagePollSnapshotin manage-poll.js:114-160) that calls the ledger's genericappendEvent. There is no equivalent for PR outcomes yet —pr_outcomedoes not appear anywhere underpackages/gittensory-miner/.Note this is a different layer from the server-side
pr_outcomeconcept:src/review/outcomes-wire.ts:285(recordPrOutcome) already writespr_outcomerows to the HOSTED backend's D1review_audit/audit_eventstables on apull_request.closedwebhook. That's the gittensory server recording ground truth for every contributor's PRs, from the App's own webhook stream. This issue is the miner's own local record of the outcomes of its own PRs, written to the miner's local SQLite viaevent-ledger.js— same concept name, different codebase layer, no shared code (a laptop-mode miner may not have a webhook relay at all). Pick a distinct local constant name (e.g.MINER_PR_OUTCOME_EVENT) to avoid implying it's the same code path asrecordPrOutcome.Deliverables
packages/gittensory-miner/lib/pr-outcome.jsexporting an event-type constant (e.g.MINER_PR_OUTCOME_EVENT = "pr_outcome") and a payload normalizer, mirroringmanage-status.js'sMANAGE_PR_UPDATE_EVENTpatternrecordPrOutcomeSnapshot(input, options)— a thin writer taking{ repoFullName, prNumber, decision: "merged"|"closed", closedAt }plus an optional reason bucket (reuseREJECTION_REASONSfromrejection-templates.js:19when the PR was closed-not-merged, so this writer and the rejection-state-machine sibling issue share one vocabulary), that callseventLedger.appendEvent(...)— same dependency-injection shape asrecordManagePollSnapshot(manage-poll.js:114-160) so it's unit-testable without a real ledger filereadPrOutcomes(eventLedger, filter)— read-side helper mirroringindexLatestManageUpdates(manage-status.js:42-53) to reconstruct current-outcome-per-PR from the ledger's append-only event streamtest/unit/miner-pr-outcome.test.tsfor the writer (bothmergedandcloseddecisions), the payload normalizer's validation, and the read-side reduction over a multi-event historyCLAUDE.md/README note distinguishing this from the server-siderecordPrOutcome(src/review/outcomes-wire.ts:285) so future contributors don't conflate the twoReferences
packages/gittensory-miner/lib/event-ledger.js:41-46,76-90,148-166(normalizeEventType,serializePayload,appendEvent— the generic primitive this builds on)packages/gittensory-miner/lib/manage-status.js:4-6,28-53(MANAGE_PR_UPDATE_EVENT,normalizeManageUpdatePayload,indexLatestManageUpdates— the pattern to mirror)packages/gittensory-miner/lib/manage-poll.js:114-160(recordManagePollSnapshot— the thin-writer-over-ledger shape to mirror)packages/gittensory-miner/lib/rejection-templates.js:19(REJECTION_REASONS— reusable reason-bucket vocabulary)src/review/outcomes-wire.ts:285-344(recordPrOutcome— the server-side namesake this must NOT be confused with)