|
@@ -4,13 +4,18 @@
|
|
|
<pstm-uri>/goals/{goal_id}</pstm-uri>
|
|
<pstm-uri>/goals/{goal_id}</pstm-uri>
|
|
|
<pstm-template>main</pstm-template>
|
|
<pstm-template>main</pstm-template>
|
|
|
<script>
|
|
<script>
|
|
|
- // The goal page: supervision surface of one goal - status head
|
|
|
|
|
- // with lifecycle actions (plus run-control parity: retry
|
|
|
|
|
- // supervision, requeue-to-resume), branch/push-state chips, one
|
|
|
|
|
- // muted activity line, the agent's live progress feed, the ATTENTION
|
|
|
|
|
- // blocks (the goal agent's answerable questions/RFCs and the
|
|
|
|
|
- // completion review), the task status strip with per-row
|
|
|
|
|
- // capability badges, the locked brief, the goal's effective
|
|
|
|
|
|
|
+ // The goal page (goal 41 T6): the state strip leads - the
|
|
|
|
|
+ // one-glance verdict (status badge, the open-item line, the
|
|
|
|
|
+ // primary lifecycle button) - then the anchor sub-nav, then the
|
|
|
|
|
+ // Act|Consult two-column layout (spry .with-sidebar): the acting
|
|
|
|
|
+ // surfaces (state, blocks/questions, plan review, completion
|
|
|
|
|
+ // review, comments) on the left, the consulting ones (tasks with
|
|
|
|
|
+ // the filter strip, initial brief, involved projects, rules,
|
|
|
|
|
+ // narrative, runs) on the right, stacking Act-then-Consult under
|
|
|
|
|
+ // the framework breakpoint. Below the fold the page keeps its
|
|
|
|
|
+ // established surfaces: the agent's live progress feed, the
|
|
|
|
|
+ // attention blocks (the goal agent's answerable questions/RFCs
|
|
|
|
|
+ // and the completion review), the locked brief, the effective
|
|
|
// rules, the approved plan (revision history behind the
|
|
// rules, the approved plan (revision history behind the
|
|
|
// expander), the supervision narrative (events at full weight,
|
|
// expander), the supervision narrative (events at full weight,
|
|
|
// comment events as footnotes), the comment thread with
|
|
// comment events as footnotes), the comment thread with
|
|
@@ -21,10 +26,9 @@
|
|
|
// R3/arch 15): a per-block queue that renders at the bottom of
|
|
// R3/arch 15): a per-block queue that renders at the bottom of
|
|
|
// the plan, persists across pulse refreshes (the maps live
|
|
// the plan, persists across pulse refreshes (the maps live
|
|
|
// outside statum re-renders), rides the rejection numbered, and
|
|
// outside statum re-renders), rides the rejection numbered, and
|
|
|
- // clears on accept. The status strip's
|
|
|
|
|
- // filter lives client-side in window.goalTaskFilter; clicking a
|
|
|
|
|
- // strip button re-runs the sealed refresh action, and the filter
|
|
|
|
|
- // rides the re-render.
|
|
|
|
|
|
|
+ // clears on accept. The tasks card's filter lives client-side in
|
|
|
|
|
+ // window.goalTaskFilter; clicking a strip button re-runs the
|
|
|
|
|
+ // sealed refresh action, and the filter rides the re-render.
|
|
|
if (window.statum) {
|
|
if (window.statum) {
|
|
|
(function () {
|
|
(function () {
|
|
|
'use strict';
|
|
'use strict';
|
|
@@ -63,6 +67,17 @@
|
|
|
if (document.visibilityState === 'visible') refreshGoal('focus');
|
|
if (document.visibilityState === 'visible') refreshGoal('focus');
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ // Goal 41 T6 shipped this page's sub-nav highlight inline
|
|
|
|
|
+ // (closest-to-fold - the two-column grid made the
|
|
|
|
|
+ // single-column observer rule light the wrong card); T11
|
|
|
|
|
+ // unified it with the task page's chassis into app.js's
|
|
|
|
|
+ // shared initSubnav engine, which keeps this page's
|
|
|
|
|
+ // selection rule for BOTH pages. The strip carries
|
|
|
|
|
+ // data-subnav; sections carry id + data-subnav-section.
|
|
|
|
|
+ if (window.initSubnav) {
|
|
|
|
|
+ window.initSubnav();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (window.initQuoteComments) {
|
|
if (window.initQuoteComments) {
|
|
|
window.initQuoteComments({
|
|
window.initQuoteComments({
|
|
|
matches: function (node) {
|
|
matches: function (node) {
|
|
@@ -85,11 +100,11 @@
|
|
|
// now lives once); only the block resolution is page
|
|
// now lives once); only the block resolution is page
|
|
|
// state.
|
|
// state.
|
|
|
// Plan 16 S2: the block for a review container resolves
|
|
// Plan 16 S2: the block for a review container resolves
|
|
|
- // from the ACTUAL [data-plan-review] element - the pending
|
|
|
|
|
- // completion review renders as an attention block (NOT the
|
|
|
|
|
- // plan section), so goal.plan_pending_block alone never
|
|
|
|
|
- // resolves it; every open block plus the plan section's
|
|
|
|
|
- // row are all candidates.
|
|
|
|
|
|
|
+ // from the ACTUAL [data-plan-review] element - the
|
|
|
|
|
+ // pending completion review renders as a LEADING review
|
|
|
|
|
+ // card (goal 41 T6), so goal.plan_pending_block alone
|
|
|
|
|
+ // never resolves it; the slot's three review shapes plus
|
|
|
|
|
+ // every open block are all candidates.
|
|
|
function resolveReviewBlock(id) {
|
|
function resolveReviewBlock(id) {
|
|
|
var goal = statum.read('goal');
|
|
var goal = statum.read('goal');
|
|
|
if (!goal) return null;
|
|
if (!goal) return null;
|
|
@@ -97,6 +112,10 @@
|
|
|
(goal.open_blocks || []).forEach(function (candidate) {
|
|
(goal.open_blocks || []).forEach(function (candidate) {
|
|
|
if (String(candidate.id) === String(id)) block = candidate;
|
|
if (String(candidate.id) === String(id)) block = candidate;
|
|
|
});
|
|
});
|
|
|
|
|
+ if (!block && goal.completion_pending_block
|
|
|
|
|
+ && String(goal.completion_pending_block.id) === String(id)) {
|
|
|
|
|
+ block = goal.completion_pending_block;
|
|
|
|
|
+ }
|
|
|
if (!block && goal.plan_pending_block
|
|
if (!block && goal.plan_pending_block
|
|
|
&& String(goal.plan_pending_block.id) === String(id)) {
|
|
&& String(goal.plan_pending_block.id) === String(id)) {
|
|
|
block = goal.plan_pending_block;
|
|
block = goal.plan_pending_block;
|
|
@@ -121,36 +140,177 @@
|
|
|
</head>
|
|
</head>
|
|
|
<body>
|
|
<body>
|
|
|
<div class="page goal-page">
|
|
<div class="page goal-page">
|
|
|
- <p><a href="/goals">← Goals</a></p>
|
|
|
|
|
|
|
+ <pstm-fragment name="breadcrumb" crumbs="goal.crumbs"/>
|
|
|
<h2 stm-if="goal.exists"><span class="goal-icon">🎯</span> #<span stm-text="goal.id">id</span> —
|
|
<h2 stm-if="goal.exists"><span class="goal-icon">🎯</span> #<span stm-text="goal.id">id</span> —
|
|
|
<span stm-text="goal.title">title</span></h2>
|
|
<span stm-text="goal.title">title</span></h2>
|
|
|
- <p stm-if="!goal.exists" class="muted">Goal not found.</p>
|
|
|
|
|
|
|
+ <p stm-if="!goal.exists" class="text-muted">Goal not found.</p>
|
|
|
|
|
|
|
|
<div stm-if="goal.exists">
|
|
<div stm-if="goal.exists">
|
|
|
- <!-- Status head (first, always): lifecycle badge, branch
|
|
|
|
|
- pair with the daemon-reported push-state chips,
|
|
|
|
|
- priority, timestamps, the assigned/parking agent
|
|
|
|
|
- saddle and the lifecycle actions — with full run
|
|
|
|
|
- control parity (plan 14 B1): Retry supervision for a
|
|
|
|
|
- failed goal, Requeue-to-resume for a run stale/parked
|
|
|
|
|
- on a dead saddle, Cancel. NO notify-me toggle — goals
|
|
|
|
|
- notify unconditionally by design. Yeehaw stays on
|
|
|
|
|
- task rows only. -->
|
|
|
|
|
- <section class="card goal-head">
|
|
|
|
|
|
|
+ <!-- GOAL 41 T6 (quick win 7): the one-line STATE STRIP —
|
|
|
|
|
+ the verdict without parsing the Status card: status
|
|
|
|
|
+ badge, the open-item line ("2 questions waiting · plan
|
|
|
|
|
+ revision 3 pending"), the PRIMARY lifecycle button
|
|
|
|
|
+ (the one matching the current state; the full ladder
|
|
|
|
|
+ keeps living on the Status card). Nothing else — the
|
|
|
|
|
+ strip is one glance. -->
|
|
|
|
|
+ <div class="goal-state-strip" data-goal-state-strip>
|
|
|
|
|
+ <span stm-attribute.class="'badge badge-' + goal.status"
|
|
|
|
|
+ stm-text="goal.display">status</span>
|
|
|
|
|
+ <span class="goal-state-verdict">
|
|
|
|
|
+ <span stm-if="goal.open_blocks.length == 0
|
|
|
|
|
+ && (goal.plan_pending_block == null
|
|
|
|
|
+ || goal.plan_pending_block == false)
|
|
|
|
|
+ && !goal.completion_pending"
|
|
|
|
|
+ class="text-muted">No open items — nothing waits on
|
|
|
|
|
+ you.</span>
|
|
|
|
|
+ <span stm-if="goal.plan_pending_block != null
|
|
|
|
|
+ && goal.plan_pending_block != false">
|
|
|
|
|
+ Plan revision #<span stm-text="goal.plan_pending_block.id">n</span>
|
|
|
|
|
+ pending</span>
|
|
|
|
|
+ <span stm-if="goal.completion_pending">Completion review
|
|
|
|
|
+ pending</span>
|
|
|
|
|
+ <span stm-if="goal.open_blocks.length == 1"
|
|
|
|
|
+ stm-text="'1 ' + (goal.open_blocks[0].block_type == 'question'
|
|
|
|
|
+ ? 'question' : goal.open_blocks[0].block_type)
|
|
|
|
|
+ + ' waiting'">1 waiting</span>
|
|
|
|
|
+ <span stm-if="goal.open_blocks.length > 1"
|
|
|
|
|
+ stm-text="goal.open_blocks.length + ' items waiting'">n waiting</span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span class="goal-state-actions">
|
|
|
|
|
+ <button type="button" class="btn-primary btn-sm"
|
|
|
|
|
+ stm-if="goal.start != null" stm-action="goal.start">Start
|
|
|
|
|
+ goal</button>
|
|
|
|
|
+ <button type="button" class="btn-primary btn-sm"
|
|
|
|
|
+ stm-if="goal.resume != null" stm-action="goal.resume">Resume</button>
|
|
|
|
|
+ <button type="button" class="btn-primary btn-sm"
|
|
|
|
|
+ stm-if="goal.retry_run != null" stm-action="goal.retry_run">Retry
|
|
|
|
|
+ supervision</button>
|
|
|
|
|
+ <button type="button" class="btn-primary btn-sm"
|
|
|
|
|
+ stm-if="goal.pause != null" stm-action="goal.pause">Pause</button>
|
|
|
|
|
+ <button type="button" class="btn-primary btn-sm"
|
|
|
|
|
+ stm-if="goal.requeue_run != null" stm-action="goal.requeue_run"
|
|
|
|
|
+ stm-confirm="Requeue the agent's run? The daemon restores its workspace context on the next dispatch.">Requeue
|
|
|
|
|
+ to resume</button>
|
|
|
|
|
+ <button type="button" class="btn-primary btn-sm"
|
|
|
|
|
+ stm-if="goal.force_wake != null" stm-action="goal.force_wake"
|
|
|
|
|
+ stm-confirm="Force-woke this goal's parked agent? It resumes immediately on its saddle - one wake per press.">Force
|
|
|
|
|
+ wake</button>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- GOAL 41 T6 (bet 2): the anchor sub-nav — Status ·
|
|
|
|
|
+ Blocks · Plan · Tasks · Brief · Narrative · Comments.
|
|
|
|
|
+ Sticky under the topbar (app.css reads its height);
|
|
|
|
|
+ the highlight listener lives in the page script
|
|
|
|
|
+ (rebound through statum.afterEvaluate). -->
|
|
|
|
|
+ <nav class="subnav" aria-label="Sections" data-subnav>
|
|
|
|
|
+ <a href="#goal-sec-status">Status</a>
|
|
|
|
|
+ <a href="#goal-sec-blocks">Blocks</a>
|
|
|
|
|
+ <a href="#goal-sec-plan">Plan</a>
|
|
|
|
|
+ <a href="#goal-sec-tasks">Tasks</a>
|
|
|
|
|
+ <a href="#goal-sec-brief">Brief</a>
|
|
|
|
|
+ <a href="#goal-sec-narrative">Narrative</a>
|
|
|
|
|
+ <a href="#goal-sec-comments">Comments</a>
|
|
|
|
|
+ </nav>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- GOAL 41 T6 (bet 1): Act|Consult — spry's
|
|
|
|
|
+ .with-sidebar grid with the proportions flipped (the
|
|
|
|
|
+ acting column is the wide one; app.css owns the
|
|
|
|
|
+ columns + the sub-55rem stack). ACT carries the
|
|
|
|
|
+ attention order the page already had: pending
|
|
|
|
|
+ reviews lead (actions surface), then state, blocks,
|
|
|
|
|
+ plan, comments. CONSULT carries the reference
|
|
|
|
|
+ surfaces the reader jumps to. -->
|
|
|
|
|
+ <div class="act-consult with-sidebar" data-goal-columns>
|
|
|
|
|
+ <div class="stack" data-goal-act>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- GOAL 41 T6 ("actions surface"): while a plan review is
|
|
|
|
|
+ pending, the review surface LEADS the acting column
|
|
|
|
|
+ (stm-if ordering by state) — the reader answers before
|
|
|
|
|
+ anything else. The plan-history card below renders
|
|
|
|
|
+ only when nothing is pending. -->
|
|
|
|
|
+ <section class="card plan-review-card" stm-if="goal.plan_pending_block != null && goal.plan_pending_block != false" id="goal-sec-plan-review" data-subnav-section="goal-sec-plan-review">
|
|
|
|
|
+ <h3>Plan review</h3>
|
|
|
|
|
+ <div class="plan-review" data-plan-review
|
|
|
|
|
+ stm-attribute.data-block-id="goal.plan_pending_block.id">
|
|
|
|
|
+ <h4>Plan submitted for review</h4>
|
|
|
|
|
+ <div class="md rfc-body goal-body" data-plan-body
|
|
|
|
|
+ stm-markdown="goal.plan_pending_block.body">revision</div>
|
|
|
|
|
+ <div class="actions">
|
|
|
|
|
+ <form stm-action="goal.plan_pending_block.answer_action" class="cluster">
|
|
|
|
|
+ <input type="hidden" name="verdict" value="accept">
|
|
|
|
|
+ <button type="submit" class="btn-primary" data-plan-accept>Approve plan</button>
|
|
|
|
|
+ </form>
|
|
|
|
|
+ <button type="button" data-plan-toggle>Reject with feedback</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div data-plan-feedback hidden>
|
|
|
|
|
+ <p class="text-muted">Highlight plan text to attach a remark to it — the queue
|
|
|
|
|
+ rides the rejection numbered, then clears. Approving 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="btn-primary" data-plan-submit>Submit feedback</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- GOAL 41 T6 ("actions surface"): the pending completion
|
|
|
|
|
+ review leads the acting column the same way — hoisted
|
|
|
|
|
+ out of the blocks loop (which skips review rows) and
|
|
|
|
|
+ keyed on the slot's completion_pending_block. -->
|
|
|
|
|
+ <section class="card plan-review-card" stm-if="goal.completion_pending_block != null && goal.completion_pending_block != false" id="goal-sec-completion-review" data-subnav-section="goal-sec-completion-review">
|
|
|
|
|
+ <h3>Completion review</h3>
|
|
|
|
|
+ <div class="plan-review" data-plan-review
|
|
|
|
|
+ stm-attribute.data-block-id="goal.completion_pending_block.id">
|
|
|
|
|
+ <pstm-fragment name="goal-branches"/>
|
|
|
|
|
+ <pstm-fragment name="goal-compare"/>
|
|
|
|
|
+ <div class="md rfc-body goal-body" data-plan-body
|
|
|
|
|
+ stm-markdown="goal.completion_pending_block.body">report</div>
|
|
|
|
|
+ <div class="actions">
|
|
|
|
|
+ <form stm-action="goal.completion_pending_block.answer_action" class="cluster">
|
|
|
|
|
+ <input type="hidden" name="verdict" value="accept">
|
|
|
|
|
+ <button type="submit" class="btn-primary" 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="text-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="btn-primary" data-plan-submit>Submit feedback</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Status head (first in the ACT column while no review
|
|
|
|
|
+ awaits): lifecycle badge, branch pair with the
|
|
|
|
|
+ daemon-reported push-state chips, priority,
|
|
|
|
|
+ timestamps, the assigned/parking agent saddle and
|
|
|
|
|
+ the FULL lifecycle ladder — with run control parity
|
|
|
|
|
+ (plan 14 B1): Retry supervision for a failed goal,
|
|
|
|
|
+ Requeue-to-resume for a run stale/parked on a dead
|
|
|
|
|
+ saddle, Cancel. NO notify-me toggle — goals notify
|
|
|
|
|
+ unconditionally by design. Yeehaw stays on task
|
|
|
|
|
+ rows only. The strip above carries the one-glance
|
|
|
|
|
+ verdict; this card keeps the detail. -->
|
|
|
|
|
+ <section class="card goal-head" id="goal-sec-status" data-subnav-section="goal-sec-status">
|
|
|
<div class="card-head">
|
|
<div class="card-head">
|
|
|
<h3>Status</h3>
|
|
<h3>Status</h3>
|
|
|
</div>
|
|
</div>
|
|
|
<p><span stm-attribute.class="'badge badge-' + goal.status" stm-text="goal.display">status</span>
|
|
<p><span stm-attribute.class="'badge badge-' + goal.status" stm-text="goal.display">status</span>
|
|
|
· goal branch <code stm-text="goal.branch_name">branch</code>
|
|
· goal branch <code stm-text="goal.branch_name">branch</code>
|
|
|
- <span class="muted">from</span> <code stm-text="goal.base_branch">base</code>
|
|
|
|
|
|
|
+ <span class="text-muted">from</span> <code stm-text="goal.base_branch">base</code>
|
|
|
<a stm-if="goal.compare_url.length > 0" stm-attribute.href="goal.compare_url"
|
|
<a stm-if="goal.compare_url.length > 0" stm-attribute.href="goal.compare_url"
|
|
|
- target="_blank" rel="noopener">· compare changes</a>
|
|
|
|
|
|
|
+ target="_blank" rel="noopener">· compare
|
|
|
|
|
+ changes</a>
|
|
|
· priority <strong stm-text="goal.priority">3</strong>
|
|
· priority <strong stm-text="goal.priority">3</strong>
|
|
|
<span stm-if="goal.agent_saddle.length > 0"> · agent saddle
|
|
<span stm-if="goal.agent_saddle.length > 0"> · agent saddle
|
|
|
<strong stm-text="goal.agent_saddle">saddle</strong></span></p>
|
|
<strong stm-text="goal.agent_saddle">saddle</strong></span></p>
|
|
|
<pstm-fragment name="goal-branches"
|
|
<pstm-fragment name="goal-branches"
|
|
|
note=""(the daemon's /status report)""/>
|
|
note=""(the daemon's /status report)""/>
|
|
|
- <p class="muted">Project:
|
|
|
|
|
|
|
+ <p class="text-muted">Project:
|
|
|
<a stm-attribute.href="'/projects/' + goal.project_id" stm-text="goal.project_name">project</a>
|
|
<a stm-attribute.href="'/projects/' + goal.project_id" stm-text="goal.project_name">project</a>
|
|
|
· Created <span stm-text="goal.created_display">when</span>
|
|
· Created <span stm-text="goal.created_display">when</span>
|
|
|
<span stm-if="goal.started_display.length > 0"> · Started
|
|
<span stm-if="goal.started_display.length > 0"> · Started
|
|
@@ -158,13 +318,13 @@
|
|
|
<span stm-if="goal.completed_display.length > 0"> · Finished
|
|
<span stm-if="goal.completed_display.length > 0"> · Finished
|
|
|
<span stm-text="goal.completed_display">when</span></span></p>
|
|
<span stm-text="goal.completed_display">when</span></span></p>
|
|
|
<p>
|
|
<p>
|
|
|
- <button type="button" class="primary" stm-if="goal.start != null"
|
|
|
|
|
|
|
+ <button type="button" class="btn-primary" stm-if="goal.start != null"
|
|
|
stm-action="goal.start">Start goal</button>
|
|
stm-action="goal.start">Start goal</button>
|
|
|
<button type="button" stm-if="goal.pause != null"
|
|
<button type="button" stm-if="goal.pause != null"
|
|
|
stm-action="goal.pause">Pause</button>
|
|
stm-action="goal.pause">Pause</button>
|
|
|
<button type="button" stm-if="goal.resume != null"
|
|
<button type="button" stm-if="goal.resume != null"
|
|
|
stm-action="goal.resume">Resume</button>
|
|
stm-action="goal.resume">Resume</button>
|
|
|
- <button type="button" class="primary" stm-if="goal.retry_run != null"
|
|
|
|
|
|
|
+ <button type="button" class="btn-primary" stm-if="goal.retry_run != null"
|
|
|
stm-action="goal.retry_run">Retry supervision</button>
|
|
stm-action="goal.retry_run">Retry supervision</button>
|
|
|
<button type="button" stm-if="goal.requeue_run != null"
|
|
<button type="button" stm-if="goal.requeue_run != null"
|
|
|
stm-action="goal.requeue_run"
|
|
stm-action="goal.requeue_run"
|
|
@@ -178,20 +338,20 @@
|
|
|
stm-action="goal.cancel"
|
|
stm-action="goal.cancel"
|
|
|
stm-confirm="Cancel this goal? Its tasks are cancelled with it.">Cancel goal</button>
|
|
stm-confirm="Cancel this goal? Its tasks are cancelled with it.">Cancel goal</button>
|
|
|
</p>
|
|
</p>
|
|
|
- <p class="muted" stm-if="goal.status == 'draft'">Starting locks the brief and
|
|
|
|
|
|
|
+ <p class="text-muted" stm-if="goal.status == 'draft'">Starting locks the brief and
|
|
|
hands the goal to its agent (an orchestrate-mode run task, priority 3).</p>
|
|
hands the goal to its agent (an orchestrate-mode run task, priority 3).</p>
|
|
|
- <p class="muted" stm-if="goal.status == 'paused'">Paused — supervision frozen;
|
|
|
|
|
|
|
+ <p class="text-muted" stm-if="goal.status == 'paused'">Paused — supervision frozen;
|
|
|
task events queue and coalesce into the resume.</p>
|
|
task events queue and coalesce into the resume.</p>
|
|
|
<!-- Plan 15 C4: the ONE muted activity line (the
|
|
<!-- Plan 15 C4: the ONE muted activity line (the
|
|
|
Current-activity card is gone) — what the run is
|
|
Current-activity card is gone) — what the run is
|
|
|
doing right now, folded into the status head. -->
|
|
doing right now, folded into the status head. -->
|
|
|
- <p class="muted" stm-if="goal.current_activity.length > 0"
|
|
|
|
|
|
|
+ <p class="text-muted" stm-if="goal.current_activity.length > 0"
|
|
|
stm-text="goal.current_activity">activity</p>
|
|
stm-text="goal.current_activity">activity</p>
|
|
|
- <p class="muted" stm-if="goal.saddle_health.length > 0"
|
|
|
|
|
|
|
+ <p class="text-muted" stm-if="goal.saddle_health.length > 0"
|
|
|
stm-text="goal.saddle_health">health</p>
|
|
stm-text="goal.saddle_health">health</p>
|
|
|
<!-- S5: the goal's aggregate LLM usage across its tasks
|
|
<!-- S5: the goal's aggregate LLM usage across its tasks
|
|
|
(the run plus the workers) — empty renders nothing. -->
|
|
(the run plus the workers) — empty renders nothing. -->
|
|
|
- <p class="muted" stm-if="goal.usage_line.length > 0"
|
|
|
|
|
|
|
+ <p class="text-muted" stm-if="goal.usage_line.length > 0"
|
|
|
stm-text="goal.usage_line">LLM: 1,234 calls · 45.2M in / 1.1M out tok · 3h 12m</p>
|
|
stm-text="goal.usage_line">LLM: 1,234 calls · 45.2M in / 1.1M out tok · 3h 12m</p>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
@@ -203,7 +363,7 @@
|
|
|
<section class="card">
|
|
<section class="card">
|
|
|
<h3>Agent progress</h3>
|
|
<h3>Agent progress</h3>
|
|
|
<pstm-fragment name="progress-feed" entries="goal.progress"/>
|
|
<pstm-fragment name="progress-feed" entries="goal.progress"/>
|
|
|
- <p stm-if="goal.progress.length == 0" class="muted">No progress reports yet — the goal
|
|
|
|
|
|
|
+ <p stm-if="goal.progress.length == 0" class="text-muted">No progress reports yet — the goal
|
|
|
agent reports via <code>saddle progress-update</code>.</p>
|
|
agent reports via <code>saddle progress-update</code>.</p>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
@@ -213,43 +373,18 @@
|
|
|
the historic answered ones fold behind the
|
|
the historic answered ones fold behind the
|
|
|
answered-blocks expander (the task page's pattern);
|
|
answered-blocks expander (the task page's pattern);
|
|
|
the completion review follows when one awaits. -->
|
|
the completion review follows when one awaits. -->
|
|
|
- <section class="card"
|
|
|
|
|
- stm-if="goal.open_blocks.length > 0 || goal.answered_blocks.length > 0">
|
|
|
|
|
|
|
+ <section class="card" stm-if="goal.open_blocks.length > 0 || goal.answered_blocks.length > 0" id="goal-sec-blocks" data-subnav-section="goal-sec-blocks">
|
|
|
<h3>Goal agent blocks</h3>
|
|
<h3>Goal agent blocks</h3>
|
|
|
<div stm-for-block-in="goal.open_blocks" class="goal-block">
|
|
<div stm-for-block-in="goal.open_blocks" class="goal-block">
|
|
|
- <p><span stm-attribute.class="'badge badge-block-' + block.block_type"
|
|
|
|
|
|
|
+ <!-- A pending completion review renders in the
|
|
|
|
|
+ LEADING completion-review card above (goal 41
|
|
|
|
|
+ T6 "actions surface"); the loop shows every
|
|
|
|
|
+ other open block — questions and RFCs with
|
|
|
|
|
+ full markdown bodies and inline answer forms. -->
|
|
|
|
|
+ <p stm-if="!block.is_completion_review"><span stm-attribute.class="'badge badge-block-' + block.block_type"
|
|
|
stm-text="block.block_type">kind</span>
|
|
stm-text="block.block_type">kind</span>
|
|
|
<strong stm-text="block.question">question</strong>
|
|
<strong stm-text="block.question">question</strong>
|
|
|
- <span class="muted" stm-text="block.created_display">when</span></p>
|
|
|
|
|
- <!-- The pending completion review renders in the rich
|
|
|
|
|
- review form (highlight-remarks queue shared with
|
|
|
|
|
- the plan review; push chips + compare above the
|
|
|
|
|
- report — chips are advisory, the push rule is
|
|
|
|
|
- enforced daemon-side at the agent's completion
|
|
|
|
|
- attempt). -->
|
|
|
|
|
- <div stm-if="block.is_completion_review"
|
|
|
|
|
- class="plan-review" data-plan-review
|
|
|
|
|
- stm-attribute.data-block-id="block.id">
|
|
|
|
|
- <pstm-fragment name="goal-branches"/>
|
|
|
|
|
- <pstm-fragment name="goal-compare"/>
|
|
|
|
|
- <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="verdict" value="accept">
|
|
|
|
|
- <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>
|
|
|
|
|
|
|
+ <span class="text-muted" stm-text="block.created_display">when</span></p>
|
|
|
<div stm-if="!block.is_completion_review">
|
|
<div stm-if="!block.is_completion_review">
|
|
|
<div stm-if="block.show_body && block.body.length > 0"
|
|
<div stm-if="block.show_body && block.body.length > 0"
|
|
|
class="md rfc-body goal-body" stm-markdown="block.body">body</div>
|
|
class="md rfc-body goal-body" stm-markdown="block.body">body</div>
|
|
@@ -263,7 +398,7 @@
|
|
|
<p><span stm-attribute.class="'badge badge-block-' + block.block_type"
|
|
<p><span stm-attribute.class="'badge badge-block-' + block.block_type"
|
|
|
stm-text="block.block_type">kind</span>
|
|
stm-text="block.block_type">kind</span>
|
|
|
<strong stm-text="block.question">question</strong>
|
|
<strong stm-text="block.question">question</strong>
|
|
|
- <span class="muted" stm-text="block.created_display">when</span></p>
|
|
|
|
|
|
|
+ <span class="text-muted" stm-text="block.created_display">when</span></p>
|
|
|
<div stm-if="block.show_body && block.body.length > 0"
|
|
<div stm-if="block.show_body && block.body.length > 0"
|
|
|
class="md rfc-body goal-body" stm-markdown="block.body">body</div>
|
|
class="md rfc-body goal-body" stm-markdown="block.body">body</div>
|
|
|
<blockquote stm-if="block.answered" class="term-comment-quote">
|
|
<blockquote stm-if="block.answered" class="term-comment-quote">
|
|
@@ -277,57 +412,32 @@
|
|
|
once the goal is complete/failed, with the report and
|
|
once the goal is complete/failed, with the report and
|
|
|
the compare link. While PENDING, the review lives in
|
|
the compare link. While PENDING, the review lives in
|
|
|
the attention blocks above (the rich review form). -->
|
|
the attention blocks above (the rich review form). -->
|
|
|
- <section class="card" stm-if="goal.terminal && goal.completion_report.length > 0">
|
|
|
|
|
|
|
+ <section class="card" stm-if="goal.terminal && goal.completion_report.length > 0" id="goal-sec-completion-report" data-subnav-section="goal-sec-completion-report">
|
|
|
<h3>Completion review</h3>
|
|
<h3>Completion review</h3>
|
|
|
<pstm-fragment name="goal-branches"/>
|
|
<pstm-fragment name="goal-branches"/>
|
|
|
<pstm-fragment name="goal-compare"/>
|
|
<pstm-fragment name="goal-compare"/>
|
|
|
<div class="md rfc-body goal-body" stm-markdown="goal.completion_report">report</div>
|
|
<div class="md rfc-body goal-body" stm-markdown="goal.completion_report">report</div>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
|
- <!-- The plan (plan 15 C4): BETWEEN attention and tasks.
|
|
|
|
|
- While a plan review is open the pending submission
|
|
|
|
|
- renders EXPANDED with the remarks queue (plan 14 B2);
|
|
|
|
|
- otherwise the approved plan and the revision history
|
|
|
|
|
- (approved + rejected) sit behind a collapsed
|
|
|
|
|
- expander — the goal page leads with what needs a
|
|
|
|
|
- human, not with settled history. -->
|
|
|
|
|
- <section class="card">
|
|
|
|
|
|
|
+ <!-- The plan history (plan 15 C4): the approved plan and
|
|
|
|
|
+ the revision history (approved + rejected) sit behind
|
|
|
|
|
+ a collapsed expander — the goal page leads with what
|
|
|
|
|
+ needs a human, not with settled history. While a plan
|
|
|
|
|
+ review is open the LEADING plan-review card above
|
|
|
|
|
+ carries it (this card waits below). -->
|
|
|
|
|
+ <section class="card" id="goal-sec-plan" data-subnav-section="goal-sec-plan">
|
|
|
<h3>Plan</h3>
|
|
<h3>Plan</h3>
|
|
|
|
|
|
|
|
- <div stm-if="goal.plan_pending_block != null && goal.plan_pending_block != false"
|
|
|
|
|
- class="plan-review" data-plan-review
|
|
|
|
|
- stm-attribute.data-block-id="goal.plan_pending_block.id">
|
|
|
|
|
- <h4>Plan submitted for review</h4>
|
|
|
|
|
- <div class="md rfc-body goal-body" data-plan-body
|
|
|
|
|
- stm-markdown="goal.plan_pending_block.body">revision</div>
|
|
|
|
|
- <div class="actions">
|
|
|
|
|
- <form stm-action="goal.plan_pending_block.answer_action" class="inline">
|
|
|
|
|
- <input type="hidden" name="verdict" value="accept">
|
|
|
|
|
- <button type="submit" class="approve" data-plan-accept>Approve plan</button>
|
|
|
|
|
- </form>
|
|
|
|
|
- <button type="button" data-plan-toggle>Reject with feedback</button>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div data-plan-feedback hidden>
|
|
|
|
|
- <p class="muted">Highlight plan text to attach a remark to it — the queue
|
|
|
|
|
- rides the rejection numbered, then clears. Approving 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>
|
|
|
|
|
-
|
|
|
|
|
- <details class="history-expander"
|
|
|
|
|
- stm-if="goal.plan_pending_block == null || goal.plan_pending_block == false">
|
|
|
|
|
|
|
+ <details class="history-expander">
|
|
|
<summary>Approved plan & revisions (<span
|
|
<summary>Approved plan & revisions (<span
|
|
|
stm-text="goal.plan_revisions.length">0</span>)</summary>
|
|
stm-text="goal.plan_revisions.length">0</span>)</summary>
|
|
|
<div stm-if="goal.plan.length > 0" class="md rfc-body goal-body" data-plan-body
|
|
<div stm-if="goal.plan.length > 0" class="md rfc-body goal-body" data-plan-body
|
|
|
stm-markdown="goal.plan">plan</div>
|
|
stm-markdown="goal.plan">plan</div>
|
|
|
- <p stm-if="goal.plan.length == 0" class="muted">No approved plan yet.</p>
|
|
|
|
|
|
|
+ <p stm-if="goal.plan.length == 0" class="text-muted">No approved plan yet.</p>
|
|
|
<div stm-for-revision-in="goal.plan_revisions" class="plan-revision">
|
|
<div stm-for-revision-in="goal.plan_revisions" class="plan-revision">
|
|
|
<p><span stm-attribute.class="'badge ' + (revision.approved ? 'badge-done' : (revision.answered ? 'badge-failed' : 'badge-plan'))"
|
|
<p><span stm-attribute.class="'badge ' + (revision.approved ? 'badge-done' : (revision.answered ? 'badge-failed' : 'badge-plan'))"
|
|
|
stm-text="revision.approved ? 'approved' : (revision.answered ? 'rejected' : 'pending')">verdict</span>
|
|
stm-text="revision.approved ? 'approved' : (revision.answered ? 'rejected' : 'pending')">verdict</span>
|
|
|
- <span class="muted">Revision #<span stm-text="revision.id">n</span> — <span stm-text="revision.created_display">when</span></span></p>
|
|
|
|
|
|
|
+ <span class="text-muted">Revision #<span stm-text="revision.id">n</span> — <span stm-text="revision.created_display">when</span></span></p>
|
|
|
<details>
|
|
<details>
|
|
|
<summary>Submitted markdown</summary>
|
|
<summary>Submitted markdown</summary>
|
|
|
<div class="md rfc-body" stm-markdown="revision.body">body</div>
|
|
<div class="md rfc-body" stm-markdown="revision.body">body</div>
|
|
@@ -339,10 +449,76 @@
|
|
|
</details>
|
|
</details>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
|
|
|
+ <!-- Comments with selection-quoting (markdown bodies).
|
|
|
|
|
+ Plan 15 C2: the thread IS the goal-run task's own
|
|
|
|
|
+ task_comments — the agent's pushes and the human's
|
|
|
|
|
+ composer land on the same rows; harness-authored
|
|
|
|
|
+ bookkeeping renders as distinct muted system rows,
|
|
|
|
|
+ never agent comment rows. The composer opens with
|
|
|
|
|
+ the run (a draft goal has no thread to inject into). -->
|
|
|
|
|
+ <section class="card" id="goal-sec-comments" data-subnav-section="goal-sec-comments">
|
|
|
|
|
+ <h3>Comments</h3>
|
|
|
|
|
+ <!-- Plan 15 C4: timeless-comment footnote styling —
|
|
|
|
|
+ the BODY leads; the author and time read as a
|
|
|
|
|
+ muted footnote (status belongs in progress
|
|
|
|
|
+ updates). System rows keep their labelled style. -->
|
|
|
|
|
+ <div stm-for-comment-in="goal.comments"
|
|
|
|
|
+ stm-attribute.class="'comment' + (comment.from_agent ? ' agent' : '') + (comment.is_system ? ' system' : '')">
|
|
|
|
|
+ <div class="md" stm-markdown="comment.body">body</div>
|
|
|
|
|
+ <blockquote stm-if="comment.quote.length > 0" stm-text="comment.quote">quote</blockquote>
|
|
|
|
|
+ <p class="comment-meta">
|
|
|
|
|
+ <strong stm-if="!comment.is_system" stm-text="comment.author">author</strong>
|
|
|
|
|
+ <span stm-if="comment.is_system" class="system-label">system</span>
|
|
|
|
|
+ <span class="text-muted" stm-text="comment.created_display">when</span>
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <p stm-if="goal.comments.length == 0" class="text-muted">No comments yet.</p>
|
|
|
|
|
+ <p stm-if="goal.run_task_id == 0" class="text-muted">The goal agent has not started
|
|
|
|
|
+ yet — comments open with its run.</p>
|
|
|
|
|
+ <!-- Goal 8 task 4: the composer stays OPEN on terminal
|
|
|
|
|
+ goals — a comment there re-opens the goal and
|
|
|
|
|
+ re-offers its agent's run with the comment riding
|
|
|
|
|
+ the resume (cancelled goals stay closed: their
|
|
|
|
|
+ composer keeps the run gate alone). -->
|
|
|
|
|
+ <form stm-if="goal.run_task_id > 0" stm-action="goal.comment">
|
|
|
|
|
+ <div class="field"><label for="goal-comment-body">Add comment</label>
|
|
|
|
|
+ <textarea id="goal-comment-body" name="body" rows="3"
|
|
|
|
|
+ placeholder="A timeless note for a future reader — status belongs in progress updates (markdown)"></textarea></div>
|
|
|
|
|
+ <p stm-if="goal.terminal && goal.status != 'cancelled'" class="text-muted">
|
|
|
|
|
+ This goal is terminal — commenting re-opens it: the agent resumes
|
|
|
|
|
+ with your comment and submits a fresh completion report.</p>
|
|
|
|
|
+ <button type="submit" class="btn-primary">Comment</button>
|
|
|
|
|
+ </form>
|
|
|
|
|
+ <dialog id="quote-comment-dialog" class="dialog-sm">
|
|
|
|
|
+ <div class="dialog-titlebar">
|
|
|
|
|
+ <p class="dialog-title">Comment on selected text</p>
|
|
|
|
|
+ <button type="button" class="dialog-close" aria-label="Close"
|
|
|
|
|
+ onclick="document.getElementById('quote-comment-dialog').close()">×</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <form stm-action="goal.comment">
|
|
|
|
|
+ <div class="dialog-body form-rows">
|
|
|
|
|
+ <blockquote id="quote-text" class="term-comment-quote"></blockquote>
|
|
|
|
|
+ <input type="hidden" name="quote">
|
|
|
|
|
+ <input type="hidden" name="return_to">
|
|
|
|
|
+ <textarea name="body" rows="4" placeholder="Your comment…"></textarea>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="dialog-footer">
|
|
|
|
|
+ <button type="button"
|
|
|
|
|
+ onclick="document.getElementById('quote-comment-dialog').close()">Cancel</button>
|
|
|
|
|
+ <button type="submit" class="btn-primary">Send comment</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </form>
|
|
|
|
|
+ </dialog>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ </div><!-- /data-goal-act -->
|
|
|
|
|
+
|
|
|
|
|
+ <div class="stack" data-goal-consult>
|
|
|
|
|
+
|
|
|
<!-- Task status strip + the goal's task list (plan 14 B5:
|
|
<!-- Task status strip + the goal's task list (plan 14 B5:
|
|
|
tasks above the brief; capability badges per row —
|
|
tasks above the brief; capability badges per row —
|
|
|
no editing here; yeehaw on rows only). -->
|
|
no editing here; yeehaw on rows only). -->
|
|
|
- <section class="card">
|
|
|
|
|
|
|
+ <section class="card" id="goal-sec-tasks" data-subnav-section="goal-sec-tasks">
|
|
|
<h3>Tasks</h3>
|
|
<h3>Tasks</h3>
|
|
|
<p class="goal-strip">
|
|
<p class="goal-strip">
|
|
|
<button type="button" stm-attribute.class="window.goalFilterClass('draft')"
|
|
<button type="button" stm-attribute.class="window.goalFilterClass('draft')"
|
|
@@ -360,7 +536,7 @@
|
|
|
<button type="button" stm-attribute.class="window.goalFilterClass('failed')"
|
|
<button type="button" stm-attribute.class="window.goalFilterClass('failed')"
|
|
|
onclick="window.goalSetFilter('failed')"
|
|
onclick="window.goalSetFilter('failed')"
|
|
|
stm-text="'failed ' + goal.failed_tasks">failed</button>
|
|
stm-text="'failed ' + goal.failed_tasks">failed</button>
|
|
|
- <span class="muted">— click a status to filter</span>
|
|
|
|
|
|
|
+ <span class="text-muted">— click a status to filter</span>
|
|
|
</p>
|
|
</p>
|
|
|
<table>
|
|
<table>
|
|
|
<thead><tr><th>#</th><th>Title</th><th>Status</th><th>Mode</th><th>Requires</th><th>Created by</th></tr></thead>
|
|
<thead><tr><th>#</th><th>Title</th><th>Status</th><th>Mode</th><th>Requires</th><th>Created by</th></tr></thead>
|
|
@@ -378,10 +554,10 @@
|
|
|
<td><span stm-for-capability-in="goal_task.capabilities">
|
|
<td><span stm-for-capability-in="goal_task.capabilities">
|
|
|
<span class="badge badge-capability"
|
|
<span class="badge badge-capability"
|
|
|
stm-text="capability">tag</span> </span></td>
|
|
stm-text="capability">tag</span> </span></td>
|
|
|
- <td class="muted" stm-text="goal_task.creator">who</td>
|
|
|
|
|
|
|
+ <td class="text-muted" stm-text="goal_task.creator">who</td>
|
|
|
</tr>
|
|
</tr>
|
|
|
<tr stm-if="goal.goal_tasks.length == 0">
|
|
<tr stm-if="goal.goal_tasks.length == 0">
|
|
|
- <td colspan="6" class="muted">No tasks yet — the goal agent fans
|
|
|
|
|
|
|
+ <td colspan="6" class="text-muted">No tasks yet — the goal agent fans
|
|
|
them out once the plan is approved.</td></tr>
|
|
them out once the plan is approved.</td></tr>
|
|
|
</tbody>
|
|
</tbody>
|
|
|
</table>
|
|
</table>
|
|
@@ -395,23 +571,22 @@
|
|
|
nothing else could change). Starting locks the brief:
|
|
nothing else could change). Starting locks the brief:
|
|
|
the editor's stm-if wrapper disappears with the
|
|
the editor's stm-if wrapper disappears with the
|
|
|
update action and the card stays the plain read view. -->
|
|
update action and the card stays the plain read view. -->
|
|
|
- <section class="card" data-long-form data-field="goal"
|
|
|
|
|
- data-lf-open="0">
|
|
|
|
|
|
|
+ <section class="card" data-long-form data-field="goal" data-lf-open="0" id="goal-sec-brief" data-subnav-section="goal-sec-brief">
|
|
|
<h3>Initial brief
|
|
<h3>Initial brief
|
|
|
- <button type="button" class="inline" stm-if="goal.update != null"
|
|
|
|
|
|
|
+ <button type="button" class="btn-ghost" stm-if="goal.update != null"
|
|
|
data-lf-toggle>Edit</button>
|
|
data-lf-toggle>Edit</button>
|
|
|
- <span class="muted" stm-if="goal.started_display.length > 0">(locked)</span></h3>
|
|
|
|
|
|
|
+ <span class="text-muted" stm-if="goal.started_display.length > 0">(locked)</span></h3>
|
|
|
<div data-lf-view>
|
|
<div data-lf-view>
|
|
|
<div class="md rfc-body goal-body" data-brief-body stm-markdown="goal.brief">brief</div>
|
|
<div class="md rfc-body goal-body" data-brief-body stm-markdown="goal.brief">brief</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div stm-if="goal.update != null">
|
|
<div stm-if="goal.update != null">
|
|
|
<form data-lf-edit hidden stm-action="goal.update">
|
|
<form data-lf-edit hidden stm-action="goal.update">
|
|
|
- <div class="form-row"><label>Title</label>
|
|
|
|
|
|
|
+ <div class="field"><label>Title</label>
|
|
|
<input type="text" name="title" data-lf-src="goal.title"></div>
|
|
<input type="text" name="title" data-lf-src="goal.title"></div>
|
|
|
- <div class="form-row"><label>Brief (markdown)</label>
|
|
|
|
|
|
|
+ <div class="field"><label>Brief (markdown)</label>
|
|
|
<textarea name="brief" rows="8"
|
|
<textarea name="brief" rows="8"
|
|
|
data-lf-src="goal.brief">brief</textarea></div>
|
|
data-lf-src="goal.brief">brief</textarea></div>
|
|
|
- <div class="form-row"><label>Priority (1–9)</label>
|
|
|
|
|
|
|
+ <div class="field"><label>Priority (1–9)</label>
|
|
|
<input type="number" name="priority" min="1" max="9"
|
|
<input type="number" name="priority" min="1" max="9"
|
|
|
data-lf-src="goal.priority"></div>
|
|
data-lf-src="goal.priority"></div>
|
|
|
<button type="submit">Save</button>
|
|
<button type="submit">Save</button>
|
|
@@ -426,14 +601,14 @@
|
|
|
<p stm-if="goal.links.length > 0"><span stm-for-link-in="goal.links">
|
|
<p stm-if="goal.links.length > 0"><span stm-for-link-in="goal.links">
|
|
|
<span stm-attribute.class="'badge badge-' + link.relationship"
|
|
<span stm-attribute.class="'badge badge-' + link.relationship"
|
|
|
stm-text="link.name + ' (' + link.relationship + ')'">link</span>
|
|
stm-text="link.name + ' (' + link.relationship + ')'">link</span>
|
|
|
- <button type="button" class="inline" stm-action="link.remove"
|
|
|
|
|
|
|
+ <button type="button" class="btn-ghost" stm-action="link.remove"
|
|
|
stm-confirm="Remove this link?">×</button>
|
|
stm-confirm="Remove this link?">×</button>
|
|
|
<input type="hidden" name="link_id" stm-attribute.value="link.id">
|
|
<input type="hidden" name="link_id" stm-attribute.value="link.id">
|
|
|
</span></p>
|
|
</span></p>
|
|
|
- <p stm-if="goal.links.length == 0" class="muted">Only the primary project.</p>
|
|
|
|
|
|
|
+ <p stm-if="goal.links.length == 0" class="text-muted">Only the primary project.</p>
|
|
|
<details stm-if="!goal.terminal">
|
|
<details stm-if="!goal.terminal">
|
|
|
<summary>Link a project</summary>
|
|
<summary>Link a project</summary>
|
|
|
- <form class="inline" stm-action="goal.add_link">
|
|
|
|
|
|
|
+ <form class="cluster" stm-action="goal.add_link">
|
|
|
<select name="linked_project_id" required>
|
|
<select name="linked_project_id" required>
|
|
|
<option stm-for-project-in="goal.project_options" stm-attribute.value="project.id"
|
|
<option stm-for-project-in="goal.project_options" stm-attribute.value="project.id"
|
|
|
stm-text="project.name">project</option>
|
|
stm-text="project.name">project</option>
|
|
@@ -444,7 +619,7 @@
|
|
|
</select>
|
|
</select>
|
|
|
<button type="submit">Link</button>
|
|
<button type="submit">Link</button>
|
|
|
</form>
|
|
</form>
|
|
|
- <form class="inline" stm-action="goal.apply_stack"
|
|
|
|
|
|
|
+ <form class="cluster" stm-action="goal.apply_stack"
|
|
|
stm-if="goal.stack_options.length > 0" style="margin-top: 0.5em;">
|
|
stm-if="goal.stack_options.length > 0" style="margin-top: 0.5em;">
|
|
|
<label for="goal-stack">Apply stack</label>
|
|
<label for="goal-stack">Apply stack</label>
|
|
|
<select id="goal-stack" name="stack_id" required>
|
|
<select id="goal-stack" name="stack_id" required>
|
|
@@ -460,24 +635,24 @@
|
|
|
the agent and every worker it fans out. -->
|
|
the agent and every worker it fans out. -->
|
|
|
<section class="card">
|
|
<section class="card">
|
|
|
<h3>Rules</h3>
|
|
<h3>Rules</h3>
|
|
|
- <p class="muted">The effective set dispatched with this goal's work — task rules,
|
|
|
|
|
|
|
+ <p class="text-muted">The effective set dispatched with this goal's work — task rules,
|
|
|
the primary project's, then co-developed projects' in link order.</p>
|
|
the primary project's, then co-developed projects' in link order.</p>
|
|
|
<div stm-for-rule-in="goal.rules" class="rule-card">
|
|
<div stm-for-rule-in="goal.rules" class="rule-card">
|
|
|
<h4 stm-text="rule.name">name</h4>
|
|
<h4 stm-text="rule.name">name</h4>
|
|
|
<div class="md" stm-markdown="rule.body">body</div>
|
|
<div class="md" stm-markdown="rule.body">body</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <p stm-if="goal.rules.length == 0" class="muted">No rules apply to this goal.</p>
|
|
|
|
|
|
|
+ <p stm-if="goal.rules.length == 0" class="text-muted">No rules apply to this goal.</p>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
|
<!-- The supervision narrative (plan 14 B6): state events
|
|
<!-- The supervision narrative (plan 14 B6): state events
|
|
|
at full weight, comment events as .footnote — the
|
|
at full weight, comment events as .footnote — the
|
|
|
feed reads as events-with-occasional-footnotes. -->
|
|
feed reads as events-with-occasional-footnotes. -->
|
|
|
- <section class="card">
|
|
|
|
|
|
|
+ <section class="card" id="goal-sec-narrative" data-subnav-section="goal-sec-narrative">
|
|
|
<h3>Supervision narrative</h3>
|
|
<h3>Supervision narrative</h3>
|
|
|
- <p stm-if="goal.events.length == 0" class="muted">Nothing yet — start the goal.</p>
|
|
|
|
|
|
|
+ <p stm-if="goal.events.length == 0" class="text-muted">Nothing yet — start the goal.</p>
|
|
|
<div stm-for-event-in="goal.events"
|
|
<div stm-for-event-in="goal.events"
|
|
|
stm-attribute.class="'goal-event' + (event.kind == 'comment' ? ' footnote' : '')">
|
|
stm-attribute.class="'goal-event' + (event.kind == 'comment' ? ' footnote' : '')">
|
|
|
- <span class="muted" stm-text="event.at_display">when</span>
|
|
|
|
|
|
|
+ <span class="text-muted" stm-text="event.at_display">when</span>
|
|
|
<span stm-attribute.class="'badge badge-goal-' + event.kind"
|
|
<span stm-attribute.class="'badge badge-goal-' + event.kind"
|
|
|
stm-text="event.kind.replace('-', ' ')">kind</span>
|
|
stm-text="event.kind.replace('-', ' ')">kind</span>
|
|
|
<!-- Comment events render as footnotes (plan 13 B4
|
|
<!-- Comment events render as footnotes (plan 13 B4
|
|
@@ -489,84 +664,33 @@
|
|
|
</div>
|
|
</div>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
|
- <!-- Comments with selection-quoting (markdown bodies).
|
|
|
|
|
- Plan 15 C2: the thread IS the goal-run task's own
|
|
|
|
|
- task_comments — the agent's pushes and the human's
|
|
|
|
|
- composer land on the same rows; harness-authored
|
|
|
|
|
- bookkeeping renders as distinct muted system rows,
|
|
|
|
|
- never agent comment rows. The composer opens with
|
|
|
|
|
- the run (a draft goal has no thread to inject into). -->
|
|
|
|
|
- <section class="card">
|
|
|
|
|
- <h3>Comments</h3>
|
|
|
|
|
- <!-- Plan 15 C4: timeless-comment footnote styling —
|
|
|
|
|
- the BODY leads; the author and time read as a
|
|
|
|
|
- muted footnote (status belongs in progress
|
|
|
|
|
- updates). System rows keep their labelled style. -->
|
|
|
|
|
- <div stm-for-comment-in="goal.comments"
|
|
|
|
|
- stm-attribute.class="'comment' + (comment.from_agent ? ' agent' : '') + (comment.is_system ? ' system' : '')">
|
|
|
|
|
- <div class="md" stm-markdown="comment.body">body</div>
|
|
|
|
|
- <blockquote stm-if="comment.quote.length > 0" stm-text="comment.quote">quote</blockquote>
|
|
|
|
|
- <p class="comment-meta">
|
|
|
|
|
- <strong stm-if="!comment.is_system" stm-text="comment.author">author</strong>
|
|
|
|
|
- <span stm-if="comment.is_system" class="system-label">system</span>
|
|
|
|
|
- <span class="muted" stm-text="comment.created_display">when</span>
|
|
|
|
|
- </p>
|
|
|
|
|
- </div>
|
|
|
|
|
- <p stm-if="goal.comments.length == 0" class="muted">No comments yet.</p>
|
|
|
|
|
- <p stm-if="goal.run_task_id == 0" class="muted">The goal agent has not started
|
|
|
|
|
- yet — comments open with its run.</p>
|
|
|
|
|
- <!-- Goal 8 task 4: the composer stays OPEN on terminal
|
|
|
|
|
- goals — a comment there re-opens the goal and
|
|
|
|
|
- re-offers its agent's run with the comment riding
|
|
|
|
|
- the resume (cancelled goals stay closed: their
|
|
|
|
|
- composer keeps the run gate alone). -->
|
|
|
|
|
- <form stm-if="goal.run_task_id > 0" stm-action="goal.comment">
|
|
|
|
|
- <div class="form-row"><label for="goal-comment-body">Add comment</label>
|
|
|
|
|
- <textarea id="goal-comment-body" name="body" rows="3"
|
|
|
|
|
- placeholder="A timeless note for a future reader — status belongs in progress updates (markdown)"></textarea></div>
|
|
|
|
|
- <p stm-if="goal.terminal && goal.status != 'cancelled'" class="muted">
|
|
|
|
|
- This goal is terminal — commenting re-opens it: the agent resumes
|
|
|
|
|
- with your comment and submits a fresh completion report.</p>
|
|
|
|
|
- <button type="submit" class="primary">Comment</button>
|
|
|
|
|
- </form>
|
|
|
|
|
- <dialog id="quote-comment-dialog">
|
|
|
|
|
- <h3>Comment on selected text</h3>
|
|
|
|
|
- <blockquote id="quote-text" class="term-comment-quote"></blockquote>
|
|
|
|
|
- <form stm-action="goal.comment">
|
|
|
|
|
- <input type="hidden" name="quote">
|
|
|
|
|
- <input type="hidden" name="return_to">
|
|
|
|
|
- <textarea name="body" rows="4" placeholder="Your comment…"
|
|
|
|
|
- style="width:100%; margin:0.5em 0;"></textarea>
|
|
|
|
|
- <button type="submit" class="primary">Send comment</button>
|
|
|
|
|
- <button type="button"
|
|
|
|
|
- onclick="document.getElementById('quote-comment-dialog').close()">Cancel</button>
|
|
|
|
|
- </form>
|
|
|
|
|
- </dialog>
|
|
|
|
|
- </section>
|
|
|
|
|
-
|
|
|
|
|
- <!-- Goal agent runs: every round with its host saddle; the
|
|
|
|
|
- event log links open in a new tab. -->
|
|
|
|
|
|
|
+ <!-- Goal agent runs: every round with its host saddle. Goal
|
|
|
|
|
+ 41 T7: the run links navigate SAME-TAB to the log (a
|
|
|
|
|
+ new tab severed the back button; the task page's Log
|
|
|
|
|
+ tab and this route are one feed). -->
|
|
|
<section class="card" stm-if="goal.runs.length > 0">
|
|
<section class="card" stm-if="goal.runs.length > 0">
|
|
|
<h3>Goal agent runs</h3>
|
|
<h3>Goal agent runs</h3>
|
|
|
- <p><a stm-attribute.href="'/tasks/' + goal.run_task_id + '/log'"
|
|
|
|
|
- target="_blank" rel="noopener">Event log</a>
|
|
|
|
|
- <span class="muted">— run task
|
|
|
|
|
|
|
+ <p><a stm-attribute.href="'/tasks/' + goal.run_task_id + '/log'">Event log</a>
|
|
|
|
|
+ <span class="text-muted">— run task
|
|
|
#<span stm-text="goal.run_task_id">id</span></span></p>
|
|
#<span stm-text="goal.run_task_id">id</span></span></p>
|
|
|
<table>
|
|
<table>
|
|
|
<thead><tr><th>Run</th><th>Saddle</th><th>Started</th><th>Ended</th><th>Outcome</th></tr></thead>
|
|
<thead><tr><th>Run</th><th>Saddle</th><th>Started</th><th>Ended</th><th>Outcome</th></tr></thead>
|
|
|
<tbody>
|
|
<tbody>
|
|
|
<tr stm-for-run-in="goal.runs">
|
|
<tr stm-for-run-in="goal.runs">
|
|
|
- <td><a stm-attribute.href="run.terminal_url" target="_blank" rel="noopener"
|
|
|
|
|
|
|
+ <td><a stm-attribute.href="run.terminal_url"
|
|
|
stm-text="'session ' + run.id">run</a></td>
|
|
stm-text="'session ' + run.id">run</a></td>
|
|
|
- <td class="muted" stm-text="run.saddle_name">saddle</td>
|
|
|
|
|
- <td class="muted" stm-text="run.started_display">when</td>
|
|
|
|
|
- <td class="muted" stm-text="run.ended_display">when</td>
|
|
|
|
|
|
|
+ <td class="text-muted" stm-text="run.saddle_name">saddle</td>
|
|
|
|
|
+ <td class="text-muted" stm-text="run.started_display">when</td>
|
|
|
|
|
+ <td class="text-muted" stm-text="run.ended_display">when</td>
|
|
|
<td><span stm-if="run.open" class="badge badge-working">open</span>
|
|
<td><span stm-if="run.open" class="badge badge-working">open</span>
|
|
|
<span stm-if="!run.open" stm-text="run.outcome">outcome</span></td>
|
|
<span stm-if="!run.open" stm-text="run.outcome">outcome</span></td>
|
|
|
</tr>
|
|
</tr>
|
|
|
</tbody>
|
|
</tbody>
|
|
|
</table>
|
|
</table>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
+
|
|
|
|
|
+ </div><!-- /data-goal-consult -->
|
|
|
|
|
+ </div><!-- /act-consult columns -->
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</body>
|
|
</body>
|