tenseleyflow/loader / 1c30cdc

Browse files

Add grounded clarify brief hints

Authored by espadonne
SHA
1c30cdc073e08f2fd484cac38ed2fc86fcfc6e54
Parents
4cfaf71
Tree
04d6248

2 changed files

StatusFile+-
M src/loader/runtime/clarify_grounding.py 97 0
M tests/test_clarify_grounding.py 54 0
src/loader/runtime/clarify_grounding.pymodified
@@ -92,6 +92,28 @@ class ClarifyRepoFact:
9292
         return f"`{self.path}`: {self.summary}"
9393
 
9494
 
95
+@dataclass(slots=True)
96
+class ClarifyBriefHints:
97
+    """Grounded hints that can strengthen a persisted clarify brief."""
98
+
99
+    likely_touchpoints: list[str] = field(default_factory=list)
100
+    constraints: list[str] = field(default_factory=list)
101
+    assumptions: list[str] = field(default_factory=list)
102
+    acceptance_criteria: list[str] = field(default_factory=list)
103
+
104
+    def has_content(self) -> bool:
105
+        """Return whether any grounded hint is available."""
106
+
107
+        return any(
108
+            (
109
+                self.likely_touchpoints,
110
+                self.constraints,
111
+                self.assumptions,
112
+                self.acceptance_criteria,
113
+            )
114
+        )
115
+
116
+
95117
 @dataclass(slots=True)
96118
 class ClarifyGrounding:
97119
     """Cheap workspace evidence that clarify mode can reference."""
@@ -191,6 +213,81 @@ class ClarifyGrounding:
191213
             return self.prompt_block()
192214
         return "\n".join(lines)
193215
 
216
+    def brief_hints(self) -> ClarifyBriefHints:
217
+        """Return grounded hints for clarify brief synthesis and fallback repair."""
218
+
219
+        primary_path = self.primary_touchpoint()
220
+        secondary_path = self.secondary_touchpoint()
221
+        primary_fact = self.primary_fact()
222
+        secondary_fact = self.secondary_fact()
223
+
224
+        likely_touchpoints = [
225
+            path for path in [primary_path, secondary_path] if path is not None
226
+        ][:2]
227
+
228
+        constraints: list[str] = []
229
+        if primary_path is not None:
230
+            constraints.append(
231
+                f"Keep the primary implementation scoped to `{primary_path}` "
232
+                "unless evidence requires a wider edit."
233
+            )
234
+        if secondary_path is not None:
235
+            constraints.append(
236
+                f"Preserve existing behavior in `{secondary_path}` unless the user broadens scope."
237
+            )
238
+
239
+        assumptions: list[str] = []
240
+        for fact in [primary_fact, secondary_fact]:
241
+            if fact is None:
242
+                continue
243
+            assumptions.append(
244
+                f"Workspace evidence: `{fact.path}` currently contains `{fact.summary}`."
245
+            )
246
+
247
+        acceptance_criteria: list[str] = []
248
+        if primary_path is not None:
249
+            acceptance_criteria.append(
250
+                f"Primary work stays scoped to `{primary_path}`."
251
+            )
252
+        if secondary_path is not None:
253
+            acceptance_criteria.append(
254
+                f"Nearby surface `{secondary_path}` stays unchanged unless "
255
+                "the user confirms otherwise."
256
+            )
257
+
258
+        return ClarifyBriefHints(
259
+            likely_touchpoints=likely_touchpoints,
260
+            constraints=constraints,
261
+            assumptions=assumptions,
262
+            acceptance_criteria=acceptance_criteria,
263
+        )
264
+
265
+    def brief_prompt_block(self) -> str:
266
+        """Render brief-oriented grounding hints for the brief synthesis prompt."""
267
+
268
+        hints = self.brief_hints()
269
+        if not hints.has_content():
270
+            return self.prompt_block()
271
+
272
+        lines: list[str] = []
273
+        if hints.likely_touchpoints:
274
+            lines.append(
275
+                "- Seed likely touchpoints: " + ", ".join(hints.likely_touchpoints)
276
+            )
277
+        if hints.constraints:
278
+            lines.append(
279
+                "- Preserve constraints: " + "; ".join(hints.constraints)
280
+            )
281
+        if hints.assumptions:
282
+            lines.append(
283
+                "- Grounded assumptions: " + "; ".join(hints.assumptions)
284
+            )
285
+        if hints.acceptance_criteria:
286
+            lines.append(
287
+                "- Scope acceptance criteria: " + "; ".join(hints.acceptance_criteria)
288
+            )
289
+        return "\n".join(lines)
290
+
194291
     def primary_touchpoint(self) -> str | None:
