فهرست منبع

ui: the completion review renders as the rich attention block while pending (highlight-remarks queue shared with the plan review, push chips + compare above the report, accept gate server-side) and the Completion review card becomes the terminal summary

clanker 1 ماه پیش
والد
کامیت
253551bba2
3فایلهای تغییر یافته به همراه67 افزوده شده و 39 حذف شده
  1. 9 5
      src/entrypoints/GoalDetailEntrypoint.vala
  2. 55 31
      src/pages/goal_detail.html
  3. 3 3
      test/web_stack_test.py

+ 9 - 5
src/entrypoints/GoalDetailEntrypoint.vala

@@ -444,10 +444,10 @@ namespace ClankerSaddle {
                     created_display = format_stamp(block.created_at),
                     is_plan_review = pending_plan,
                     is_completion_review = pending_completion,
-                    // A pending plan/completion block hides its body
-                    // preview: the plan/completion section already
-                    // renders it (the task page's duplicate rule).
-                    show_body = !(pending_plan || pending_completion),
+                    // A pending plan hides its body preview (the plan
+                    // section renders it); the pending completion review
+                    // SHOWS its body — the block IS the review surface.
+                    show_body = !pending_plan,
                     approved = block.answer != null
                         && block.answer == NOTICE_PLAN_APPROVED
                 };
@@ -478,7 +478,11 @@ namespace ClankerSaddle {
                 var view = (GoalBlockView) block_array[index];
                 if (view.answered) {
                     answered_sink.add(view);
-                } else if (!view.is_plan_review && !view.is_completion_review) {
+                } else if (!view.is_plan_review) {
+                    // The PENDING completion review rides the attention
+                    // blocks like any other (the rich review form with
+                    // the highlight-remarks queue); the dedicated
+                    // Completion review card is the terminal summary.
                     open_sink.add(view);
                 }
             }

+ 55 - 31
src/pages/goal_detail.html

@@ -387,20 +387,56 @@
                              stm-text="block.block_type">kind</span>
                         <strong stm-text="block.question">question</strong>
                         <span class="muted" stm-text="block.created_display">when</span></p>
-                    <div stm-if="block.show_body && block.body.length > 0"
-                         class="md rfc-body goal-body" stm-markdown="block.body">body</div>
-                    <form stm-action="block.answer_action">
-                        <div stm-if="block.options.length > 0" class="form-row">
-                            <label>Options</label>
-                            <select name="option">
-                                <option stm-for-option-in="block.options" stm-attribute.value="option"
-                                         stm-text="option">opt</option>
-                            </select></div>
-                        <div class="form-row">
-                            <textarea name="answer" rows="2"
-                                      placeholder="Reply (or pick an option)"></textarea></div>
-                        <button type="submit" class="primary">Answer</button>
-                    </form>
+                    <!-- The pending completion review renders in the rich
+                         review form (highlight-remarks queue shared with
+                         the plan review; push chips + compare above the
+                         report; accept gate enforced server-side). -->
+                    <div stm-if="block.is_completion_review"
+                         class="plan-review" data-plan-review
+                         stm-attribute.data-block-id="block.id">
+                        <p stm-if="goal.push_branches.length > 0">Goal branches:
+                            <span stm-for-branch-in="goal.push_branches">
+                                <code stm-text="branch.branch">b</code>
+                                <span stm-attribute.class="branch.pushed ? 'badge badge-done' : 'badge badge-failed'"
+                                      stm-text="branch.pushed ? 'pushed' : 'unpushed'">state</span>
+                            </span></p>
+                        <p><a stm-if="goal.compare_url.length > 0" stm-attribute.href="goal.compare_url"
+                              target="_blank" rel="noopener">Compare changes</a></p>
+                        <div class="md rfc-body goal-body" data-plan-body
+                             stm-markdown="block.body">report</div>
+                        <div class="actions">
+                            <form stm-action="block.answer_action" class="inline">
+                                <input type="hidden" name="answer"
+                                       value="Review approved. Continue with the task.">
+                                <button type="submit" class="approve" data-plan-accept>Accept goal</button>
+                            </form>
+                            <button type="button" data-plan-toggle>Reject with feedback</button>
+                        </div>
+                        <div data-plan-feedback hidden>
+                            <p class="muted">Highlight report text to attach a remark to it — the queue
+                                rides the rejection numbered, then clears. Accepting ignores the queue.</p>
+                            <ul class="plan-comments" data-plan-remarks></ul>
+                            <textarea name="feedback" rows="2"
+                                      placeholder="Additional feedback (optional)"></textarea>
+                            <button type="button" class="primary" data-plan-submit>Submit feedback</button>
+                        </div>
+                    </div>
+                    <div stm-if="!block.is_completion_review">
+                        <div stm-if="block.show_body && block.body.length > 0"
+                             class="md rfc-body goal-body" stm-markdown="block.body">body</div>
+                        <form stm-action="block.answer_action">
+                            <div stm-if="block.options.length > 0" class="form-row">
+                                <label>Options</label>
+                                <select name="option">
+                                    <option stm-for-option-in="block.options" stm-attribute.value="option"
+                                             stm-text="option">opt</option>
+                                </select></div>
+                            <div class="form-row">
+                                <textarea name="answer" rows="2"
+                                          placeholder="Reply (or pick an option)"></textarea></div>
+                            <button type="submit" class="primary">Answer</button>
+                        </form>
+                    </div>
                 </div>
                 <details class="history-expander" stm-if="goal.answered_blocks.length > 0">
                     <summary>Answered blocks (<span stm-text="goal.answered_blocks.length">0</span>)</summary>
@@ -418,9 +454,11 @@
                 </details>
             </section>
 
-            <!-- Completion review: the report, compare link (an
-                 answerable attention block). -->
-            <section class="card" stm-if="goal.completion_pending">
+            <!-- Completion review card: the TERMINAL summary — shown
+                 once the goal is complete/failed, with the report and
+                 the compare link. While PENDING, the review lives in
+                 the attention blocks above (the rich review form). -->
+            <section class="card" stm-if="goal.terminal && goal.completion_report.length > 0">
                 <h3>Completion review</h3>
                 <p stm-if="goal.push_branches.length > 0">Goal branches:
                     <span stm-for-branch-in="goal.push_branches">
@@ -431,20 +469,6 @@
                 <p><a stm-if="goal.compare_url.length > 0" stm-attribute.href="goal.compare_url"
                       target="_blank" rel="noopener">Compare changes</a></p>
                 <div class="md rfc-body goal-body" stm-markdown="goal.completion_report">report</div>
-                <form stm-action="goal.completion_pending_block.answer_action" class="inline">
-                    <input type="hidden" name="answer"
-                           value="Review approved. Continue with the task.">
-                    <button type="submit" class="approve">Accept goal</button>
-                </form>
-                <details>
-                    <summary>Request changes</summary>
-                    <form stm-action="goal.completion_pending_block.answer_action">
-                        <div class="form-row">
-                            <textarea name="answer" rows="4" required
-                                      placeholder="What remains to be done?"></textarea></div>
-                        <button type="submit" class="reject">Send feedback</button>
-                    </form>
-                </details>
             </section>
 
             <!-- The plan (plan 15 C4): BETWEEN attention and tasks.

+ 3 - 3
test/web_stack_test.py

@@ -5755,9 +5755,9 @@ def bundle_goals(ctx):
           "the daemon's review-kind completion push adopts the pending row (no twin)")
     state = goal_state(goal1)
     review_family_in_open = [b for b in state.get("open_blocks", [])
-                             if b["block_type"] in ("completion", "review")]
-    check(state["completion_pending"] is True and not review_family_in_open,
-          "the completion review renders once (dedicated card, not duplicated)")
+                             if b.get("is_completion_review")]
+    check(state["completion_pending"] is True and len(review_family_in_open) == 1,
+          "the pending completion review renders ONCE — as the rich attention block")
     fake.pending_block = None
     # Plan 15 C4: the completion-accept hard gate — the live probe
     # flags still report repob's branch unpushed, so the operator's