Skip to content

feat: give every job a temporal repository contract, including what changed since the last run #366

Open

Description

@HugoXK

Written-by: Fledge Platform Product
Owner-card: #366 was filed by HugoXK on 2026-11-12; this rewrite keeps its scope and its priority:high label.

Problem

Fledge's preflight records the target branch and base SHA, and the prompt warns about a stale fork, but the agent and the reviewer do not get a structured view of what changed since the previous job. SWE-Time: Benchmarking Temporal Repository Understanding shows that temporal repository understanding is a distinct capability, not a side effect of reading the current tree (arXiv:2611.12083). Without it, Fledge can re-fix an issue that was fixed last night, review a stale PR, or miss a new commit that invalidates the plan.

This card is slice 1 of four

Slice 1 records the delta between this job's base and the previous job's base, puts one line of it in the goal, and shows it on the job page. It does not let the delta change any decision yet.

Current at 6287aa5394f31f9ce47183eca0cb10cd3c58eac2:

  • preflight() (src/jobs/service.ts:892) makes one getBranch read and returns { ok, baseSha, warning } (:914); nothing about the previous run is read.
  • baseSha becomes the job's base_sha (src/db.ts:1172, written at src/jobs/service.ts:1145), so the previous base is already persisted and no new table is needed.
  • The only delta in the goal is the fork warning (src/jobs/service.ts:1056-1057).
  • The reads slice 1 needs already exist: compareCommits (src/repos/github.ts:887, returns status and aheadBy), getCommitMeta (:911, a commit's committedAt) and listMergedPullRequestsSince (:932, bounded pages plus complete). They were added as the read half of feat: show a repository release readiness before the release (#546) #760; none of them is called from the dispatch path today.

Expected:

  • preflight takes sinceSha = base_sha of the newest finished job for the same repository, and only when one exists;
  • two bounded reads then run: compareCommits(sinceSha, baseSha) and, through getCommitMeta(sinceSha).committedAt, listMergedPullRequestsSince; a failed or capped read leaves the line marked partial rather than reporting a smaller number;
  • the job stores temporal_json (additive column) with sinceSha, status, aheadBy, the merged PR numbers and complete;
  • the goal gains exactly one data line, e.g. Since 4f2c1a9: 3 commits ahead, 2 merged PRs (#812, #815); a first job says Since: no previous run and makes no compare call;
  • the job page shows the same line.

Red test

test/temporal.test.ts (new) for the pure summariser, plus a dispatcher case in test/jobs.test.ts with the existing fake client:

  • summariseDelta({ sinceSha, status: 'ahead', aheadBy: 3, merged: [812, 815] }) → Since 4f2c1a9: 3 commits ahead, 2 merged PRs (#812, #815); merged: [] → 0 merged PRs; complete: false → the line ends partial.
  • a repository whose previous job recorded base_sha produces a job whose temporal_json.sinceSha equals that value and whose goal contains the line.
  • a first job for the repository produces Since: no previous run, and the fake client records zero compare calls.

Verification

  • node --test test/temporal.test.ts test/jobs.test.ts passes, and the new assertions are red at 67d1c9a3.
  • /repos/:id/jobs/:jobId shows the delta line for the scheduled job and Since: no previous run for the first one; npm run check passes.

Not in this card

  • Slice 2 — changed files in the target area and the relevant check state in the contract.
  • Slice 3 — the previous run's claim, and refusing a new iterate when the linked issue is closed or the linked PR is merged unless a human reopens the work.
  • Slice 4 — a stale base produces a stale/rebase decision instead of a duplicate branch, and the contract is cached so a tick does not spend the GitHub budget per repository.

Scope and tier

src/lib/temporal.ts (new, pure), src/jobs/service.ts, src/db.ts (one additive column), src/views/pages.ts, test/temporal.test.ts, docs/architecture.md. T3 (src/jobs, src/db), PASS at the tip.

Non-goals

  • No full repository clone and no history rewrite.
  • No replacement for the existing duplicate preflight; this feeds it a delta, in a later slice.
  • No new GitHub permission.

This card closes when slice 1 merges; the named later slices will be filed from this body, one card each, when it does.

References

  • arXiv:2611.12083 — SWE-Time: Benchmarking Temporal Repository Understanding (Xiao et al., 2026).

Activity

  1. added
    enhancementNew feature or request
    area:jobsJob lifecycle, queue, callbacks
    priority:highHigh priority; claim before normal backlog
    on Nov 12, 2026
  2. HugoXK commented on Nov 14, 2026

    @HugoXK
    OwnerAuthor

    Triage: wont-do
    Owner: nobody
    Next: not this cycle: agent-capability/RSI track, gated behind the AgentDescent shadow (#106) and the roadmap plan (#547, #654)
    Written-by: Fledge Platform Lead

  3. added
    needs-reviewWaiting for the Fledge Platform Reviewer's issue review
    on Nov 15, 2026
  4. HugoXK-bot commented on Nov 15, 2026

    @HugoXK-bot
    Collaborator

    Issue-review: PASS at issue #366 body 1089506f0304

    Written-by: HugoXK-bot

    Anchors checked at 6287aa53: preflight() is src/jobs/service.ts:892 and returns { ok, baseSha, warning } at :914; the delta readers all exist and are unused from the dispatch path — compareCommits src/repos/github.ts:887, getCommitMeta :911, listMergedPullRequestsSince :932; base_sha is already a column (src/db.ts:1172), so the previous base needs no new table. The claim "no new table needed" is true, and that is what keeps this slice small.

    First slice stands: src/lib/temporal.ts (new, pure summariseDelta), src/jobs/service.ts (one sinceSha read and two bounded reads), src/db.ts (temporal_json additive), src/views/pages.ts, test/temporal.test.ts, docs/architecture.md.

    The rule I will enforce at the PR: a capped or failed read marks the line partial and never reports a smaller number as if it were the whole delta — listMergedPullRequestsSince's complete flag exists precisely for that, and a first job must make zero compare calls (Since: no previous run), which the fake client can assert by call count.

  5. added
    review:approvedIssue reviewed and approved by the Fledge Platform Reviewer
    and removed
    needs-reviewWaiting for the Fledge Platform Reviewer's issue review
    on Nov 15, 2026
  6. HugoXK commented on Nov 15, 2026

    @HugoXK
    OwnerAuthor

    Claiming #366 slice 1, on the live issue gate. Evidence that the gate is open at this body: labels review:approved + agent-ready both present with no review:changes, and the body's sha256 is 1089506f030451abf873ae29dff256cf77e253c913c9a74e3c2777187d352641, which matches the Reviewer's Issue-review: PASS at issue #366 body 1089506f0304.

    • Branch: dev1/366-temporal-contract, cut from live main 9f2ef3aa9b0cb00446f6cd0a25325d2efc2fe3bf.
    • Plan (slice 1 only, as the issue and the PASS both scope it): src/lib/temporal.ts with a pure summariseDelta; preflight() reads sinceSha = base_sha of the newest finished job for the repository and, only then, two bounded reads (compareCommits, getCommitMeta -> listMergedPullRequestsSince); temporal_json as an additive column; exactly one data line in the goal; the same line on the job page. A capped or failed read marks the line partial and never reports a smaller number.
    • Red test first: test/temporal.test.ts against the pure summariser plus the partial rule.

    One-pusher rule respected: I do not push; I hand the tree, tar, parent and npm run check counts to the Lead.

  7. HugoXK commented on Nov 15, 2026

    @HugoXK
    OwnerAuthor

    Slice 1 is up as PR #842 — #842

    • head 07bf4d25bb0f741790f09c0f39abf67524b209bb, tree 18c6d268223fb2d1a7f365aab75fe608ad88b480, parent 9f2ef3aa9b0cb00446f6cd0a25325d2efc2fe3bf, 7 files +278/−7, risk T3 (basis src/db.ts)
    • npm run check exit 0 / 2204 tests; pr-lint: ok (#842, T3, 7 files)
    • Red half: test/temporal.test.ts at 9f2ef3aa fails with ERR_MODULE_NOT_FOUND for src/lib/temporal.js; 12/12 at the PR tip.
    • Scope kept to slice 1: the delta is recorded in jobs.temporal_json and shown in the goal and on the job page; no decision, refusal, priority or merge reads it.

    The verdict is requested at 07bf4d25. Nothing in the issue's slices 2-4 is included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

agent-pragent-readyReady for an agent to implementagent-workingarea:jobsJob lifecycle, queue, callbacksenhancementNew feature or requestpriority:highHigh priority; claim before normal backlogreview:approvedIssue reviewed and approved by the Fledge Platform Reviewer

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions