@cueloop/schema 0.1.0-alpha.14 → 0.1.0-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cueloop/schema",
3
- "version": "0.1.0-alpha.14",
3
+ "version": "0.1.0-alpha.16",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -98,6 +98,25 @@ describe("renderFeedback", () => {
98
98
  expect(out).toContain("_No edits or annotations._");
99
99
  });
100
100
 
101
+ test("agent notes never come back as feedback items", () => {
102
+ const note = ann({
103
+ kind: "note",
104
+ anchor: { quote: "src/a.ts", prefix: "", suffix: "" },
105
+ body: "The agent's own explanation of the change.",
106
+ });
107
+ const noteOnly = renderFeedback({ verdictKind: "approve", summary: "", artifactContent: PLAN, annotations: [note] });
108
+ expect(noteOnly).toContain("_No edits or annotations._");
109
+ expect(noteOnly).not.toContain("The agent's own explanation of the change.");
110
+ const mixed = renderFeedback({
111
+ verdictKind: "request_changes",
112
+ summary: "",
113
+ artifactContent: PLAN,
114
+ annotations: [note, ann({ anchor: { quote: "one JSON document", prefix: "written as ", suffix: " per session." } })],
115
+ });
116
+ expect(mixed).toContain("## Annotations (1)");
117
+ expect(mixed).not.toContain("The agent's own explanation of the change.");
118
+ });
119
+
101
120
  test("anchors resolve against the working copy when present", () => {
102
121
  // annotation made on text that only exists in the edited copy
103
122
  const working = PLAN.replace("## Storage", "## Persistence");
package/src/feedback.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * first, then every annotation is addressed, located by quoted text.
6
6
  */
7
7
 
8
- import type { Annotation, ReviewSession, VerdictKind } from "./types";
8
+ import { isAgentNote, type Annotation, type ReviewSession, type VerdictKind } from "./types";
9
9
  import { parseBlocks, sectionOf } from "./markdown";
10
10
  import { resolveAnchor } from "./anchor";
11
11
  import { unifiedDiffText } from "./diff";
@@ -26,6 +26,8 @@ const quoteLines = (s: string) => "> " + s.replace(/\n/g, "\n> ");
26
26
 
27
27
  export function renderFeedback(input: FeedbackInput): string {
28
28
  const path = input.planPath ?? "plan.md";
29
+ // agent notes are the submitter's own context - never echoed back as feedback
30
+ const annotations = input.annotations.filter((annotation) => !isAgentNote(annotation));
29
31
  const blocks = parseBlocks(input.workingCopy ?? input.artifactContent);
30
32
  const lines: string[] = [];
31
33
  lines.push("# Review: " + input.verdictKind.replace("_", " "));
@@ -49,12 +51,12 @@ export function renderFeedback(input: FeedbackInput): string {
49
51
  lines.push("");
50
52
  }
51
53
 
52
- if (input.annotations.length) {
53
- lines.push(`## Annotations (${input.annotations.length})`);
54
+ if (annotations.length) {
55
+ lines.push(`## Annotations (${annotations.length})`);
54
56
  lines.push("");
55
57
  lines.push(`Address every item. Locate each one in ${path} by its quoted text.`);
56
58
  lines.push("");
57
- input.annotations.forEach((a, i) => {
59
+ annotations.forEach((a, i) => {
58
60
  const res = resolveAnchor(a.anchor, blocks);
59
61
  const sec = res ? sectionOf(blocks, res.blockIndex) : "";
60
62
  const loc = sec ? ` (§ ${sec})` : "";
@@ -77,7 +79,7 @@ export function renderFeedback(input: FeedbackInput): string {
77
79
  });
78
80
  }
79
81
 
80
- if (!diff && !input.annotations.length) {
82
+ if (!diff && !annotations.length) {
81
83
  lines.push("_No edits or annotations._");
82
84
  lines.push("");
83
85
  }
package/src/types.ts CHANGED
@@ -54,6 +54,16 @@ export interface Anchor {
54
54
  /** The annotation kind set is open (map #2); these are the built-ins. */
55
55
  export type AnnotationKind = "comment" | "suggestion" | (string & {});
56
56
 
57
+ /**
58
+ * Agent-authored context, not reviewer feedback: the guided walk's per-file
59
+ * notes (kind "note", anchored by the file path). Excluded from the feedback
60
+ * document and the reviewer's pending counts - an agent must never receive
61
+ * its own notes back as items to address.
62
+ */
63
+ export function isAgentNote(annotation: Pick<Annotation, "kind">): boolean {
64
+ return annotation.kind === "note";
65
+ }
66
+
57
67
  export interface Annotation {
58
68
  id: string;
59
69
  kind: AnnotationKind;
@@ -97,6 +107,12 @@ export interface ReviewSession {
97
107
  * Undefined = no direct edits.
98
108
  */
99
109
  workingCopy?: string;
110
+ /**
111
+ * File paths the reviewer marked viewed during the guided walk (diff
112
+ * sessions). Persisting with the session means a resumed review keeps its
113
+ * progress. Undefined = the walk never started.
114
+ */
115
+ viewedPaths?: string[];
100
116
  verdict: Verdict | null;
101
117
  status: SessionStatus;
102
118
  createdAt: string;