claude-code-session-manager 0.33.1 → 0.34.0
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/README.md +5 -1
- package/dist/assets/{TiptapBody-BqQFXHkk.js → TiptapBody-DWeWI8gw.js} +51 -51
- package/dist/assets/index-C2m4dco8.css +32 -0
- package/dist/assets/index-CFT773vM.js +3491 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/plugins/session-manager-dev/skills/discover-features/SKILL.md +95 -0
- package/plugins/session-manager-dev/skills/optimize-kpi/SKILL.md +9 -9
- package/plugins/session-manager-dev/skills/process-feedback/SKILL.md +77 -62
- package/plugins/session-manager-dev/skills/project-status/SKILL.md +13 -0
- package/src/main/__tests__/chat-queue.test.cjs +65 -0
- package/src/main/__tests__/chat-stop-signal.test.cjs +52 -0
- package/src/main/__tests__/exchanges.test.cjs +177 -0
- package/src/main/__tests__/files-reject-credentials.test.cjs +40 -0
- package/src/main/__tests__/kg-augment.test.cjs +195 -0
- package/src/main/__tests__/memoryAggregate.test.cjs +70 -0
- package/src/main/agentMemory.cjs +0 -21
- package/src/main/chatRunner.cjs +393 -0
- package/src/main/exchanges.cjs +125 -0
- package/src/main/files.cjs +20 -8
- package/src/main/historyAggregator.cjs +0 -162
- package/src/main/index.cjs +76 -57
- package/src/main/ipcSchemas.cjs +70 -30
- package/src/main/lib/kgExchangePairing.cjs +75 -0
- package/src/main/lib/reaperHelpers.cjs +7 -1
- package/src/main/lib/summarize.cjs +114 -0
- package/src/main/memoryAggregate.cjs +250 -0
- package/src/main/pluginInstall.cjs +4 -2
- package/src/main/scheduler.cjs +66 -20
- package/src/main/supervisor.cjs +16 -0
- package/src/main/transcripts.cjs +22 -2
- package/src/main/voiceHotkey.cjs +0 -2
- package/src/main/webRemote.cjs +11 -78
- package/src/preload/api.d.ts +131 -125
- package/src/preload/index.cjs +45 -29
- package/dist/assets/index-1PpZBVUr.js +0 -3535
- package/dist/assets/index-AKeGl-VM.css +0 -32
- package/src/main/kg.cjs +0 -792
- package/src/main/lib/kgLite.cjs +0 -195
- package/src/main/lib/kgPrune.cjs +0 -87
package/dist/index.html
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;0,6..72,700;1,6..72,400&family=Geist:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
10
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-CFT773vM.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/monaco-editor-BW5C4Iv1.js">
|
|
12
12
|
<link rel="stylesheet" crossorigin href="./assets/monaco-editor-BTnBOi8r.css">
|
|
13
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
13
|
+
<link rel="stylesheet" crossorigin href="./assets/index-C2m4dco8.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body class="bg-bg text-fg font-sans antialiased">
|
|
16
16
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-session-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "Local cockpit for the Claude Code CLI — multi-tab terminal, full config surface, scheduler, voice dictation, and live observability.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/main/index.cjs",
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: discover-features
|
|
3
|
+
description: >-
|
|
4
|
+
Propose and prototype NEW features for the current project. Reads the project's issues, PRs,
|
|
5
|
+
`main`, and md/docs to learn its objectives, then runs THREE independent discovery sessions
|
|
6
|
+
(each may also web-search for ideas) that every one proposes 5 high-level feature ideas best
|
|
7
|
+
fitting the project's goals — 15 total. Synthesises and ranks them, picks the top 3, and runs a
|
|
8
|
+
high-quality `/develop` build for each. Delivers a deployed URL per feature plus a validation
|
|
9
|
+
checklist so the human can try them — and NEVER opens a PR or a GitHub issue from a proposed
|
|
10
|
+
feature (the human validates first, then decides). Use when the user says "/discover-features",
|
|
11
|
+
"propose features", "discover feature opportunities", "what should we build next", "prototype
|
|
12
|
+
some new features for me to try". Keywords: discover, propose, feature, opportunity, ideation,
|
|
13
|
+
prototype, what's next, roadmap.
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# /discover-features — propose → prototype → hand over URLs (no PRs)
|
|
17
|
+
|
|
18
|
+
**Role:** the *generative* counterpart to `/find-opportunity`. `/find-opportunity` triages the
|
|
19
|
+
*existing* backlog to pick the next issue to resolve; `/discover-features` *invents* net-new
|
|
20
|
+
features the backlog doesn't contain yet, prototypes the best ones, and hands the human running
|
|
21
|
+
URLs to validate. It is for "what should we build next?", not "which open issue next?".
|
|
22
|
+
|
|
23
|
+
**Hard rules (do not violate):**
|
|
24
|
+
- **Never open a PR or a GitHub issue** from a proposed feature. The deliverable is a *running,
|
|
25
|
+
validatable prototype on a branch* + a URL + a validation checklist — the human decides what
|
|
26
|
+
(if anything) becomes a PR. (See the `solve-dont-open-issues` principle.)
|
|
27
|
+
- **No fabricated data.** Prototypes run on the project's real data layer / real queries. If a
|
|
28
|
+
feature needs data that doesn't exist, it shows an honest empty state — never seeded fakes.
|
|
29
|
+
- **Don't touch `main`.** Build on a fresh branch (or worktrees) off the latest `main`.
|
|
30
|
+
- **Respect the conflict-skip sense** (from `/find-opportunity`): don't prototype something an
|
|
31
|
+
open PR is already building.
|
|
32
|
+
|
|
33
|
+
## Phase 0 — Ground in the project's objectives
|
|
34
|
+
|
|
35
|
+
Before ideating, learn what the project is *for* (so ideas fit, not just dazzle):
|
|
36
|
+
```bash
|
|
37
|
+
gh issue list --state open --limit 100 --json number,title,labels
|
|
38
|
+
gh pr list --state all --limit 60 --json number,title,headRefName,state
|
|
39
|
+
ls docs/ README.md AGENTS.md CLAUDE.md 2>/dev/null
|
|
40
|
+
```
|
|
41
|
+
Read the design docs / README / AGENTS for the mission, the north-star, the explicit
|
|
42
|
+
non-goals/constraints, and the data model. Extract a short **objectives + constraints** brief —
|
|
43
|
+
this is the anchor every discovery session and the ranking use.
|
|
44
|
+
|
|
45
|
+
## Phase 1 — THREE independent discovery sessions (fan-out)
|
|
46
|
+
|
|
47
|
+
Spawn **3 independent agents in parallel**. Each gets the objectives brief and is told to think
|
|
48
|
+
differently from the others (assign distinct stances, e.g. *user-value first* / *data-leverage
|
|
49
|
+
first* / *differentiation-&-novelty first*). Each agent:
|
|
50
|
+
- Re-reads the issues / PRs / `main` / docs itself (independent grounding, not just your brief).
|
|
51
|
+
- **May web-search** for ideas — comparable products, domain best-practice, what peer
|
|
52
|
+
civic/▢-tech projects ship — and bring back what genuinely fits.
|
|
53
|
+
- Returns **exactly 5 high-level feature ideas**, each with: one-line pitch; which project
|
|
54
|
+
objective it advances; the data/infra it leans on (must already exist or be honestly stubbable);
|
|
55
|
+
rough surface (new route/page is preferred so it's independently deployable + validatable); a
|
|
56
|
+
novelty/effort/impact read. Be creative — no artificial limits.
|
|
57
|
+
|
|
58
|
+
15 ideas total. Keep each agent blind to the others (diversity > consensus).
|
|
59
|
+
|
|
60
|
+
## Phase 2 — Synthesise & rank → top 3
|
|
61
|
+
|
|
62
|
+
Merge the 15. De-dupe near-identicals (keep the sharpest framing). Drop anything that: an open PR
|
|
63
|
+
already builds, needs data the project doesn't have, or is a multi-week epic that can't reach a
|
|
64
|
+
*validatable* prototype in one build. Rank the survivors by **objective-fit × user-value ×
|
|
65
|
+
prototype-feasibility**. Pick the **top 3**. State *why* each won and what you dropped (no silent
|
|
66
|
+
cuts). Prefer 3 that are independently deployable (separate routes) so the human can validate each
|
|
67
|
+
in isolation.
|
|
68
|
+
|
|
69
|
+
## Phase 3 — High-quality build of each top-3 feature
|
|
70
|
+
|
|
71
|
+
For each of the 3, run a `/develop` `quality: high`-style build (deep-check → plan → implement →
|
|
72
|
+
tests → self-validate). Build all three on **one branch** (or worktrees) so a single running app
|
|
73
|
+
serves all three. Wire each as its own route/page where possible. Real data via real queries;
|
|
74
|
+
honest empty states. Typecheck + the project's tests must pass before you call a feature done.
|
|
75
|
+
|
|
76
|
+
## Phase 4 — Deploy locally & hand over (NO PR)
|
|
77
|
+
|
|
78
|
+
Launch the project's dev server (or preview) so the features are reachable. Deliver, per feature:
|
|
79
|
+
- **The URL** it's live at (e.g. `http://localhost:<port>/<route>`).
|
|
80
|
+
- **What it does** in two lines + which objective it serves.
|
|
81
|
+
- **A validation checklist** — concrete things for the human to click/observe to judge it
|
|
82
|
+
("filter to sector X, confirm the sparkline matches the table total", "open on mobile width",
|
|
83
|
+
"try an entity with no data → honest empty state").
|
|
84
|
+
- Note any assumptions or stubs.
|
|
85
|
+
|
|
86
|
+
End with: the branch name (un-pushed), the 3 URLs, and "say which to keep → I'll turn those into
|
|
87
|
+
PRs." **Do not push or PR anything yourself.**
|
|
88
|
+
|
|
89
|
+
## Notes
|
|
90
|
+
- This skill is token-intensive by design (3 discovery sessions + 3 builds). Run it when the user
|
|
91
|
+
has explicitly asked for a feature-ideation+prototype round, typically as an overnight batch.
|
|
92
|
+
- If the dev server can only serve one branch at a time, that's fine — all three features share
|
|
93
|
+
the one branch and one server; give three routes/URLs on it.
|
|
94
|
+
- Keep ideas anchored to the project's actual objectives — a brilliant idea that fights the
|
|
95
|
+
mission is noise. Creativity in service of the goal, not despite it.
|
|
@@ -4,7 +4,7 @@ description: >-
|
|
|
4
4
|
Project-agnostic North-Star-KPI optimization cycle. Reads the current project's
|
|
5
5
|
declared North-Star KPI from its CLAUDE.md, measures it, audits real
|
|
6
6
|
consumption/usage telemetry + operational logs, grades the prior iteration's
|
|
7
|
-
filed lever, then fans out 3 INDEPENDENT recommender agents (
|
|
7
|
+
filed lever, then fans out 3 INDEPENDENT recommender agents (Fable 5, max
|
|
8
8
|
thinking) that each diagnose the gap and propose the single
|
|
9
9
|
highest-leverage improvement — every recommendation grounded in usage + logs,
|
|
10
10
|
not the scorecard alone; one consolidator agent merges them into ONE feedback
|
|
@@ -14,7 +14,7 @@ description: >-
|
|
|
14
14
|
"optimize the KPI", "improve our north-star metric", or runs the daily KPI
|
|
15
15
|
optimization loop. Keywords: optimize, KPI, north-star, metric, coverage,
|
|
16
16
|
recommenders, consolidate, feedback, scheduler, attribution.
|
|
17
|
-
model:
|
|
17
|
+
model: fable
|
|
18
18
|
---
|
|
19
19
|
|
|
20
20
|
# /optimize-kpi — measure → grade last lever → 3 recommenders → consolidate → file → scheduler
|
|
@@ -158,12 +158,12 @@ the point; do not coordinate them. (Default panel = 3; you may scale to 4–5 wh
|
|
|
158
158
|
the gap is large and token budget allows, or drop to 2 for a tiny gap — note the
|
|
159
159
|
choice.)
|
|
160
160
|
|
|
161
|
-
- **Model:** `
|
|
162
|
-
with `model:
|
|
163
|
-
that one with `model:
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
161
|
+
- **Model:** `fable` (Fable 5) with **failover to `opus`, then `sonnet`** — launch
|
|
162
|
+
each agent with `model: fable`; if an agent dies on a model/availability error,
|
|
163
|
+
re-spawn that one with `model: opus`, and `sonnet` only if opus is also
|
|
164
|
+
unavailable. A **mixed panel** (some fable, some opus/sonnet) is fine — don't
|
|
165
|
+
block waiting for a uniform fleet. Instruct each to think at **maximum depth**
|
|
166
|
+
before answering.
|
|
167
167
|
- **Prompt (identical for all 3, vary only an angle hint):** give each the KPI
|
|
168
168
|
statement, the definition doc path, the Step-1 scorecard block, the **Step-1b
|
|
169
169
|
usage+log evidence block**, the **Step-2 prior-lever grade + in-flight/cooldown
|
|
@@ -197,7 +197,7 @@ choice.)
|
|
|
197
197
|
|
|
198
198
|
## Step 4 — Consolidate into ONE recommendation + a ranked backlog (single agent)
|
|
199
199
|
|
|
200
|
-
Spawn **one** consolidator agent (same `opus`→`sonnet` failover, max thinking).
|
|
200
|
+
Spawn **one** consolidator agent (same `fable`→`opus`→`sonnet` failover, max thinking).
|
|
201
201
|
Give it the 3 temp files **and** the Step-2 in-flight/cooldown set. It must:
|
|
202
202
|
|
|
203
203
|
- Read all three, dedupe overlapping ideas, and **score** the distinct proposals
|
|
@@ -3,10 +3,10 @@ name: process-feedback
|
|
|
3
3
|
description: >-
|
|
4
4
|
Process the current project's inbound feedback folder end-to-end: read every
|
|
5
5
|
open item, evaluate it against real code, and for work that belongs to this
|
|
6
|
-
project queue it as scheduled PRDs via /develop (never implement inline)
|
|
7
|
-
|
|
8
|
-
lessons back into the folder's README so
|
|
9
|
-
agents/projects) gets better. Use whenever the user says "/process-feedback",
|
|
6
|
+
project queue it as scheduled PRDs via /develop (never implement inline),
|
|
7
|
+
archive the item as processed **the moment it is queued** (the scheduler owns
|
|
8
|
+
execution from there), and fold lessons back into the folder's README so
|
|
9
|
+
future feedback (written by other agents/projects) gets better. Use whenever the user says "/process-feedback",
|
|
10
10
|
"review the feedback folder", "work through the feedback", "any open
|
|
11
11
|
feedback?", or drops new files into feedback/. Keywords: feedback, intake,
|
|
12
12
|
external-feedback, cross-project requests, process feedback, triage feedback.
|
|
@@ -30,9 +30,24 @@ conventions — read it first; the steps below are the process.
|
|
|
30
30
|
**Core principle:** this skill *triages and dispatches*; it does not implement.
|
|
31
31
|
Anything that requires writing code for this project is decomposed and queued as
|
|
32
32
|
scheduled PRDs through **`/develop`**, which runs them headlessly on the
|
|
33
|
-
session-manager scheduler. process-feedback
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
session-manager scheduler. **process-feedback is done the moment every item is
|
|
34
|
+
dispositioned — queued as a PRD, declined, or forwarded — and archived; the
|
|
35
|
+
scheduler owns execution from there on.** It does NOT hold items in the inbox
|
|
36
|
+
waiting for PRDs to land, and it does NOT babysit the scheduler. Implementing
|
|
37
|
+
feedback inline — bypassing the scheduler — is the one thing this skill must not
|
|
38
|
+
do.
|
|
39
|
+
|
|
40
|
+
**Definition of done (resilience contract):** the actionable inbox is empty.
|
|
41
|
+
Every open item has been turned into a scheduler PRD (or declined / forwarded
|
|
42
|
+
with a reason), given a `## RESOLUTION`, and moved to `processed/`. Archival
|
|
43
|
+
happens at **disposition time, not delivery time** — once an item is a queued
|
|
44
|
+
PRD, its job is done and the file is archived immediately. The README
|
|
45
|
+
status-log **row** (🛠) is the durable execution tracker that lives on after the
|
|
46
|
+
file is archived; it is reconciled 🛠→✅ (and failures flagged) by
|
|
47
|
+
`/project-status`'s scheduler-PRD audit, cross-referencing the queue — never by
|
|
48
|
+
process-feedback blocking on it. A pass that leaves a queued item sitting in the
|
|
49
|
+
inbox "until its PRD lands" is the non-resilient bug this contract exists to
|
|
50
|
+
prevent.
|
|
36
51
|
|
|
37
52
|
## Steps
|
|
38
53
|
|
|
@@ -50,14 +65,16 @@ so the empty case must cost almost nothing:
|
|
|
50
65
|
an agent loop.
|
|
51
66
|
- Only when at least one **open** item exists do you continue — an open item
|
|
52
67
|
means *someone cares about this project*, so it's worth the full pass (and,
|
|
53
|
-
per step
|
|
68
|
+
per step 6, leaving the README better for next time).
|
|
54
69
|
|
|
55
70
|
### 1. Read the intake
|
|
56
71
|
|
|
57
|
-
- Read `feedback/README.md` (conventions + the status log), then every
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
- Read `feedback/README.md` (conventions + the status log), then every open/🆕
|
|
73
|
+
file still in the inbox. Under this contract a **🛠 (queued) item has already
|
|
74
|
+
been archived to `processed/`** at disposition time — so anything still sitting
|
|
75
|
+
in the inbox is genuinely un-dispositioned and needs a pass. You will not find
|
|
76
|
+
🛠 items in the inbox to "re-check"; their execution is tracked by the
|
|
77
|
+
status-log row + `/project-status`'s scheduler audit, not by the folder.
|
|
61
78
|
- If the folder doesn't exist, say so and stop — don't invent one.
|
|
62
79
|
|
|
63
80
|
### 2. Evaluate before queueing
|
|
@@ -102,55 +119,45 @@ work — the implementation **commit + deploy**. That means process-feedback doe
|
|
|
102
119
|
|
|
103
120
|
Record the emitted PRD filenames/ids — you need them for steps 4–6.
|
|
104
121
|
|
|
105
|
-
### 4.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
### 4. Disposition + archive every item now — this is the definition of done
|
|
123
|
+
|
|
124
|
+
Every open item gets a disposition, a `## RESOLUTION`, and a `git mv` to
|
|
125
|
+
`feedback/processed/` **in this pass** — archival is at disposition time, not
|
|
126
|
+
delivery time. Do NOT leave a queued item in the inbox "until its PRD lands":
|
|
127
|
+
that is the drift this contract forbids. By disposition:
|
|
128
|
+
|
|
129
|
+
- **Queued (Ours, do it):** append `## RESOLUTION` naming the emitted PRD
|
|
130
|
+
filename(s)/id(s) and stating execution is now the scheduler's job. Set the
|
|
131
|
+
README status-log row to **🛠 queued (PRD NN)** (add 🛠 to the legend if
|
|
132
|
+
absent). `git mv` the file (and any `-REPLY`) to `processed/` **now**. The 🛠
|
|
133
|
+
row — not the file's location — is what tracks execution; do not fabricate
|
|
134
|
+
verification for code that hasn't run yet, just record the handoff.
|
|
135
|
+
- **Declined (Ours, decline):** append `## RESOLUTION` with the reason (contract
|
|
136
|
+
/ boundary conflict), flip the row to ✅, `git mv` to `processed/`.
|
|
137
|
+
- **Forwarded (Theirs):** append `## RESOLUTION` naming the upstream filing
|
|
138
|
+
(`/my-feedback to <project>` id), flip the row to ✅ (closed here — the ask now
|
|
139
|
+
lives in their intake), `git mv` to `processed/`.
|
|
140
|
+
|
|
141
|
+
After this step the actionable inbox is **empty** — only genuinely un-dispositioned
|
|
142
|
+
items (still being triaged) may remain, and only within this same pass. Commit the
|
|
143
|
+
feedback bookkeeping + any upstream filings in one clean commit (message
|
|
144
|
+
references the file id, e.g. `chore(feedback): triage + queue 2026-06-10-01`).
|
|
121
145
|
Only commit a clean, green tree; if unrelated in-flight work is mixed into the
|
|
122
146
|
working tree, stop and tell the user instead of committing around it.
|
|
123
147
|
|
|
124
|
-
### 5.
|
|
125
|
-
|
|
126
|
-
The queued PRDs run headlessly and can take a while. **Do not re-implement the
|
|
127
|
-
monitor here** — `/develop` Phase 2 already owns it (the 30-min scheduler watch,
|
|
128
|
-
the escalate-on-stuck/`needs_review`/timeout logic, and the live verification
|
|
129
|
-
against each PRD's acceptance criteria). When you call `/develop` in step 3, that
|
|
130
|
-
tracking runs as part of it.
|
|
131
|
-
|
|
132
|
-
Your only job in this step is to consume its outcome per queued item:
|
|
133
|
-
|
|
134
|
-
- **`/develop` escalated a PRD** (failed / stuck / needs attention) — relay it to
|
|
135
|
-
the user with its specifics; leave the feedback item at 🛠 (still in flight)
|
|
136
|
-
until it's resolved or re-queued. Don't archive a broken item as done.
|
|
137
|
-
- **`/develop` reported all of an item's PRDs landed + verified** — proceed to
|
|
138
|
-
step 6 to finalize that item's bookkeeping.
|
|
139
|
-
|
|
140
|
-
### 6. Finalize the archive (when an item's PRDs land + verify)
|
|
141
|
-
|
|
142
|
-
Once `/develop` Phase 2 reports an item's PRDs merged and verified against the AC:
|
|
148
|
+
### 5. Hand off to the scheduler — do NOT babysit
|
|
143
149
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
- `
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
Execution is the scheduler's job from here. **Do not run an interactive watch
|
|
151
|
+
loop, and do not block the pass on PRDs landing** — `/develop` already queued
|
|
152
|
+
them with the engineering standards inline, the scheduler runs them at its
|
|
153
|
+
cadence, and **`/project-status` owns the ongoing audit**: its scheduler-PRD
|
|
154
|
+
check cross-references `queue.json` to reconcile each 🛠 status-log row → ✅ when
|
|
155
|
+
its PRD lands (the file is already archived), and surfaces any `failed` /
|
|
156
|
+
`needs_review` / stuck Burrow PRD. If a PRD later fails, the requester re-files or
|
|
157
|
+
the status audit escalates it — the feedback pass does not stay open waiting for
|
|
158
|
+
that. If the user wants live progress, point them at the SchedulePanel.
|
|
152
159
|
|
|
153
|
-
###
|
|
160
|
+
### 6. Self-improve the intake (always do this)
|
|
154
161
|
|
|
155
162
|
Update the folder's `README.md` guidance section based on what this round
|
|
156
163
|
taught you:
|
|
@@ -172,12 +179,20 @@ This step is the point of the skill: every processing pass should make the
|
|
|
172
179
|
- **Never implement feedback inline.** Code that belongs to this project goes
|
|
173
180
|
through `/develop` → the scheduler. The only commits process-feedback makes
|
|
174
181
|
itself are feedback bookkeeping and upstream filings.
|
|
175
|
-
- **
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
- **Archive at disposition time, not delivery time.** The moment an item is
|
|
183
|
+
queued as a PRD (or declined / forwarded), give it a RESOLUTION and `git mv` it
|
|
184
|
+
to `processed/` — do NOT leave it in the inbox waiting for the PRD to land. A
|
|
185
|
+
queued item is archived with a **🛠** status-log row (not ✅); the row is the
|
|
186
|
+
durable execution tracker and is reconciled 🛠→✅ by `/project-status` from the
|
|
187
|
+
scheduler queue. Leaving dispositioned items in the inbox "until they verify"
|
|
188
|
+
is the non-resilient behavior this contract exists to kill.
|
|
189
|
+
- **The status-log row is honest about state even after archival.** 🛠 = "PRD
|
|
190
|
+
queued, scheduler owns it, not yet landed"; ✅ = "landed/verified (or
|
|
191
|
+
declined/forwarded)". Never fabricate a ✅ for code that hasn't run — archive at
|
|
192
|
+
🛠 and let the status audit flip it.
|
|
178
193
|
- Never delete feedback files to "clear" the folder — archive them.
|
|
179
194
|
- Service boundaries outrank feedback asks: an item that requests a boundary
|
|
180
195
|
violation gets a documented decline + an upstream filing, not compliance.
|
|
181
|
-
- Report honestly in the RESOLUTION:
|
|
182
|
-
|
|
183
|
-
what unblocks it.
|
|
196
|
+
- Report honestly in the RESOLUTION: which PRD id owns the work, what was
|
|
197
|
+
declined/forwarded and why, deps on other teams. An archived item with open
|
|
198
|
+
external deps should say what unblocks it.
|
|
@@ -141,6 +141,19 @@ pending feedback (cross-project asks others filed to us, plus the prior cycle's
|
|
|
141
141
|
`/my-feedback`, decline-with-reason. Don't generate new levers on top of an
|
|
142
142
|
unprocessed backlog. (If the inbox is empty, say so and move on.)
|
|
143
143
|
|
|
144
|
+
**Reconcile queued feedback — this audit owns it, because `/process-feedback`
|
|
145
|
+
hands off at queue time.** Under the resilience contract, `/process-feedback` is
|
|
146
|
+
done the moment an item is queued as a PRD and archived to `processed/` — it does
|
|
147
|
+
NOT wait for the PRD to land. So the ongoing tracking is **this skill's job**: as
|
|
148
|
+
part of the chores/scheduler audit, cross-reference the feedback status-log
|
|
149
|
+
against `queue.json` and (a) flip any **🛠** row whose PRD now shows `completed`
|
|
150
|
+
to **✅** with the landing evidence, and (b) surface any `failed` / `needs_review`
|
|
151
|
+
/ stuck Burrow PRD behind a still-🛠 row as a finding to route. The file is
|
|
152
|
+
already in `processed/`; only the row's status is reconciled here. A `-local` may
|
|
153
|
+
supply the exact cross-reference command (grep 🛠 rows → look up their PRD id in
|
|
154
|
+
the queue); if it doesn't, do it inline. Never expect `/process-feedback` to have
|
|
155
|
+
delivery-gated the archive — that's the anti-pattern this split removes.
|
|
156
|
+
|
|
144
157
|
Then route **this audit's own findings**, by ownership:
|
|
145
158
|
|
|
146
159
|
1. **A finding that belongs to another project** (an upstream/downstream service
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chat-queue.test.cjs — unit tests for the chatRunner serial run queue (v0.34).
|
|
3
|
+
* Asserts the "one loop at a time" guarantee: runs execute serially in FIFO
|
|
4
|
+
* order, and a queued (not-yet-started) run can be cancelled without running.
|
|
5
|
+
*
|
|
6
|
+
* Run: timeout 120 node --test src/main/__tests__/chat-queue.test.cjs
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
// Force the default cap (1) regardless of the developer's shell env.
|
|
12
|
+
delete process.env.SM_CHAT_CONCURRENCY;
|
|
13
|
+
|
|
14
|
+
const { test } = require('node:test');
|
|
15
|
+
const assert = require('node:assert/strict');
|
|
16
|
+
const cr = require('../chatRunner.cjs');
|
|
17
|
+
|
|
18
|
+
const tick = () => new Promise((r) => setImmediate(r));
|
|
19
|
+
const job = (id) => ({ tabId: id, sessionId: id, prompt: 'x', cwd: '/', resume: false });
|
|
20
|
+
|
|
21
|
+
test('runs execute one at a time in FIFO order', async () => {
|
|
22
|
+
const order = [];
|
|
23
|
+
let active = 0;
|
|
24
|
+
let maxActive = 0;
|
|
25
|
+
// Stub the spawn: each run resolves on the next tick, so the queue must
|
|
26
|
+
// advance via the pump's finally hook for B and C to ever run.
|
|
27
|
+
cr.__setExecutor((j) => {
|
|
28
|
+
active += 1;
|
|
29
|
+
maxActive = Math.max(maxActive, active);
|
|
30
|
+
order.push(j.tabId);
|
|
31
|
+
return new Promise((res) => setImmediate(() => { active -= 1; res(); }));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
cr.run(job('A'));
|
|
35
|
+
cr.run(job('B'));
|
|
36
|
+
cr.run(job('C'));
|
|
37
|
+
|
|
38
|
+
// Drain the queue (each run takes one tick; allow generous headroom).
|
|
39
|
+
for (let i = 0; i < 12 && order.length < 3; i++) await tick();
|
|
40
|
+
await tick();
|
|
41
|
+
|
|
42
|
+
assert.equal(maxActive, 1, 'never more than one run active at once');
|
|
43
|
+
assert.deepEqual(order, ['A', 'B', 'C'], 'runs execute in FIFO order');
|
|
44
|
+
|
|
45
|
+
cr.__setExecutor(null); // restore real executor
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('cancelling a queued run drops it without executing', async () => {
|
|
49
|
+
const order = [];
|
|
50
|
+
cr.__setExecutor((j) => {
|
|
51
|
+
order.push(j.tabId);
|
|
52
|
+
return new Promise((res) => setImmediate(res));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// X takes the only lane; Y queues behind it. Cancel Y before the lane frees.
|
|
56
|
+
cr.run(job('X'));
|
|
57
|
+
cr.run(job('Y'));
|
|
58
|
+
cr.cancel('Y'); // Y is still in the waiting list — drop it
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < 8; i++) await tick();
|
|
61
|
+
|
|
62
|
+
assert.deepEqual(order, ['X'], 'only X ran; Y was cancelled while queued');
|
|
63
|
+
|
|
64
|
+
cr.__setExecutor(null);
|
|
65
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chat-stop-signal.test.cjs — unit tests for chatRunner.parseStopSignal, the
|
|
3
|
+
* single source of truth for the terminal-chat stop-signal protocol (PRD 318).
|
|
4
|
+
*
|
|
5
|
+
* Run: timeout 120 node --test src/main/__tests__/chat-stop-signal.test.cjs
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const { test } = require('node:test');
|
|
11
|
+
const assert = require('node:assert/strict');
|
|
12
|
+
const { parseStopSignal, STOP_SENTINEL } = require('../chatRunner.cjs');
|
|
13
|
+
|
|
14
|
+
test('sentinel present with valid JSON → questions array', () => {
|
|
15
|
+
const text =
|
|
16
|
+
'I did some work but need to know which target.\n' +
|
|
17
|
+
`${STOP_SENTINEL}\n` +
|
|
18
|
+
'{"questions":["Which environment?","Overwrite existing config?"]}';
|
|
19
|
+
const out = parseStopSignal(text);
|
|
20
|
+
assert.deepEqual(out, {
|
|
21
|
+
questions: ['Which environment?', 'Overwrite existing config?'],
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('sentinel absent → null (run is complete)', () => {
|
|
26
|
+
const text = 'All done. I created the file and the tests pass.';
|
|
27
|
+
assert.equal(parseStopSignal(text), null);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('sentinel present but malformed JSON → null (treated as complete, no crash)', () => {
|
|
31
|
+
const text = `Here is a summary.\n${STOP_SENTINEL}\n{questions: [oops not json}`;
|
|
32
|
+
assert.equal(parseStopSignal(text), null);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('sentinel present but JSON lacks questions array → null', () => {
|
|
36
|
+
const text = `${STOP_SENTINEL}\n{"foo":"bar"}`;
|
|
37
|
+
assert.equal(parseStopSignal(text), null);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('non-string input → null (no crash)', () => {
|
|
41
|
+
assert.equal(parseStopSignal(undefined), null);
|
|
42
|
+
assert.equal(parseStopSignal(null), null);
|
|
43
|
+
assert.equal(parseStopSignal(42), null);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('only the LAST sentinel occurrence is parsed', () => {
|
|
47
|
+
const text =
|
|
48
|
+
`${STOP_SENTINEL}\n{"questions":["stale earlier block"]}\n` +
|
|
49
|
+
'then the agent kept working...\n' +
|
|
50
|
+
`${STOP_SENTINEL}\n{"questions":["the real question"]}`;
|
|
51
|
+
assert.deepEqual(parseStopSignal(text), { questions: ['the real question'] });
|
|
52
|
+
});
|