feat(proposalModel): setProposalApplied re-anchors + stores original (#64)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,25 @@ export function removeProposal(artifact: Artifact, proposalId: string): boolean
|
|||||||
return artifact.proposals.length < before;
|
return artifact.proposals.length < before;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F12/#64 (INV-48): record a proposal as optimistically applied — store the
|
||||||
|
* pre-apply `original` (for revert + the struck `<del>`) and re-point its anchor
|
||||||
|
* fingerprint to the now-in-buffer applied text so `resolve()` finds it. Idempotent
|
||||||
|
* shape: a second call simply overwrites with the same values.
|
||||||
|
*/
|
||||||
|
export function setProposalApplied(
|
||||||
|
artifact: Artifact,
|
||||||
|
proposalId: string,
|
||||||
|
appliedFp: Fingerprint,
|
||||||
|
original: string,
|
||||||
|
): boolean {
|
||||||
|
const p = artifact.proposals.find((x) => x.id === proposalId);
|
||||||
|
if (!p) return false;
|
||||||
|
p.original = original;
|
||||||
|
artifact.anchors[p.anchorId] = { fingerprint: appliedFp };
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** Markdown comment body: instruction header + fenced whole-range diff. */
|
/** Markdown comment body: instruction header + fenced whole-range diff. */
|
||||||
export function proposalBody(targetText: string, p: Proposal): string {
|
export function proposalBody(targetText: string, p: Proposal): string {
|
||||||
const header = p.instruction ? `**Claude proposes** — _${p.instruction}_` : "**Claude proposes**";
|
const header = p.instruction ? `**Claude proposes** — _${p.instruction}_` : "**Claude proposes**";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
type Proposal,
|
type Proposal,
|
||||||
} from "../src/model";
|
} from "../src/model";
|
||||||
import { CoauthorStore } from "../src/store";
|
import { CoauthorStore } from "../src/store";
|
||||||
import { addProposal, proposalBody, removeProposal } from "../src/proposalModel";
|
import { addProposal, proposalBody, removeProposal, setProposalApplied } from "../src/proposalModel";
|
||||||
|
|
||||||
const agent = {
|
const agent = {
|
||||||
kind: "agent" as const,
|
kind: "agent" as const,
|
||||||
@@ -104,4 +104,19 @@ describe("proposalModel helpers (spec §6.4)", () => {
|
|||||||
expect(body).toContain("- old line two");
|
expect(body).toContain("- old line two");
|
||||||
expect(body).toContain("+ new only line");
|
expect(body).toContain("+ new only line");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("setProposalApplied stores original and re-anchors the fingerprint to the applied text", () => {
|
||||||
|
const a = emptyArtifact("docs/x.md");
|
||||||
|
const { proposalId, anchorId } = addProposal(
|
||||||
|
a,
|
||||||
|
{ text: "old", before: "", after: "", lineHint: 0 },
|
||||||
|
"new",
|
||||||
|
{ kind: "agent", id: "claude", agent: { sdk: "x", model: "m", sessionId: "s" } },
|
||||||
|
{ granularity: "block" },
|
||||||
|
);
|
||||||
|
setProposalApplied(a, proposalId, { text: "new", before: "", after: "", lineHint: 0 }, "old");
|
||||||
|
const p = a.proposals.find((x) => x.id === proposalId)!;
|
||||||
|
expect(p.original).toBe("old");
|
||||||
|
expect(a.anchors[anchorId].fingerprint.text).toBe("new");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user