@cueloop/schema 0.1.0-alpha.45 → 0.1.0-alpha.47

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.45",
3
+ "version": "0.1.0-alpha.47",
4
4
  "description": "The ReviewSession primitive: types, markdown block model, quote-primary anchors, feedback serialization",
5
5
  "homepage": "https://github.com/mmurakaru/cueloop#readme",
6
6
  "bugs": {
@@ -34,7 +34,7 @@ describe("renderFeedback", () => {
34
34
  artifactContent: PLAN,
35
35
  workingCopy: PLAN.replace("one JSON document", "one JSON record"),
36
36
  annotations: [],
37
- planPath: "docs/plan.md",
37
+ artifactPath: "docs/plan.md",
38
38
  });
39
39
 
40
40
  // Assert
@@ -200,4 +200,27 @@ describe("renderFeedback", () => {
200
200
  // Assert
201
201
  expect(feedback).toContain("(§ Persistence)");
202
202
  });
203
+
204
+ test("a prototype annotation locates by its selector and is never orphan-flagged", () => {
205
+ // Act
206
+ const feedback = renderFeedback({
207
+ verdictKind: "request_changes",
208
+ summary: "",
209
+ artifactType: "prototype",
210
+ artifactContent: "<main><div class='card'>Pricing</div></main>",
211
+ annotations: [
212
+ makeAnnotation({
213
+ body: "Tighten the padding.",
214
+ anchor: { quote: "Pricing", prefix: "", suffix: "", selector: "main > div.card" },
215
+ }),
216
+ ],
217
+ artifactPath: "proto.html",
218
+ });
219
+
220
+ // Assert
221
+ expect(feedback).toContain("(main > div.card)");
222
+ expect(feedback).toContain("Tighten the padding.");
223
+ expect(feedback).toContain("by its CSS selector");
224
+ expect(feedback).not.toContain("orphaned anchor");
225
+ });
203
226
  });
package/src/feedback.ts CHANGED
@@ -28,8 +28,8 @@ export interface FeedbackInput {
28
28
  /** Artifact kind; defaults to "plan". A diff working copy is already a patch. */
29
29
  artifactType?: ArtifactType;
30
30
  annotations: Annotation[];
31
- /** Path the agent knows the plan by, for direct reference. */
32
- planPath?: string;
31
+ /** Path the agent knows the artifact by (plan or prototype), for direct reference. */
32
+ artifactPath?: string;
33
33
  /** Session id, so the document can teach the addressed-ids resubmit call. */
34
34
  sessionId?: string;
35
35
  }
@@ -37,7 +37,7 @@ export interface FeedbackInput {
37
37
  const quoteLines = (text: string) => "> " + text.replace(/\n/g, "\n> ");
38
38
 
39
39
  export function renderFeedback(input: FeedbackInput): string {
40
- const path = input.planPath ?? "plan.md";
40
+ const path = input.artifactPath ?? "plan.md";
41
41
  // agent notes are the submitter's own context - never echoed back as
42
42
  // feedback - and annotations a previous revision already addressed stay out
43
43
  // of the next document, so the agent only ever sees the open items
@@ -45,6 +45,7 @@ export function renderFeedback(input: FeedbackInput): string {
45
45
  (annotation) => !isAgentNote(annotation) && !isAddressed(annotation),
46
46
  );
47
47
  const isDiff = input.artifactType === "diff";
48
+ const isPrototype = input.artifactType === "prototype";
48
49
  // A diff's annotations anchor to the submitted patch rows; resolve against it,
49
50
  // not the curated working copy (which may drop the rejected rows).
50
51
  const blocks = parseBlocks(
@@ -98,14 +99,22 @@ export function renderFeedback(input: FeedbackInput): string {
98
99
  if (annotations.length) {
99
100
  lines.push(`## Annotations (${annotations.length})`);
100
101
  lines.push("");
101
- lines.push(`Address every item. Locate each one in ${path} by its quoted text.`);
102
+ lines.push(
103
+ isPrototype
104
+ ? `Address every item. Locate each one in ${path} by its CSS selector.`
105
+ : `Address every item. Locate each one in ${path} by its quoted text.`,
106
+ );
102
107
  lines.push("");
103
108
  annotations.forEach((annotation, annotationIndex) => {
104
- const resolved = resolveAnchor(annotation.anchor, blocks);
109
+ // a prototype selector anchor is never resolved or orphaned against blocks
110
+ const selector = annotation.anchor.selector;
111
+ const resolved = selector ? null : resolveAnchor(annotation.anchor, blocks);
105
112
  const sectionTitle = resolved ? sectionOf(blocks, resolved.blockIndex) : "";
106
- const location = sectionTitle ? ` (§ ${sectionTitle})` : "";
113
+ const location = selector ? ` (${selector})` : sectionTitle ? ` (§ ${sectionTitle})` : "";
107
114
  const orphanFlag =
108
- resolved === null ? " [orphaned anchor: the quoted text is no longer present]" : "";
115
+ !selector && resolved === null
116
+ ? " [orphaned anchor: the quoted text is no longer present]"
117
+ : "";
109
118
  lines.push(
110
119
  `### ${annotationIndex + 1}. ${capitalize(annotation.kind)}${location}${orphanFlag}`,
111
120
  );
@@ -151,7 +160,7 @@ export function feedbackForSession(
151
160
  workingCopy: session.workingCopy,
152
161
  artifactType: session.artifact.type,
153
162
  annotations: session.annotations,
154
- planPath: session.artifact.meta.planPath,
163
+ artifactPath: session.artifact.meta.prototypePath ?? session.artifact.meta.planPath,
155
164
  sessionId: session.id,
156
165
  });
157
166
  }
package/src/types.ts CHANGED
@@ -12,7 +12,7 @@ export interface WorkspaceKey {
12
12
  branch: string;
13
13
  }
14
14
 
15
- export type ArtifactType = "plan" | "diff";
15
+ export type ArtifactType = "plan" | "diff" | "prototype";
16
16
 
17
17
  export interface ArtifactMeta {
18
18
  cwd?: string;
@@ -21,6 +21,8 @@ export interface ArtifactMeta {
21
21
  agentSessionId?: string;
22
22
  /** Path to the plan file on disk, so feedback can reference it. */
23
23
  planPath?: string;
24
+ /** Path to the prototype's entry HTML file on disk. */
25
+ prototypePath?: string;
24
26
  /** Pull request reference the diff came from, so the verdict can be posted back. */
25
27
  pr?: string;
26
28
  /** herdr pane the submitting agent runs in - the review returns focus there. */
@@ -67,6 +69,8 @@ export interface Anchor {
67
69
  /** Character offsets within that block's text (hint). */
68
70
  start?: number;
69
71
  end?: number;
72
+ /** Prototype anchors: the CSS selector of the annotated element (authority). */
73
+ selector?: string;
70
74
  }
71
75
 
72
76
  /** The annotation kind set is open; these are the built-ins. */