195292
         """Return the best available repo anchor for a focused question."""
196293
 
tests/test_clarify_grounding.pymodified
@@ -126,6 +126,60 @@ def test_slot_prompt_block_adds_secondary_touchpoint_for_example_pressure() -> N
126126
     assert "Relevant paths: src/loader/runtime/workflow_lanes.py" in block
127127
 
128128
 
129
+def test_brief_hints_seed_touchpoints_constraints_and_acceptance() -> None:
130
+    grounding = ClarifyGrounding(
131
+        existing_references=["src/loader/runtime/workflow_lanes.py"],
132
+        candidate_touchpoints=["src/loader/runtime/clarify_strategy.py"],
133
+        repo_facts=[
134
+            ClarifyRepoFact(
135
+                path="src/loader/runtime/workflow_lanes.py",
136
+                summary="class WorkflowLaneRunner:",
137
+            ),
138
+            ClarifyRepoFact(
139
+                path="src/loader/runtime/clarify_strategy.py",
140
+                summary="Intent-aware clarify strategy for runtime follow-up.",
141
+            ),
142
+        ],
143
+    )
144
+
145
+    hints = grounding.brief_hints()
146
+
147
+    assert hints.likely_touchpoints == [
148
+        "src/loader/runtime/workflow_lanes.py",
149
+        "src/loader/runtime/clarify_strategy.py",
150
+    ]
151
+    assert any("workflow_lanes.py" in item for item in hints.constraints)
152
+    assert any("clarify_strategy.py" in item for item in hints.constraints)
153
+    assert any("WorkflowLaneRunner" in item for item in hints.assumptions)
154
+    assert any("Primary work stays scoped" in item for item in hints.acceptance_criteria)
155
+
156
+
157
+def test_brief_prompt_block_renders_grounded_brief_hints() -> None:
158
+    grounding = ClarifyGrounding(
159
+        existing_references=["src/loader/runtime/workflow_lanes.py"],
160
+        candidate_touchpoints=["src/loader/runtime/clarify_strategy.py"],
161
+        repo_facts=[
162
+            ClarifyRepoFact(
163
+                path="src/loader/runtime/workflow_lanes.py",
164
+                summary="class WorkflowLaneRunner:",
165
+            ),
166
+            ClarifyRepoFact(
167
+                path="src/loader/runtime/clarify_strategy.py",
168
+                summary="Intent-aware clarify strategy for runtime follow-up.",
169
+            ),
170
+        ],
171
+    )
172
+
173
+    block = grounding.brief_prompt_block()
174
+
175
+    assert "Seed likely touchpoints" in block
176
+    assert "Preserve constraints" in block
177
+    assert "Grounded assumptions" in block
178
+    assert "Scope acceptance criteria" in block
179
+    assert "workflow_lanes.py" in block
180
+    assert "clarify_strategy.py" in block
181
+
182
+
129183
 def test_build_grounded_question_anchors_touchpoint_tradeoff_with_repo_fact() -> None:
130184
     question = build_grounded_clarify_question(
131185
         task="Tighten Loader runtime clarify behavior.",