groove-dev 0.27.113 → 0.27.116
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/CENTRAL_COMMAND_REBUILD.md +689 -0
- package/EMBEDDING_DIAGNOSTIC.md +197 -0
- package/TRAINING_DATA_v4.md +6 -0
- package/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/cli/src/commands/team.js +59 -2
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/api.js +27 -2
- package/node_modules/@groove-dev/daemon/src/filewatcher.js +45 -0
- package/node_modules/@groove-dev/daemon/src/index.js +14 -2
- package/node_modules/@groove-dev/daemon/src/process.js +254 -208
- package/node_modules/@groove-dev/daemon/src/teams.js +143 -20
- package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +78 -45
- package/node_modules/@groove-dev/gui/dist/assets/index-DdN9RVnC.css +1 -0
- package/node_modules/@groove-dev/gui/dist/assets/{index-BYh6iHqL.js → index-fq--PD7_.js} +1731 -1731
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/node_modules/@groove-dev/gui/src/components/agents/workspace-mode.jsx +0 -22
- package/node_modules/@groove-dev/gui/src/components/layout/status-bar.jsx +43 -45
- package/node_modules/@groove-dev/gui/src/components/settings/quick-connect.jsx +2 -1
- package/node_modules/@groove-dev/gui/src/components/teams/team-removal-dialog.jsx +156 -0
- package/node_modules/@groove-dev/gui/src/stores/groove.js +57 -12
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +23 -4
- package/node_modules/@groove-dev/gui/src/views/editor.jsx +1 -20
- package/node_modules/@groove-dev/gui/src/views/teams.jsx +84 -5
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/commands/team.js +59 -2
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/api.js +27 -2
- package/packages/daemon/src/filewatcher.js +45 -0
- package/packages/daemon/src/index.js +14 -2
- package/packages/daemon/src/process.js +254 -208
- package/packages/daemon/src/teams.js +143 -20
- package/packages/daemon/src/tunnel-manager.js +78 -45
- package/packages/gui/dist/assets/index-DdN9RVnC.css +1 -0
- package/packages/gui/dist/assets/{index-BYh6iHqL.js → index-fq--PD7_.js} +1731 -1731
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/components/agents/workspace-mode.jsx +0 -22
- package/packages/gui/src/components/layout/status-bar.jsx +43 -45
- package/packages/gui/src/components/settings/quick-connect.jsx +2 -1
- package/packages/gui/src/components/teams/team-removal-dialog.jsx +156 -0
- package/packages/gui/src/stores/groove.js +57 -12
- package/packages/gui/src/views/agents.jsx +23 -4
- package/packages/gui/src/views/editor.jsx +1 -20
- package/packages/gui/src/views/teams.jsx +84 -5
- package/TRAINING_DATA_v3.md +0 -11
- package/codex-test/offroad-nitro-racer/dist/assets/index-CuvdKK6U.js +0 -44
- package/codex-test/offroad-nitro-racer/dist/assets/index-DvHn2Thu.css +0 -1
- package/codex-test/offroad-nitro-racer/dist/index.html +0 -23
- package/codex-test/offroad-nitro-racer/index.html +0 -21
- package/codex-test/offroad-nitro-racer/package-lock.json +0 -841
- package/codex-test/offroad-nitro-racer/package.json +0 -15
- package/codex-test/offroad-nitro-racer/src/game/AI.ts +0 -28
- package/codex-test/offroad-nitro-racer/src/game/Audio.ts +0 -63
- package/codex-test/offroad-nitro-racer/src/game/Car.ts +0 -247
- package/codex-test/offroad-nitro-racer/src/game/Effects.ts +0 -62
- package/codex-test/offroad-nitro-racer/src/game/Game.ts +0 -229
- package/codex-test/offroad-nitro-racer/src/game/Input.ts +0 -45
- package/codex-test/offroad-nitro-racer/src/game/Renderer.ts +0 -224
- package/codex-test/offroad-nitro-racer/src/game/Track.ts +0 -158
- package/codex-test/offroad-nitro-racer/src/game/UI.ts +0 -96
- package/codex-test/offroad-nitro-racer/src/game/math.ts +0 -42
- package/codex-test/offroad-nitro-racer/src/main.ts +0 -24
- package/codex-test/offroad-nitro-racer/src/style.css +0 -291
- package/codex-test/offroad-nitro-racer/src/vite-env.d.ts +0 -1
- package/codex-test/offroad-nitro-racer/tsconfig.json +0 -18
- package/codex-test/offroad-nitro-racer/vite.config.ts +0 -7
- package/node_modules/@groove-dev/gui/dist/assets/index-DAlSbVyK.css +0 -1
- package/packages/gui/dist/assets/index-DAlSbVyK.css +0 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Embedding Service Diagnostic — Central Command Rebuild
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
After the Central Command rebuild, `session_embedding` is `null` on all SESSION_CLOSE envelopes and `domain_tags` show keyword-mode confidence (~0.067) instead of embedding-mode confidence (~0.3-0.5). Embeddings were working correctly before the rebuild (TRAINING_DATA_v3 had full 384-dim vectors on every session).
|
|
6
|
+
|
|
7
|
+
The endpoint responds to direct curl tests from a developer machine, but the Groove client is falling back to keyword mode during live sessions.
|
|
8
|
+
|
|
9
|
+
## What "working" looked like (v3 data)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
domain_tags: primary=react_frontend (0.4932)
|
|
13
|
+
session_embedding: 384d, model=sentence-transformers/all-MiniLM-L6-v2, nonzero=377/384
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## What's happening now (v4 data)
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
domain_tags: primary=nlp_llm (0.0769) ← keyword mode
|
|
20
|
+
session_embedding: null ← embed() returns null in keyword mode
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How the client decides between keyword and embedding mode
|
|
24
|
+
|
|
25
|
+
On every agent spawn, the `DomainTagger.init()` runs this sequence:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
1. POST to EMBEDDING_SERVICE_URL with {"input": "health check", "model": "sentence-transformers/all-MiniLM-L6-v2"}
|
|
29
|
+
2. If response is 200 OK:
|
|
30
|
+
a. Switch to "http" mode
|
|
31
|
+
b. Call _buildCentroids() — embeds all 40 domain descriptions (40 sequential POST calls)
|
|
32
|
+
c. If all succeeds → ready, embedding mode active
|
|
33
|
+
3. If ANYTHING fails (network error, non-200, timeout, _buildCentroids() error):
|
|
34
|
+
→ Fall back to "keyword" mode silently
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The client **never logs** why it fell back — it catches all errors silently. So the failure is invisible.
|
|
38
|
+
|
|
39
|
+
## Likely failure points (in order of probability)
|
|
40
|
+
|
|
41
|
+
### 1. `_buildCentroids()` is failing
|
|
42
|
+
|
|
43
|
+
Even if the health probe succeeds, `init()` then makes **40 sequential embed calls** to build domain centroids. If any single one fails, the whole init throws and falls back to keyword mode. The entire block is wrapped in a try/catch:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(this._serviceUrl, { ... }); // health probe
|
|
48
|
+
if (res.ok) {
|
|
49
|
+
this._mode = this._leafRegistry?.length ? 'registry' : 'http';
|
|
50
|
+
await this._buildCentroids(); // ← 40 more calls, if this throws → keyword mode
|
|
51
|
+
this._ready = true;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
// silently falls through to keyword mode
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**To check:** Look at Central Command logs during a Groove session. You should see ~41 POST requests to `/v1/embed` in quick succession (1 health probe + 40 centroid builds). If you see fewer, one is failing.
|
|
60
|
+
|
|
61
|
+
### 2. Timeout under load
|
|
62
|
+
|
|
63
|
+
The health probe has a **5-second timeout**. The centroid embed calls have a **10-second timeout** each. If the ONNX model is cold or the server is under load, individual calls might be timing out.
|
|
64
|
+
|
|
65
|
+
**To check:** Add timing logs to the `/v1/embed` endpoint:
|
|
66
|
+
```javascript
|
|
67
|
+
const start = Date.now();
|
|
68
|
+
const vector = await embed(text);
|
|
69
|
+
console.log(`[embed] ${Date.now() - start}ms "${text.slice(0, 50)}..."`);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 3. Response format mismatch
|
|
73
|
+
|
|
74
|
+
The client parses the response as:
|
|
75
|
+
```javascript
|
|
76
|
+
const data = await res.json();
|
|
77
|
+
const embedding = data?.data?.[0]?.embedding;
|
|
78
|
+
if (!Array.isArray(embedding)) {
|
|
79
|
+
// returns null — "Invalid embedding response format"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The expected response is **exactly**:
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"data": [
|
|
87
|
+
{
|
|
88
|
+
"embedding": [0.0123, -0.0456, ...384 floats],
|
|
89
|
+
"index": 0
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"model": "sentence-transformers/all-MiniLM-L6-v2"
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**To check:** Verify the response structure. Common mistakes:
|
|
97
|
+
- Returning `{ "embedding": [...] }` instead of `{ "data": [{ "embedding": [...] }] }`
|
|
98
|
+
- Returning the vector as a nested array `[[0.01, ...]]` instead of flat `[0.01, ...]`
|
|
99
|
+
- Returning Float32Array or typed array instead of plain JSON numbers
|
|
100
|
+
|
|
101
|
+
### 4. CORS or request rejection
|
|
102
|
+
|
|
103
|
+
The Groove daemon makes requests from `localhost` (or wherever it runs). If the rebuilt server has stricter CORS, different firewall rules, or middleware that rejects requests without a specific User-Agent or Origin header, the fetch would fail.
|
|
104
|
+
|
|
105
|
+
**To check:** The original Central Command had `Access-Control-Allow-Origin: *`. Verify the rebuild has the same.
|
|
106
|
+
|
|
107
|
+
### 5. URL path mismatch
|
|
108
|
+
|
|
109
|
+
The client hits exactly: `POST https://api.groovedev.ai/v1/embed`
|
|
110
|
+
|
|
111
|
+
**To check:** Verify the route is mounted at `/v1/embed`, not `/embed` or `/v1/embeddings` or `/api/v1/embed`.
|
|
112
|
+
|
|
113
|
+
## Quick diagnostic commands
|
|
114
|
+
|
|
115
|
+
Run these on the Central Command server:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# 1. Verify endpoint exists and responds correctly
|
|
119
|
+
curl -s -X POST http://localhost:8443/v1/embed \
|
|
120
|
+
-H "Content-Type: application/json" \
|
|
121
|
+
-d '{"input": "Python programming debugging testing"}' \
|
|
122
|
+
| python3 -c "
|
|
123
|
+
import sys, json
|
|
124
|
+
d = json.load(sys.stdin)
|
|
125
|
+
v = d.get('data', [{}])[0].get('embedding')
|
|
126
|
+
if v and isinstance(v, list):
|
|
127
|
+
print(f'OK: {len(v)}-dim vector, type={type(v[0]).__name__}')
|
|
128
|
+
else:
|
|
129
|
+
print(f'BROKEN: response structure = {json.dumps(d)[:200]}')"
|
|
130
|
+
|
|
131
|
+
# 2. Simulate the full init sequence (health probe + 40 centroids)
|
|
132
|
+
python3 -c "
|
|
133
|
+
import requests, time
|
|
134
|
+
url = 'http://localhost:8443/v1/embed'
|
|
135
|
+
domains = [
|
|
136
|
+
'Python programming, debugging, testing with pytest',
|
|
137
|
+
'TypeScript and Node.js backend, Express frameworks',
|
|
138
|
+
'React frontend development, JSX components, hooks',
|
|
139
|
+
# ...add all 40 domain descriptions from domain-tagger.js
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
# Health probe
|
|
143
|
+
start = time.time()
|
|
144
|
+
r = requests.post(url, json={'input': 'health check', 'model': 'sentence-transformers/all-MiniLM-L6-v2'}, timeout=5)
|
|
145
|
+
print(f'Health probe: {r.status_code} in {time.time()-start:.1f}s')
|
|
146
|
+
|
|
147
|
+
# Centroid batch
|
|
148
|
+
fails = 0
|
|
149
|
+
for i, desc in enumerate(domains):
|
|
150
|
+
try:
|
|
151
|
+
r = requests.post(url, json={'input': desc}, timeout=10)
|
|
152
|
+
d = r.json()
|
|
153
|
+
v = d.get('data', [{}])[0].get('embedding')
|
|
154
|
+
if not v or not isinstance(v, list) or len(v) != 384:
|
|
155
|
+
print(f' Domain {i}: BAD RESPONSE')
|
|
156
|
+
fails += 1
|
|
157
|
+
except Exception as e:
|
|
158
|
+
print(f' Domain {i}: FAILED - {e}')
|
|
159
|
+
fails += 1
|
|
160
|
+
|
|
161
|
+
print(f'Centroid build: {len(domains)-fails}/{len(domains)} succeeded, {fails} failed')
|
|
162
|
+
if fails > 0:
|
|
163
|
+
print('THIS IS WHY EMBEDDINGS ARE NULL - any failure causes full fallback to keyword mode')
|
|
164
|
+
"
|
|
165
|
+
|
|
166
|
+
# 3. Check response time under sequential load
|
|
167
|
+
for i in $(seq 1 10); do
|
|
168
|
+
time curl -s -X POST http://localhost:8443/v1/embed \
|
|
169
|
+
-H "Content-Type: application/json" \
|
|
170
|
+
-d "{\"input\": \"test embedding call $i\"}" > /dev/null
|
|
171
|
+
done
|
|
172
|
+
|
|
173
|
+
# 4. Check server logs during a live Groove session
|
|
174
|
+
# Start a Groove agent and watch for /v1/embed requests in the Central Command logs
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## What success looks like
|
|
178
|
+
|
|
179
|
+
After fix, a SESSION_CLOSE envelope should show:
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"metadata": {
|
|
183
|
+
"domain_tags": {
|
|
184
|
+
"primary": { "domain": "react_frontend", "confidence": 0.49 },
|
|
185
|
+
"secondary": { "domain": "vue_frontend", "confidence": 0.47 },
|
|
186
|
+
"tertiary": { "domain": "typescript_node", "confidence": 0.40 }
|
|
187
|
+
},
|
|
188
|
+
"session_embedding": {
|
|
189
|
+
"model": "sentence-transformers/all-MiniLM-L6-v2",
|
|
190
|
+
"vector": [0.0123, -0.0456, "...384 floats"],
|
|
191
|
+
"source_text": "frontend\nI'll scaffold the project..."
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Confidence scores in the 0.25-0.55 range (cosine similarity), NOT 0.06-0.08 (keyword hit ratio).
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{"envelope_id":"env_f93f9a50-bda7-453f-ac14-5fdaf7e4b9f0","session_id":"sess_a3717729-38ba-4b17-bc7b-ee6de297819c","chunk_sequence":0,"contributor_id":"23e6dd8c4a884836bf78cafda9fbe57d","attestation":{"session_hmac":"54323779fa5dd41968d8a3a47bd224c14904de2105d80c0f019fc3bce2b2242a","sequence":0,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"metadata":{"model_engine":"gpt-5.5","provider":"codex","agent_role":"planner","agent_id":"0f8f9413","task_complexity":"medium","team_size":1,"session_quality":0,"groove_version":"0.27.115","leaf_context":null},"trajectory_log":[{"step":1,"type":"thought","timestamp":1777357867.668,"content":"I’m planner-15, ready to create a team plan and route work for this project; what would you like the team to work on?","token_count":30},{"step":2,"type":"resolution","timestamp":1777357867.736,"content":"","token_count":1}]}
|
|
2
|
+
{"envelope_id":"env_b87816e2-78a0-49a7-a752-a1e4d2e254ac","session_id":"sess_a3717729-38ba-4b17-bc7b-ee6de297819c","type":"SESSION_CLOSE","attestation":{"session_hmac":"c14d57b241931c303d012250d705ac684846bb2e1ca0f54b763f0836431057cf","sequence":1,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"metadata":{"model_engine":"gpt-5.5","provider":"codex","agent_role":"planner","agent_id":"0f8f9413","task_complexity":"medium","team_size":1,"session_quality":50,"groove_version":"0.27.115","leaf_context":null,"domain_tags":{"primary":{"domain":"game_dev","confidence":0.3195},"secondary":{"domain":"terraform_iac","confidence":0.2711},"tertiary":{"domain":"data_engineering","confidence":0.2643}},"session_embedding":{"model":"sentence-transformers/all-MiniLM-L6-v2","vector":[-0.06693711876869202,0.03756159171462059,0.010457690805196762,0.04468412324786186,0.002729380503296852,-0.029737668111920357,-0.06678873300552368,0.004431950394064188,-0.029793797060847282,0.03199131786823273,-0.05346382036805153,-0.052542418241500854,-0.0896829217672348,0.06104477867484093,0.0013839079765602946,-0.0016345101175829768,-0.003324210410937667,-0.11078022420406342,-0.003062125528231263,-0.04880036041140556,-0.048932887613773346,-0.051840100437402725,0.02568761073052883,0.039964400231838226,0.001537518692202866,0.040539808571338654,0.030761633068323135,0.0491737462580204,-0.07218410819768906,-0.029797852039337158,-0.0066963909193873405,0.038294192403554916,0.015140545554459095,-0.04978591948747635,0.0278309416025877,0.06458312273025513,0.006800215691328049,-0.01994621753692627,0.059406038373708725,-0.03646699711680412,-0.01317537296563387,0.006807025521993637,-0.012372791767120361,0.007981612347066402,-0.047996290028095245,-0.06941527128219604,-0.021287590265274048,0.0697072371840477,-0.0012229934800416231,0.006396177690476179,-0.017981786280870438,-0.09368792921304703,-0.021155012771487236,-0.045693740248680115,-0.006683778017759323,0.017966078594326973,-0.05211588740348816,-0.0267979484051466,0.025201359763741493,-0.12047793716192245,-0.0361454002559185,-0.025392761453986168,-0.03815518692135811,-0.018638024106621742,-0.06582809239625931,0.0019236942753195763,0.029014267027378082,0.13426721096038818,-0.0005220572929829359,-0.05717352777719498,-0.024502145126461983,-0.04326274245977402,-0.03909342736005783,-0.009473098441958427,0.0497124008834362,0.023660186678171158,0.054812654852867126,-0.054756440222263336,0.05391204357147217,-0.04714641720056534,0.028515657410025597,0.04642858728766441,-0.04145672917366028,0.10116692632436752,-0.03991951793432236,-0.04286665841937065,0.017647257074713707,0.09745117276906967,0.03830735757946968,-0.008003407157957554,-0.014752407558262348,0.04168744012713432,0.04748523607850075,-0.02546866610646248,-0.10061267018318176,0.12033362686634064,-0.027015231549739838,-0.14085499942302704,-0.005614984314888716,0.00886533036828041,0.015765583142638206,-0.0006136206211522222,0.05842571333050728,0.016121435910463333,-0.04278235509991646,-0.0030503568705171347,0.0036935152020305395,-0.028376350179314613,-0.014532533474266529,0.04114052280783653,0.0011675329878926277,-0.021999606862664223,-0.017133478075265884,0.005161401350051165,0.0396900437772274,-0.0035789432004094124,-0.09314292669296265,0.06771265715360641,0.00790176261216402,0.07370912283658981,-0.006244460120797157,0.025356663390994072,0.03252163529396057,0.038172513246536255,0.0009429815108887851,0.026619913056492805,-0.006710680201649666,-4.834445698393237e-33,0.0317494161427021,0.07065433263778687,0.008340931497514248,0.1201411709189415,0.09289234131574631,-0.020369000732898712,0.023603154346346855,0.030785277485847473,-0.06636367738246918,0.043442901223897934,0.004750489257276058,-0.042186837643384933,0.00009028187923831865,0.05069036781787872,0.07535631954669952,-0.10499453544616699,0.014247747138142586,0.0270184725522995,-0.09973820298910141,-0.011029377579689026,-0.032685618847608566,-0.006465937942266464,0.010154122486710548,-0.02717854641377926,0.12462681531906128,0.011647133156657219,0.003071556566283107,-0.008692835457623005,0.07693301141262054,0.01446034386754036,0.024890810251235962,0.06814736872911453,-0.07334719598293304,0.002170490799471736,-0.029263827949762344,0.09250277280807495,-0.06061100587248802,-0.11188185214996338,0.03905009478330612,0.0033079206477850676,-0.03201739862561226,0.005462287459522486,-0.031173614785075188,-0.020481854677200317,0.04092852398753166,0.019254270941019058,0.03622661158442497,0.0007735321414656937,0.034228887408971786,-0.041223932057619095,-0.07547527551651001,-0.00144545070361346,-0.043760668486356735,-0.04899723082780838,0.0038046231493353844,-0.020684348419308662,0.06484944373369217,-0.05336824804544449,-0.01875849813222885,0.024013284593820572,0.04057905077934265,0.054865285754203796,-0.04459976777434349,-0.019519207999110222,0.0027556102722883224,0.020701291039586067,-0.04129016026854515,0.03876744210720062,0.18292708694934845,-0.1101064383983612,-0.01986405998468399,-0.015210955403745174,0.13115163147449493,0.05985547602176666,0.006015945225954056,0.04702761769294739,-0.016290070489048958,0.03228021785616875,-0.024850063025951385,0.026119623333215714,-0.05488264933228493,-0.006398380734026432,-0.006747493054717779,-0.005061847157776356,0.0892919972538948,0.05025973916053772,0.02357408031821251,0.09547967463731766,-0.07367022335529327,0.053491003811359406,0.006920004729181528,0.015010586939752102,0.01579098030924797,0.12157966941595078,-0.06020873785018921,1.3929382141923558e-33,0.016278034076094627,-0.014178301207721233,0.04308824986219406,-0.010197533294558525,0.11034440249204636,-0.06756774336099625,0.005605938378721476,-0.12820777297019958,0.11364550143480301,0.023939447477459908,-0.13100779056549072,-0.038116730749607086,0.02452114038169384,-0.007561508100479841,-0.04172280430793762,-0.04998759552836418,0.0445985421538353,-0.11505752056837082,0.0316021703183651,-0.007184158079326153,-0.03980126231908798,-0.007068125531077385,-0.13575677573680878,0.0429917648434639,0.023145517334342003,0.04615885391831398,0.035206861793994904,-0.13508564233779907,-0.011482535861432552,0.004406603053212166,-0.019343743100762367,-0.09097670018672943,0.02864338457584381,-0.06782244145870209,0.01546765211969614,0.019078753888607025,-0.06060025095939636,0.010488520376384258,-0.031113414093852043,0.009230522438883781,0.08841842412948608,-0.04379266873002052,0.05899025499820709,0.016347873955965042,-0.026219137012958527,0.02038387954235077,-0.014200525358319283,0.009894083254039288,-0.06384336203336716,0.0022446049842983484,0.01027018390595913,0.047613710165023804,-0.0830245241522789,-0.07711603492498398,0.017686014994978905,0.026766380295157433,0.02611905336380005,-0.07114812731742859,0.06848011165857315,0.04019796475768089,-0.0353044793009758,0.04928945004940033,0.04998962581157684,0.10279839485883713,-0.01383902132511139,0.01666494645178318,-0.027739690616726875,-0.05444987118244171,0.007934018038213253,-0.00008676606375956908,-0.036469899117946625,0.04313051328063011,0.01788181997835636,-0.0031711673364043236,0.011032620444893837,-0.08506286889314651,0.0029793395660817623,0.009692475199699402,0.012268202379345894,0.052996765822172165,-0.021802926436066628,0.04182073846459389,-0.040531259030103683,0.03108423575758934,-0.00071404327172786,0.02872210554778576,-0.02999175526201725,0.051085226237773895,0.00921647995710373,0.06241995841264725,-0.020895760506391525,-0.038975074887275696,0.04905983433127403,-0.03376005217432976,0.03695639967918396,-2.4303401957581627e-8,0.03082858957350254,0.06290039420127869,-0.005677367560565472,-0.03198196366429329,0.02765379473567009,-0.08999671041965485,-0.04596478492021561,-0.012033313512802124,0.10859999060630798,0.04584134370088577,0.041828371584415436,0.029676562175154686,-0.07500626891851425,0.010680696927011013,-0.011483248323202133,-0.010828768834471703,0.006966833490878344,0.07397440075874329,-0.027604015544056892,-0.06020504608750343,-0.021679310128092766,0.01734982803463936,-0.09294107556343079,-0.015492177568376064,0.022490480914711952,-0.016370315104722977,-0.11188998073339462,0.023930232971906662,-0.008641882799565792,0.042171284556388855,-0.01778116449713707,0.0352688692510128,0.0006121583865024149,0.05162434279918671,0.00946846418082714,-0.058817308396101,-0.06093035265803337,-0.05471249669790268,0.03433128818869591,0.024074459448456764,0.021978890523314476,0.07237174361944199,-0.05034384876489639,0.014771189540624619,-0.029563160613179207,-0.04772720858454704,-0.06582613289356232,-0.08140838891267776,-0.07585163414478302,-0.058470383286476135,-0.05282985046505928,-0.01877354271709919,0.04150386527180672,0.03611302003264427,0.12656284868717194,0.07502514123916626,-0.012954971753060818,-0.04893255606293678,0.024131637066602707,0.013823425397276878,0.022045692428946495,-0.009787112474441528,-0.10270018875598907,0.05586628243327141],"source_text":"planner\nI’m planner-15, ready to create a team plan and route work for this project; what would you like the team to work on?"}},"outcome":{"status":"SUCCESS","session_quality":50,"quality_tier":"TIER_B","quality_tier_reason":"moderate_quality","user_interventions":0,"total_steps":2,"total_chunks":1,"total_tokens":31,"duration_seconds":3,"files_modified":0,"errors_encountered":0,"errors_recovered":0,"coordination_events":0,"training_eligible":false,"training_exclusion_reason":"too_few_steps"}}
|
|
3
|
+
{"envelope_id":"env_09a682fb-de06-420a-9164-e44aa67a3520","session_id":"sess_a3717729-38ba-4b17-bc7b-ee6de297819c","type":"USER_FEEDBACK","attestation":{"session_hmac":"b3ce4560438facbc7a2719ea53aca69cd135a3edda800a692ae424fcdda33367","sequence":2,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"feedback":{"signal":"accepted","timestamp":1777357868.451,"context":"session completed successfully with no user interventions","target_step":2,"revision_rounds":0,"delta_summary":null}}
|
|
4
|
+
{"envelope_id":"env_1317b05c-9986-4d33-b386-4020575623cb","session_id":"sess_2bcbe7fe-a1b0-488e-bf66-a20381bb57ea","chunk_sequence":0,"contributor_id":"23e6dd8c4a884836bf78cafda9fbe57d","attestation":{"session_hmac":"1ff8b76c0044294d19713e0bc4b36ef76f7eae2daf6eafd0d00d11b1ed2c227c","sequence":0,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"metadata":{"model_engine":"gpt-5.5","provider":"codex","agent_role":"planner","agent_id":"c7f1a11c","task_complexity":"medium","team_size":1,"session_quality":0,"groove_version":"0.27.115","leaf_context":null},"trajectory_log":[{"step":1,"type":"thought","timestamp":1777357911.75,"content":"I’ll quickly check the team registry and the relevant app entry points, then route the work without implementing it.","token_count":29},{"step":2,"type":"action","timestamp":1777357912.464,"tool":"command_execution","arguments":{"command":"/bin/zsh -lc 'pwd && ls && (test -f AGENTS_REGISTRY.md && cat AGENTS_REGISTRY.md || true) && (test -f .groove/recommended-team.json && cat .groove/recommended-team.json || true)'"},"content":"Executing: /bin/zsh -lc 'pwd && ls && (test -f AGENTS_REGISTRY.md && cat AGENTS_REGISTRY.md || true) && (test -f .groove/recommended-team.json && cat .groove/recommended-team.json || true)'","token_count":96},{"step":3,"type":"observation","timestamp":1777357912.512,"is_error":false,"content":"~/Desktop/groove-project/groove/codex\n","truncated":false,"original_token_count":12,"token_count":10},{"step":4,"type":"thought","timestamp":1777357919.886,"content":"No registry surfaced in the current folder, so I’m checking hidden project metadata and nearby package hints.","token_count":28},{"step":5,"type":"action","timestamp":1777357920.233,"tool":"command_execution","arguments":{"command":"/bin/zsh -lc \"ls -la && find . -maxdepth 3 -type f \\\\( -name 'AGENTS_REGISTRY.md' -o -name 'recommended-team.json' -o -name 'package.json' -o -name 'README.md' \\\\) -print\""},"content":"Executing: /bin/zsh -lc \"ls -la && find . -maxdepth 3 -type f \\\\( -name 'AGENTS_REGISTRY.md' -o -name 'recommended-team.json' -o -name 'package.json' -o -name 'README.md' \\\\) -print\"","token_count":94},{"step":6,"type":"observation","timestamp":1777357920.285,"is_error":false,"content":"total 0\ndrwxr-xr-x@ 2 rok staff 64 Apr 27 23:30 .\ndrwxr-xr-x@ 52 rok staff 1664 Apr 27 23:31 ..\n","truncated":false,"original_token_count":26,"token_count":26},{"step":7,"type":"thought","timestamp":1777357941.242,"content":"I’ll create the routing config for a new static landing-page project in this empty workspace.","token_count":24},{"step":8,"type":"action","timestamp":1777357947.238,"tool":"command_execution","arguments":{"command":"/bin/zsh -lc \"mkdir -p .groove && cat > .groove/recommended-team.json <<'EOF'\n{\n \\\"projectDir\\\": \\\"coming-soon-landing\\\",\n \\\"agents\\\": [\n {\n \\\"role\\\": \\\"frontend\\\",\n \\\"phase\\\": 1,\n \\\"scope\\\": [\n \\\"**/*\\\"\n ],\n \\\"prompt\\\": \\\"Build a basic static coming-soon landing page with a 5-day countdown. Create a small self-contained site in this project directory with an index.html entry point plus any needed CSS/JS assets. The page should include a clear product/brand placeholder headline, short supporting copy, email signup UI as a non-submitting visual form or safe mailto-free placeholder, and a responsive countdown showing days, hours, minutes, and seconds. The countdown should start at 5 days for a first-time visitor and persist the target timestamp in localStorage so refreshing does not reset it. Keep the design polished but lightweight, mobile-friendly, accessible, and dependency-free unless a minimal toolchain is already created by you. Do not delete unrelated files.\\\"\n },\n {\n \\\"role\\\": \\\"fullstack\\\",\n \\\"phase\\\": 2,\n \\\"scope\\\": [],\n \\\"prompt\\\": \\\"QC Senior Dev: Audit the frontend landing page for correctness, accessibility, responsiveness, and countdown behavior. Verify the countdown persists across refreshes via localStorage and handles expiry cleanly. Run any available validation/build commands if the frontend agent added a toolchain; otherwise inspect the static files directly. Do NOT start long-running dev servers. Do NOT open files in a browser with an 'open' command. Commit all changes.\\\"\n }\n ],\n \\\"preview\\\": {\n \\\"kind\\\": \\\"static-html\\\",\n \\\"command\\\": \\\"\\\",\n \\\"openPath\\\": \\\"index.html\\\"\n }\n}\nEOF\ncat .groove/recommended-team.json\""},"content":"Executing: /bin/zsh -lc \"mkdir -p .groove && cat > .groove/recommended-team.json <<'EOF'\n{\n \\\"projectDir\\\": \\\"coming-soon-landing\\\",\n \\\"agents\\\": [\n {\n \\\"role\\\": \\\"frontend\\\",\n \\\"phase\\\": 1,\n \\\"scope\\\": [\n \\\"**/*\\\"\n ],\n \\\"prompt\\\": \\\"Build a basic static coming-soon landing page with a 5-day countdown. Create a small self-contained site in this project directory with an index.html entry point plus any needed CSS/JS assets. The page should include a clear product/brand placeholder headline, short supporting copy, email signup UI as a non-submitting visual form or safe mailto-free placeholder, and a responsive countdown showing days, hours, minutes, and seconds. The countdown should start at 5 days for a first-time visitor and persist the target timestamp in localStorage so refreshing does not reset it. Keep the design polished but lightweight, mobile-friendly, accessible, and dependency-free unless a minimal toolchain is already created by you. Do not delete unrelated files.\\\"\n },\n {\n \\\"role\\\": \\\"fullstack\\\",\n \\\"phase\\\": 2,\n \\\"scope\\\": [],\n \\\"prompt\\\": \\\"QC Senior Dev: Audit the frontend landing page for correctness, accessibility, responsiveness, and countdown behavior. Verify the countdown persists across refreshes via localStorage and handles expiry cleanly. Run any available validation/build commands if the frontend agent added a toolchain; otherwise inspect the static files directly. Do NOT start long-running dev servers. Do NOT open files in a browser with an 'open' command. Commit all changes.\\\"\n }\n ],\n \\\"preview\\\": {\n \\\"kind\\\": \\\"static-html\\\",\n \\\"command\\\": \\\"\\\",\n \\\"openPath\\\": \\\"index.html\\\"\n }\n}\nEOF\ncat .groove/recommended-team.json\"","token_count":906},{"step":9,"type":"observation","timestamp":1777357947.29,"is_error":false,"content":"{\n \"projectDir\": \"coming-soon-landing\",\n \"agents\": [\n {\n \"role\": \"frontend\",\n \"phase\": 1,\n \"scope\": [\n \"**/*\"\n ],\n \"prompt\": \"Build a basic static coming-soon landing page with a 5-day countdown. Create a small self-contained site in this project directory with an index.html entry point plus any needed CSS/JS assets. The page should include a clear product/brand placeholder headline, short supporting copy, email signup UI as a non-submitting visual form or safe mailto-free placeholder, and a responsive countdown showing days, hours, minutes, and seconds. The countdown should start at 5 days for a first-time visitor and persist the target timestamp in localStorage so refreshing does not reset it. Keep the design polished but lightweight, mobile-friendly, accessible, and dependency-free unless a minimal toolchain is already created by you. Do not delete unrelated files.\"\n },\n {\n \"role\": \"fullstack\",\n \"phase\": 2,\n \"scope\": [],\n \"prompt\": \"QC Senior Dev: Audit the frontend landing page for correctness, accessibility, responsiveness, and countdown behavior. Verify the countdown persists across refreshes via localStorage and handles expiry cleanly. Run any available validation/build commands if the frontend agent added a toolchain; otherwise inspect the static files directly. Do NOT start long-running dev servers. Do NOT open files in a browser with an 'open' command. Commit all changes.\"\n }\n ],\n \"preview\": {\n \"kind\": \"static-html\",\n \"command\": \"\",\n \"openPath\": \"index.html\"\n }\n}\n","truncated":false,"original_token_count":394,"token_count":394},{"step":10,"type":"thought","timestamp":1777357951.62,"content":"Routing plan written to `.groove/recommended-team.json:1`.\n\n- Created a new-project team plan for `coming-soon-landing`.\n- Assigned `frontend` to build a static `index.html` coming-soon page with a persisted 5-day countdown.\n- Assigned `fullstack` as phase 2 QC to verify responsiveness, accessibility, countdown persistence, and expiry behavior.\n- Configured preview as `static-html` opening `index.html`.\n\nNo source code was implemented by me.","token_count":112},{"step":11,"type":"resolution","timestamp":1777357951.695,"content":"","token_count":1}]}
|
|
5
|
+
{"envelope_id":"env_35478843-ef60-461d-b3ce-422d07270005","session_id":"sess_2bcbe7fe-a1b0-488e-bf66-a20381bb57ea","type":"SESSION_CLOSE","attestation":{"session_hmac":"47fb2e06056a87f6491a6ac83f84e2f169090d33732da961f2ad2fd2a81393eb","sequence":1,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"metadata":{"model_engine":"gpt-5.5","provider":"codex","agent_role":"planner","agent_id":"c7f1a11c","task_complexity":"medium","team_size":1,"session_quality":60,"groove_version":"0.27.115","leaf_context":null,"domain_tags":{"primary":{"domain":"ci_cd","confidence":0.2656},"secondary":{"domain":"terraform_iac","confidence":0.2173},"tertiary":{"domain":"csharp_dotnet","confidence":0.1886}},"session_embedding":{"model":"sentence-transformers/all-MiniLM-L6-v2","vector":[-0.02388685755431652,-0.060105498880147934,-0.023632973432540894,0.0032994654029607773,0.01703188754618168,-0.027073629200458527,-0.06481088697910309,-0.017189089208841324,-0.05652660131454468,0.014533017762005329,-0.01777762547135353,0.02002338506281376,-0.05209732800722122,0.04445069283246994,-0.007964960299432278,0.04861873760819435,-0.012648002244532108,-0.08211388438940048,0.051421307027339935,-0.029105566442012787,0.0005955102969892323,0.022396843880414963,0.022131549194455147,0.04424780607223511,-0.01220770739018917,0.004836526699364185,0.028830472379922867,0.041462864726781845,0.026998143643140793,-0.000980757991783321,0.012424197047948837,0.11313086003065109,-0.07381390035152435,-0.01920468732714653,0.13104867935180664,0.07106650620698929,0.03553297743201256,0.010054200887680054,0.023640574887394905,-0.026549845933914185,0.0605519637465477,0.015304633416235447,0.03918188437819481,0.04107779636979103,-0.01577165350317955,-0.06581766158342361,0.0033992244862020016,-0.0348748154938221,0.005415500141680241,-0.0031897486187517643,0.03264386206865311,-0.09864047169685364,0.02709083817899227,-0.08861556649208069,-0.000052495539421215653,0.06640173494815826,0.04121771827340126,0.0004893096629530191,-0.00977682787925005,-0.07920201122760773,0.13322006165981293,-0.043157704174518585,-0.016540568321943283,-0.054678160697221756,-0.095985047519207,0.05884283408522606,0.0032373068388551474,0.009309493005275726,0.08217776566743851,-0.05484403297305107,-0.07754853367805481,-0.019648581743240356,-0.027543600648641586,-0.027237258851528168,0.02558710239827633,0.00013364652113523334,0.023264585062861443,0.0011471020989120007,0.06965775042772293,-0.13843274116516113,0.08088801056146622,0.013594448566436768,0.029804017394781113,0.12125246226787567,0.033591799437999725,-0.05364574119448662,0.018196476623415947,0.009922769851982594,0.09473657608032227,0.07483018189668655,-0.03030695952475071,-0.048255182802677155,0.0418412871658802,-0.07262617349624634,-0.11693336069583893,0.05892452597618103,-0.038537364453077316,-0.03292952477931976,-0.030068717896938324,0.08499839156866074,-0.05652804300189018,-0.02501920610666275,0.03261302784085274,0.021289926022291183,0.028933417052030563,0.022540424019098282,0.04930088669061661,-0.011273123323917389,-0.0009935525013133883,0.0701846033334732,-0.01747896708548069,-0.01582796312868595,0.007453564554452896,0.0068029495887458324,-0.07404918223619461,-0.00664112251251936,-0.023154813796281815,0.001421975321136415,-0.055900655686855316,0.021410414949059486,-0.03479393199086189,0.0009077505674213171,0.0983644649386406,0.031113509088754654,-0.02366735227406025,-0.017292210832238197,-0.05703660100698471,9.485468911323095e-34,0.049997519701719284,0.08261831104755402,-0.015507739037275314,0.027001556009054184,0.04633799567818642,-0.09600644558668137,0.03635014221072197,0.010093399323523045,-0.003712594276294112,-0.00631878525018692,-0.026720624417066574,0.010993762873113155,0.07502569258213043,-0.00509985676035285,-0.01989608444273472,-0.05150638148188591,0.0054930527694523335,0.03485715761780739,-0.001701683853752911,-0.06095350533723831,-0.05227480083703995,-0.04240967705845833,-0.03602784126996994,-0.07175292074680328,0.12459434568881989,0.054003290832042694,-0.027733396738767624,0.022252900525927544,0.049904536455869675,0.019711073487997055,0.04208594188094139,0.0926598459482193,0.011147594079375267,0.03464190661907196,-0.059706829488277435,0.0705917552113533,-0.06051686778664589,-0.09401654452085495,0.05709428712725639,0.1019669696688652,-0.005356642417609692,-0.036960046738386154,-0.039272770285606384,-0.04939410835504532,0.014264113269746304,-0.03555767238140106,-0.013013712130486965,-0.051901645958423615,0.17037756741046906,-0.03869776427745819,-0.017398767173290253,-0.020863287150859833,-0.0091478256508708,0.030313894152641296,-0.009502967819571495,-0.10463112592697144,-0.034701697528362274,-0.029594063758850098,0.08568678051233292,0.028067853301763535,0.00702727772295475,-0.020609155297279358,-0.0953810065984726,0.04143253341317177,-0.027815813198685646,0.02031555026769638,-0.06704629212617874,0.044165097177028656,0.08477029949426651,-0.09975844621658325,0.01727958954870701,0.000894423050340265,0.08260852843523026,0.0006351986667141318,-0.02283228561282158,0.028247075155377388,-0.05774255469441414,0.05414297804236412,-0.0931570902466774,0.013774513266980648,0.013258248567581177,0.009294215589761734,0.004645416978746653,0.025863856077194214,0.03964362293481827,-0.02484980970621109,0.029589718207716942,0.03249607980251312,-0.035005245357751846,0.08652828633785248,-0.035142406821250916,-0.00884088221937418,-0.029139533638954163,0.12507598102092743,0.02195696160197258,-3.289483573169272e-37,0.018034616485238075,0.019557246938347816,-0.033867284655570984,0.002278698608279228,0.03126790374517441,-0.02864532545208931,0.06274496018886566,-0.05692826583981514,0.04448181763291359,0.0591057650744915,-0.04386522248387337,0.02608109451830387,0.01508491113781929,-0.041225191205739975,-0.002441790420562029,-0.035356178879737854,0.0071209389716386795,-0.054987628012895584,0.04377412423491478,0.04183093085885048,-0.00621685478836298,-0.031353116035461426,-0.10444547981023788,-0.0833139568567276,0.05675416439771652,0.0362086184322834,0.04481751471757889,-0.04107509180903435,-0.07948796451091766,0.003126996336504817,-0.010310756973922253,-0.003558435710147023,-0.048596419394016266,-0.11138182133436203,0.02340853400528431,0.06813378632068634,-0.13512185215950012,0.01128294039517641,-0.024462617933750153,-0.06024760380387306,0.06362652033567429,-0.004108428955078125,-0.020379841327667236,0.09104712307453156,0.009642861783504486,0.0021345391869544983,0.07418365031480789,-0.033214300870895386,-0.02716899663209915,-0.029562801122665405,0.04602033272385597,0.01990636996924877,-0.04943450540304184,-0.038352664560079575,0.005142817273736,0.16565272212028503,0.008641287684440613,-0.03526175022125244,-0.01924167387187481,0.010664568282663822,0.054390184581279755,-0.008514161221683025,-0.0618470199406147,0.10752137005329132,0.014099428430199623,-0.00508504081517458,-0.009550908580422401,0.08488281816244125,-0.037636417895555496,0.03946157544851303,-0.10607825964689255,0.042513005435466766,0.025197044014930725,0.013312465511262417,0.010461016558110714,-0.053037941455841064,0.08911341428756714,0.016598965972661972,0.025846417993307114,0.01968512125313282,-0.061517030000686646,0.02003258280456066,-0.042076341807842255,-0.057019345462322235,0.005304405931383371,0.021328125149011612,-0.05654192343354225,0.06762088090181351,-0.03129829466342926,0.07132996618747711,-0.01712295040488243,-0.03540065884590149,0.06953057646751404,-0.034674271941185,0.0068288929760456085,-4.765118788441214e-8,0.021352697163820267,0.1262984275817871,-0.006307561881840229,-0.03768131881952286,0.04515105113387108,0.030682465061545372,0.022922370582818985,0.03771546110510826,0.06148586794734001,0.05424340069293976,-0.05243263766169548,-0.008472433313727379,-0.0981537327170372,0.07113897800445557,-0.054021935909986496,-0.013147328980267048,-0.003634627675637603,0.0749971941113472,-0.08111397922039032,-0.08387390524148941,-0.08342036604881287,0.01695854775607586,-0.026544621214270592,0.0368790365755558,-0.016829654574394226,0.035303663462400436,-0.03214229643344879,-0.01911233365535736,0.043698012828826904,0.0414605550467968,-0.03473788499832153,0.06389732658863068,-0.045386821031570435,0.04035051539540291,-0.026537632569670677,0.040752001106739044,-0.0030007059685885906,0.008067303337156773,0.00835010688751936,0.0029566672164946795,0.029438525438308716,0.04444463551044464,0.006823315285146236,-0.0028545972891151905,-0.01422444824129343,0.0022671471815556288,-0.027213815599679947,-0.047464873641729355,0.0025221756659448147,-0.06314513832330704,-0.090935617685318,-0.010546295903623104,-0.012237844057381153,0.06477628648281097,0.0828094407916069,0.08613219857215881,-0.03376612439751625,-0.11163280159235,0.018945032730698586,0.02491677738726139,-0.03860095888376236,-0.04143964871764183,-0.048489443957805634,-0.021546607837080956],"source_text":"planner\nI’ll quickly check the team registry and the relevant app entry points, then route the work without implementing it.\nNo registry surfaced in the current folder, so I’m checking hidden project metadata and nearby package hints.\nI’ll create the routing config for a new static landing-page project in this empty workspace."}},"outcome":{"status":"SUCCESS","session_quality":60,"quality_tier":"TIER_B","quality_tier_reason":"moderate_quality","user_interventions":0,"total_steps":11,"total_chunks":1,"total_tokens":1720,"duration_seconds":45,"files_modified":0,"errors_encountered":0,"errors_recovered":0,"coordination_events":0,"training_eligible":true,"training_exclusion_reason":null}}
|
|
6
|
+
{"envelope_id":"env_14658ff7-104e-4448-b50c-36cdd70103fb","session_id":"sess_2bcbe7fe-a1b0-488e-bf66-a20381bb57ea","type":"USER_FEEDBACK","attestation":{"session_hmac":"3df52d98395ea0b79e95f8bf90e821057b8fc1879d96d41448584faaf99caa19","sequence":2,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"feedback":{"signal":"accepted","timestamp":1777357952.417,"context":"session completed successfully with no user interventions","target_step":11,"revision_rounds":0,"delta_summary":null}}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
// GROOVE CLI — team commands
|
|
2
2
|
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
3
3
|
|
|
4
|
+
import { createInterface } from 'readline';
|
|
4
5
|
import chalk from 'chalk';
|
|
5
6
|
import { apiCall } from '../client.js';
|
|
6
7
|
|
|
8
|
+
function prompt(question) {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
11
|
+
rl.question(question, (answer) => { rl.close(); resolve(answer.trim()); });
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
export async function teamCreate(name) {
|
|
8
16
|
try {
|
|
9
17
|
const team = await apiCall('POST', '/api/teams', { name });
|
|
@@ -37,9 +45,58 @@ export async function teamList() {
|
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
export async function teamDelete(id) {
|
|
48
|
+
const choice = await prompt(` Archive or permanently delete? [${chalk.bold('a')}rchive / ${chalk.bold('D')}elete] `);
|
|
49
|
+
const normalized = choice.toLowerCase();
|
|
50
|
+
|
|
51
|
+
if (normalized === 'd' || normalized === 'delete') {
|
|
52
|
+
const teamName = await prompt(chalk.yellow(' WARNING: All files in this team will be permanently lost.\n') + ` Type the team name to confirm: `);
|
|
53
|
+
if (!teamName) {
|
|
54
|
+
console.log(chalk.dim(' Cancelled.'));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
await apiCall('DELETE', `/api/teams/${encodeURIComponent(id)}?permanent=true`);
|
|
59
|
+
console.log(chalk.green(` Permanently deleted team "${id}".`));
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.error(chalk.red(' Failed:'), err.message);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
} else if (normalized === 'a' || normalized === 'archive' || normalized === '') {
|
|
65
|
+
try {
|
|
66
|
+
await apiCall('DELETE', `/api/teams/${encodeURIComponent(id)}`);
|
|
67
|
+
console.log(chalk.green(` Archived team "${id}"`) + chalk.dim(' — restore with `groove team restore <id>`'));
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(chalk.red(' Failed:'), err.message);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
console.log(chalk.dim(' Cancelled.'));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export async function teamArchived() {
|
|
78
|
+
try {
|
|
79
|
+
const { archived } = await apiCall('GET', '/api/teams/archived');
|
|
80
|
+
if (archived.length === 0) {
|
|
81
|
+
console.log(chalk.dim(' No archived teams.'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(chalk.bold(`\n Archived Teams (${archived.length})\n`));
|
|
85
|
+
for (const t of archived) {
|
|
86
|
+
const date = t.deletedAt ? new Date(t.deletedAt).toLocaleDateString() : 'unknown';
|
|
87
|
+
console.log(` ${chalk.bold(t.originalName || t.id)} — archive-id: ${t.id} — deleted ${date} — ${t.agentCount} agent(s)`);
|
|
88
|
+
}
|
|
89
|
+
console.log('');
|
|
90
|
+
} catch {
|
|
91
|
+
console.error(chalk.red(' Cannot connect to daemon.'));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function teamRestore(id) {
|
|
40
97
|
try {
|
|
41
|
-
await apiCall('
|
|
42
|
-
console.log(chalk.green(`
|
|
98
|
+
const team = await apiCall('POST', `/api/teams/archived/${encodeURIComponent(id)}/restore`);
|
|
99
|
+
console.log(chalk.green(` Restored team "${team.name}"`) + ` (new id: ${team.id})`);
|
|
43
100
|
} catch (err) {
|
|
44
101
|
console.error(chalk.red(' Failed:'), err.message);
|
|
45
102
|
process.exit(1);
|
|
@@ -1100,6 +1100,30 @@ export function createApi(app, daemon) {
|
|
|
1100
1100
|
}
|
|
1101
1101
|
});
|
|
1102
1102
|
|
|
1103
|
+
app.get('/api/teams/archived', (req, res) => {
|
|
1104
|
+
res.json({ archived: daemon.teams.listArchived() });
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
app.post('/api/teams/archived/:id/restore', (req, res) => {
|
|
1108
|
+
try {
|
|
1109
|
+
const team = daemon.teams.restore(req.params.id);
|
|
1110
|
+
daemon.audit.log('team.restore', { archivedId: req.params.id, newId: team.id, name: team.name });
|
|
1111
|
+
res.json(team);
|
|
1112
|
+
} catch (err) {
|
|
1113
|
+
res.status(400).json({ error: err.message });
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
app.delete('/api/teams/archived/:id', (req, res) => {
|
|
1118
|
+
try {
|
|
1119
|
+
daemon.teams.purge(req.params.id);
|
|
1120
|
+
daemon.audit.log('team.purge', { archivedId: req.params.id });
|
|
1121
|
+
res.json({ ok: true });
|
|
1122
|
+
} catch (err) {
|
|
1123
|
+
res.status(400).json({ error: err.message });
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1103
1127
|
app.patch('/api/teams/:id', (req, res) => {
|
|
1104
1128
|
try {
|
|
1105
1129
|
if (req.body.name) daemon.teams.rename(req.params.id, req.body.name);
|
|
@@ -1114,8 +1138,9 @@ export function createApi(app, daemon) {
|
|
|
1114
1138
|
|
|
1115
1139
|
app.delete('/api/teams/:id', (req, res) => {
|
|
1116
1140
|
try {
|
|
1117
|
-
|
|
1118
|
-
daemon.
|
|
1141
|
+
const permanent = req.query.permanent === 'true';
|
|
1142
|
+
daemon.teams.delete(req.params.id, { permanent });
|
|
1143
|
+
daemon.audit.log(permanent ? 'team.delete' : 'team.archive', { id: req.params.id, permanent });
|
|
1119
1144
|
res.json({ ok: true });
|
|
1120
1145
|
} catch (err) {
|
|
1121
1146
|
res.status(400).json({ error: err.message });
|
|
@@ -8,6 +8,7 @@ export class FileWatcher {
|
|
|
8
8
|
constructor(daemon) {
|
|
9
9
|
this.daemon = daemon;
|
|
10
10
|
this.watchers = new Map(); // relPath → { watcher, timer }
|
|
11
|
+
this.dirWatchers = new Map(); // relPath → { watcher, timer }
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
watch(relPath) {
|
|
@@ -51,9 +52,53 @@ export class FileWatcher {
|
|
|
51
52
|
this.watchers.delete(relPath);
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
watchDir(relPath) {
|
|
56
|
+
if (typeof relPath !== 'string') return;
|
|
57
|
+
if (relPath && relPath.includes('..')) return;
|
|
58
|
+
if (this.dirWatchers.has(relPath)) return;
|
|
59
|
+
|
|
60
|
+
const fullPath = relPath ? resolve(this.daemon.projectDir, relPath) : this.daemon.projectDir;
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const watcher = watch(fullPath, () => {
|
|
64
|
+
const entry = this.dirWatchers.get(relPath);
|
|
65
|
+
if (!entry) return;
|
|
66
|
+
|
|
67
|
+
if (entry.timer) clearTimeout(entry.timer);
|
|
68
|
+
entry.timer = setTimeout(() => {
|
|
69
|
+
this.daemon.broadcast({
|
|
70
|
+
type: 'file:tree-changed',
|
|
71
|
+
path: relPath,
|
|
72
|
+
timestamp: Date.now(),
|
|
73
|
+
});
|
|
74
|
+
}, 300);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
watcher.on('error', () => {
|
|
78
|
+
this.unwatchDir(relPath);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
this.dirWatchers.set(relPath, { watcher, timer: null });
|
|
82
|
+
} catch {
|
|
83
|
+
// Directory doesn't exist or not watchable — ignore
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
unwatchDir(relPath) {
|
|
88
|
+
const entry = this.dirWatchers.get(relPath);
|
|
89
|
+
if (!entry) return;
|
|
90
|
+
|
|
91
|
+
if (entry.timer) clearTimeout(entry.timer);
|
|
92
|
+
try { entry.watcher.close(); } catch { /* already closed */ }
|
|
93
|
+
this.dirWatchers.delete(relPath);
|
|
94
|
+
}
|
|
95
|
+
|
|
54
96
|
unwatchAll() {
|
|
55
97
|
for (const [relPath] of this.watchers) {
|
|
56
98
|
this.unwatch(relPath);
|
|
57
99
|
}
|
|
100
|
+
for (const [relPath] of this.dirWatchers) {
|
|
101
|
+
this.unwatchDir(relPath);
|
|
102
|
+
}
|
|
58
103
|
}
|
|
59
104
|
}
|
|
@@ -325,8 +325,9 @@ export class Daemon {
|
|
|
325
325
|
data: enrichAgents(this.registry.getAll()),
|
|
326
326
|
}));
|
|
327
327
|
|
|
328
|
-
// Track which files this client is watching (for cleanup on disconnect)
|
|
328
|
+
// Track which files/dirs this client is watching (for cleanup on disconnect)
|
|
329
329
|
const watchedFiles = new Set();
|
|
330
|
+
const watchedDirs = new Set();
|
|
330
331
|
|
|
331
332
|
ws.on('message', (raw) => {
|
|
332
333
|
try {
|
|
@@ -335,7 +336,7 @@ export class Daemon {
|
|
|
335
336
|
// Validate message type against whitelist
|
|
336
337
|
const VALID_WS_TYPES = new Set([
|
|
337
338
|
'terminal:spawn', 'terminal:resize', 'terminal:input', 'terminal:close', 'terminal:kill', 'terminal:rename',
|
|
338
|
-
'editor:watch', 'editor:unwatch', 'editor:save',
|
|
339
|
+
'editor:watch', 'editor:unwatch', 'editor:save', 'editor:watchdir', 'editor:unwatchdir',
|
|
339
340
|
'ping'
|
|
340
341
|
]);
|
|
341
342
|
if (!msg || typeof msg !== 'object' || !VALID_WS_TYPES.has(msg.type)) return;
|
|
@@ -351,6 +352,14 @@ export class Daemon {
|
|
|
351
352
|
case 'editor:unwatch':
|
|
352
353
|
if (msg.path) { this.fileWatcher.unwatch(msg.path); watchedFiles.delete(msg.path); }
|
|
353
354
|
break;
|
|
355
|
+
case 'editor:watchdir':
|
|
356
|
+
if (typeof msg.path === 'string' && !msg.path.includes('..')) {
|
|
357
|
+
this.fileWatcher.watchDir(msg.path); watchedDirs.add(msg.path);
|
|
358
|
+
}
|
|
359
|
+
break;
|
|
360
|
+
case 'editor:unwatchdir':
|
|
361
|
+
if (typeof msg.path === 'string') { this.fileWatcher.unwatchDir(msg.path); watchedDirs.delete(msg.path); }
|
|
362
|
+
break;
|
|
354
363
|
// Terminal
|
|
355
364
|
case 'terminal:spawn': {
|
|
356
365
|
if (msg.cwd !== undefined && (typeof msg.cwd !== 'string' || msg.cwd.includes('..'))) break;
|
|
@@ -389,6 +398,9 @@ export class Daemon {
|
|
|
389
398
|
for (const path of watchedFiles) {
|
|
390
399
|
this.fileWatcher.unwatch(path);
|
|
391
400
|
}
|
|
401
|
+
for (const path of watchedDirs) {
|
|
402
|
+
this.fileWatcher.unwatchDir(path);
|
|
403
|
+
}
|
|
392
404
|
this.terminalManager.cleanupClient(ws);
|
|
393
405
|
});
|
|
394
406
|
});
|