opencode-goal-mode 0.4.3 → 0.4.4
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/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/docs/sidebar-preview.png +0 -0
- package/package.json +1 -1
- package/plugins/goal-guard/summary.js +6 -3
- package/plugins/goal-sidebar.tsx +35 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.4.4
|
|
4
|
+
|
|
5
|
+
### Sidebar todos and gates stay correct and up to date
|
|
6
|
+
|
|
7
|
+
- **Acceptance-criterion todos now check off.** They were matched against the
|
|
8
|
+
*display-clipped* criterion text, so any criterion longer than the sidebar width
|
|
9
|
+
never showed as done even with exact matching evidence. Matching now uses the full
|
|
10
|
+
criterion text (clipping is display-only). Verified live in the OpenCode TUI.
|
|
11
|
+
- **The Goal section refreshes promptly.** It now updates on OpenCode activity
|
|
12
|
+
events (`message.part.updated`, …) — the same mechanism the reference TUI plugin
|
|
13
|
+
uses — in addition to the polling fallback, and forces a repaint on each refresh,
|
|
14
|
+
so gates and todos track the goal's real state as reviewers pass and evidence is
|
|
15
|
+
recorded instead of going stale.
|
|
16
|
+
|
|
17
|
+
### Docs
|
|
18
|
+
|
|
19
|
+
- The README preview is now a real TUI screenshot (`docs/sidebar-preview.png`).
|
|
20
|
+
|
|
3
21
|
## v0.4.3
|
|
4
22
|
|
|
5
23
|
### Build mode no longer behaves like a goal
|
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ config, including `.opencode/tui.json`. See [Installer options](#installer-optio
|
|
|
60
60
|
[](LICENSE)
|
|
61
61
|
[](package.json)
|
|
62
62
|
|
|
63
|
-

|
|
64
64
|
|
|
65
65
|
<sub>↑ In goal mode, the Goal plugin takes over the sidebar todo section with a
|
|
66
66
|
structured, evidence-aware Goal todo list — a bold `GOAL` label, then the goal
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -54,9 +54,12 @@ function sidebarTodos(state, required, missing) {
|
|
|
54
54
|
const criteria = Array.isArray(state?.contract?.acceptanceCriteria) ? state.contract.acceptanceCriteria : [];
|
|
55
55
|
const items = [];
|
|
56
56
|
for (const criterion of criteria.slice(0, 4)) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
// Match evidence against the FULL criterion text; clip only for display. (Clipping
|
|
58
|
+
// before matching meant any criterion longer than the display width never checked
|
|
59
|
+
// off — the recorded evidence carries the full text.)
|
|
60
|
+
const full = String(criterion || "").replace(/\s+/g, " ").trim();
|
|
61
|
+
if (!full) continue;
|
|
62
|
+
items.push({ status: criterionEvidenceFresh(state, full) ? "done" : "todo", text: clip(full, 52) });
|
|
60
63
|
}
|
|
61
64
|
if (state?.dirty) items.push({ status: "todo", text: "Re-verify & re-review after recent edits" });
|
|
62
65
|
// One row per missing/stale review gate, by friendly name — more scannable than a
|
package/plugins/goal-sidebar.tsx
CHANGED
|
@@ -167,9 +167,42 @@ const tui = async (api, options) => {
|
|
|
167
167
|
// Returning undefined at mount (the old behavior) meant the poll never
|
|
168
168
|
// ran and the Goal section never showed even once a goal existed.
|
|
169
169
|
const first = read();
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
// equals:false → every refresh re-notifies, so a changed snapshot always
|
|
171
|
+
// repaints (gates/todos stay live even when the new object compares equal).
|
|
172
|
+
const [model, setModel] = createSignal(first, { equals: false });
|
|
173
|
+
const refresh = () => setModel(read());
|
|
174
|
+
// Refresh on OpenCode activity. Tool calls (verdicts, evidence, edits)
|
|
175
|
+
// change the gates/todos and emit message-part events, so subscribing here
|
|
176
|
+
// keeps the section up to date promptly — this is the mechanism the
|
|
177
|
+
// reference OpenCode TUI plugin uses. The interval is a fallback for any
|
|
178
|
+
// quiet period or runtime where the event bus is unavailable.
|
|
179
|
+
const offs = [];
|
|
180
|
+
try {
|
|
181
|
+
const bus = api && api.event;
|
|
182
|
+
if (bus && typeof bus.on === "function") {
|
|
183
|
+
for (const ev of ["message.part.updated", "message.updated", "session.idle"]) {
|
|
184
|
+
try {
|
|
185
|
+
const off = bus.on(ev, refresh);
|
|
186
|
+
if (typeof off === "function") offs.push(off);
|
|
187
|
+
} catch {
|
|
188
|
+
/* unknown event type on this OpenCode build — skip it */
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
} catch {
|
|
193
|
+
/* no event bus — rely on the interval */
|
|
194
|
+
}
|
|
195
|
+
const timer = setInterval(refresh, POLL_MS);
|
|
172
196
|
onCleanup(() => clearInterval(timer));
|
|
197
|
+
onCleanup(() => {
|
|
198
|
+
for (const off of offs) {
|
|
199
|
+
try {
|
|
200
|
+
off();
|
|
201
|
+
} catch {
|
|
202
|
+
/* ignore */
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
173
206
|
// First-display rainbow: starts the moment a goal FIRST appears. If a goal
|
|
174
207
|
// is already present at mount it starts immediately; otherwise the effect
|
|
175
208
|
// fires when the goal later appears (the common case — the goal is set
|