groove-dev 0.27.115 → 0.27.117

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.
Files changed (38) hide show
  1. package/TRAINING_DATA_v4.md +6 -3
  2. package/moe-training/client/domain-tagger.js +20 -0
  3. package/moe-training/client/trajectory-capture.js +36 -7
  4. package/moe-training/test/client/trajectory-capture.test.js +182 -1
  5. package/node_modules/@groove-dev/cli/package.json +1 -1
  6. package/node_modules/@groove-dev/cli/src/commands/team.js +27 -12
  7. package/node_modules/@groove-dev/daemon/package.json +1 -1
  8. package/node_modules/@groove-dev/daemon/src/api.js +3 -2
  9. package/node_modules/@groove-dev/daemon/src/process.js +283 -211
  10. package/node_modules/@groove-dev/daemon/src/teams.js +53 -24
  11. package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +21 -3
  12. package/node_modules/@groove-dev/gui/dist/assets/{index-D4Q72afD.css → index-DdN9RVnC.css} +1 -1
  13. package/node_modules/@groove-dev/gui/dist/assets/{index-BKCiOUDb.js → index-fq--PD7_.js} +1724 -1724
  14. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  15. package/node_modules/@groove-dev/gui/package.json +1 -1
  16. package/node_modules/@groove-dev/gui/src/components/teams/team-removal-dialog.jsx +156 -0
  17. package/node_modules/@groove-dev/gui/src/stores/groove.js +15 -4
  18. package/node_modules/@groove-dev/gui/src/views/agents.jsx +10 -19
  19. package/node_modules/@groove-dev/gui/src/views/teams.jsx +17 -41
  20. package/node_modules/moe-training/client/domain-tagger.js +20 -0
  21. package/node_modules/moe-training/client/trajectory-capture.js +36 -7
  22. package/node_modules/moe-training/test/client/trajectory-capture.test.js +182 -1
  23. package/package.json +1 -1
  24. package/packages/cli/package.json +1 -1
  25. package/packages/cli/src/commands/team.js +27 -12
  26. package/packages/daemon/package.json +1 -1
  27. package/packages/daemon/src/api.js +3 -2
  28. package/packages/daemon/src/process.js +283 -211
  29. package/packages/daemon/src/teams.js +53 -24
  30. package/packages/daemon/src/tunnel-manager.js +21 -3
  31. package/packages/gui/dist/assets/{index-D4Q72afD.css → index-DdN9RVnC.css} +1 -1
  32. package/packages/gui/dist/assets/{index-BKCiOUDb.js → index-fq--PD7_.js} +1724 -1724
  33. package/packages/gui/dist/index.html +2 -2
  34. package/packages/gui/package.json +1 -1
  35. package/packages/gui/src/components/teams/team-removal-dialog.jsx +156 -0
  36. package/packages/gui/src/stores/groove.js +15 -4
  37. package/packages/gui/src/views/agents.jsx +10 -19
  38. package/packages/gui/src/views/teams.jsx +17 -41
@@ -1,3 +1,6 @@
1
- {"envelope_id":"env_70dfa132-575b-48a3-becc-a2ea8a75aecc","session_id":"sess_54e35697-302f-45bc-bc3e-c4282b5f6034","chunk_sequence":0,"contributor_id":"23e6dd8c4a884836bf78cafda9fbe57d","attestation":{"session_hmac":"9f2d5a6369edcb2545181101574e61e02c65e939e253c068d398d2cbf8f20cd4","sequence":0,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"metadata":{"model_engine":"claude-opus-4-6","provider":"claude-code","agent_role":"fullstack","agent_id":"e18a8fa4","task_complexity":"medium","team_size":2,"session_quality":0,"groove_version":"0.27.113","leaf_context":null},"trajectory_log":[{"step":1,"type":"thought","timestamp":1777354900.276,"content":"Let me trace the exact URL the client is using.","token_count":12},{"step":2,"type":"action","timestamp":1777354901.244,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && grep -n 'EMBEDDING_SERVICE_URL\\|CENTRAL_COMMAND_URL' moe-training/shared/constants.js"},"content":"Using Bash","token_count":37},{"step":3,"type":"observation","timestamp":1777354901.808,"content":"41:export const CENTRAL_COMMAND_URL = process.env.GROOVE_CENTRAL_URL || 'https://api.groovedev.ai';\n42:export const EMBEDDING_SERVICE_URL = process.env.EMBEDDING_SERVICE_URL || `${CENTRAL_COMMAND_URL}/v1/embed`;\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":71,"is_error":false,"tool":"Bash","token_count":69},{"step":4,"type":"action","timestamp":1777354905.484,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && grep -n 'serviceUrl\\|EMBEDDING' moe-training/client/domain-tagger.js | head -10"},"content":"Using Bash","token_count":36},{"step":5,"type":"observation","timestamp":1777354905.528,"content":"3:import { EMBEDDING_SERVICE_URL } from '../shared/constants.js';\n176: this._serviceUrl = options.serviceUrl !== undefined ? options.serviceUrl : EMBEDDING_SERVICE_URL;\n208: if (this._serviceUrl) {\n210: const res = await fetch(this._serviceUrl, {\n361: const res = await fetch(this._serviceUrl, {\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":97,"is_error":false,"tool":"Bash","token_count":95},{"step":6,"type":"thought","timestamp":1777354911.293,"content":"The constant looks correct — `https://api.groovedev.ai/v1/embed`, no trailing slash. But let me check what the DomainTagger actually receives at runtime. The `TrajectoryCapture` creates the DomainTagger — let me see if it passes any options.","token_count":61},{"step":7,"type":"action","timestamp":1777354911.644,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && grep -n 'DomainTagger\\|domainTagger\\|_domainTagger' moe-training/client/trajectory-capture.js"},"content":"Using Bash","token_count":40},{"step":8,"type":"observation","timestamp":1777354911.695,"content":"11:import { DomainTagger } from './domain-tagger.js';\n48: this._domainTagger = new DomainTagger();\n49: await this._domainTagger.init();\n299: if (this._domainTagger) {\n304: const routingText = DomainTagger.buildRoutingText(role, firstPrompt, remainingThoughts);\n305: ctx.metadata.domain_tags = await this._domainTagger.tag(routingText);\n306: ctx.metadata.session_embedding = await this._domainTagger.embed(routingText);\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":129,"is_error":false,"tool":"Bash","token_count":127},{"step":9,"type":"thought","timestamp":1777354916.313,"content":"`new DomainTagger()` — no options passed, so it uses the default `EMBEDDING_SERVICE_URL`. Now let me check where the daemon actually imports and uses this. The `moe-training` module is consumed by the daemon.","token_count":52},{"step":10,"type":"action","timestamp":1777354916.852,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && grep -rn 'TrajectoryCapture\\|trajectory-capture\\|moe-training' packages/daemon/src/ | grep -v node_modules"},"content":"Using Bash","token_count":43},{"step":11,"type":"observation","timestamp":1777354916.946,"content":"packages/daemon/src/index.js:46:import { TrajectoryCapture, ConsentManager } from '../../../moe-training/client/index.js';\npackages/daemon/src/index.js:594: this._initTrajectoryCapture().catch(() => {});\npackages/daemon/src/index.js:680: async _initTrajectoryCapture() {\npackages/daemon/src/index.js:685: this.trajectoryCapture = new TrajectoryCapture({\npackages/daemon/src/api.js:18:import { ConsentManager } from '../../../moe-training/client/index.js';\npackages/daemon/src/api.js:4939: await daemon._initTrajectoryCapture();\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":155,"is_error":false,"tool":"Bash","token_count":153},{"step":12,"type":"action","timestamp":1777354920.727,"tool":"Read","arguments":{"file_path":"~/Desktop/groove-project/groove/packages/daemon/src/index.js","offset":678,"limit":25},"content":"Using Read","token_count":28},{"step":13,"type":"observation","timestamp":1777354920.728,"content":"678\t }\n679\t\n680\t async _initTrajectoryCapture() {\n681\t try {\n682\t if (!ConsentManager.isCaptureEnabled()) return;\n683\t const pkgPath = new URL('../package.json', import.meta.url);\n684\t const version = JSON.parse(readFileSync(pkgPath, 'utf8')).version;\n685\t this.trajectoryCapture = new TrajectoryCapture({\n686\t centralCommandUrl: process.env.GROOVE_CENTRAL_URL || 'https://api.groovedev.ai',\n687\t grooveVersion: version,\n688\t });\n689\t this.trajectoryCapture.init();\n690\t } catch (e) {\n691\t // Training capture is never critical\n692\t }\n693\t }\n694\t\n695\t _startGarbageCollector() {\n696\t // Run once on startup, then every 24 hours\n697\t this._gc();\n698\t this._gcInterval = setInterval(() => this._gc(), 24 * 60 * 60 * 1000);\n699\t\n700\t // Periodic state save — crash protection (every 30s)\n701\t this._stateSaveInterval = setInterval(async () => {\n702\t try { this.state.set('agents', this.registry.getAll()); await this.state.save(); } catch {}","truncated":false,"original_token_count":255,"is_error":false,"tool":"Read","token_count":255},{"step":14,"type":"thought","timestamp":1777354925.525,"content":"Line 689 — `this.trajectoryCapture.init()` — no `await`. That's not the bug here though. Let me look at what `TrajectoryCapture.init()` does with the DomainTagger.","token_count":41},{"step":15,"type":"action","timestamp":1777354926.407,"tool":"Read","arguments":{"file_path":"~/Desktop/groove-project/groove/moe-training/client/trajectory-capture.js","offset":38,"limit":16},"content":"Using Read","token_count":31},{"step":16,"type":"observation","timestamp":1777354926.407,"content":"38\t async init() {\n39\t if (!ConsentManager.isCaptureEnabled()) {\n40\t this._enabled = false;\n41\t return;\n42\t }\n43\t this._enabled = true;\n44\t this._scrubber = new PIIScrubber();\n45\t this._attestation = new SessionAttestation(this._centralCommandUrl);\n46\t this._transmissionQueue = new TransmissionQueue(this._centralCommandUrl);\n47\t this._transmissionQueue.start();\n48\t this._domainTagger = new DomainTagger();\n49\t await this._domainTagger.init();\n50\t this._offlineRetryTimer = setInterval(() => {\n51\t this._retryOfflineQueue();\n52\t }, OFFLINE_RETRY_INTERVAL_MS);\n53\t }","truncated":false,"original_token_count":155,"is_error":false,"tool":"Read","token_count":155},{"step":17,"type":"thought","timestamp":1777354935.764,"content":"Wait — line 689 in `index.js`: `this.trajectoryCapture.init()` — **no await**. That means `init()` runs as a fire-and-forget promise. The DomainTagger's `init()` calls `await this._domainTagger.init()` which does 41 HTTP requests. But the daemon doesn't await the TrajectoryCapture's init.\n\nThat's fine in theory — the DomainTagger should still eventually resolve. But let me check: if `init()` isn't awaited and an agent spawns before the DomainTagger finishes its 41 embed calls, the `_domainTagger` might be set but not yet `_ready`. Let me look at the timing.\n\nActually, that's not the issue either — `onAgentSpawn` doesn't check `_domainTagger.ready`. The domain tagging only happens in `_closeAgent`, by which point init would have long completed.\n\nLet me look at this from another angle — is the `EMBEDDING_SERVICE_URL` constant actually making it into the published npm package?","token_count":222},{"step":18,"type":"action","timestamp":1777354936.676,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && node -e \"\nimport { EMBEDDING_SERVICE_URL, CENTRAL_COMMAND_URL } from './moe-training/shared/constants.js';\nconsole.log('CENTRAL_COMMAND_URL:', CENTRAL_COMMAND_URL);\nconsole.log('EMBEDDING_SERVICE_URL:', EMBEDDING_SERVICE_URL);\n\""},"content":"Using Bash","token_count":74},{"step":19,"type":"observation","timestamp":1777354936.764,"content":"CENTRAL_COMMAND_URL: https://api.groovedev.ai\nEMBEDDING_SERVICE_URL: https://api.groovedev.ai/v1/embed\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":44,"is_error":false,"tool":"Bash","token_count":42},{"step":20,"type":"action","timestamp":1777354948.816,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && node -e \"\nimport { DomainTagger } from './moe-training/client/domain-tagger.js';\nconst t = new DomainTagger();\nconsole.log('serviceUrl:', t._serviceUrl);\nconsole.log('mode:', t._mode);\nconsole.log('ready:', t._ready);\n\""},"content":"Using Bash","token_count":73},{"step":21,"type":"observation","timestamp":1777354948.897,"content":"serviceUrl: https://api.groovedev.ai/v1/embed\nmode: null\nready: false\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":36,"is_error":false,"tool":"Bash","token_count":34},{"step":22,"type":"thought","timestamp":1777354952.865,"content":"URL is correct. Let me test the full init flow.","token_count":12},{"step":23,"type":"action","timestamp":1777354956.383,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && node -e \"\nimport { DomainTagger } from './moe-training/client/domain-tagger.js';\nconst t = new DomainTagger();\nconsole.log('serviceUrl:', t._serviceUrl);\nconsole.time('init');\ntry {\n await t.init();\n console.timeEnd('init');\n console.log('mode:', t.mode);\n console.log('ready:', t.ready);\n console.log('lastError:', t.lastError);\n if (t._centroids) {\n console.log('centroids:', Object.keys(t._centroids).length);\n }\n const result = await t.tag('Build a React frontend with TypeScript and Tailwind CSS');\n console.log('tag result:', JSON.stringify(result));\n const emb = await t.embed('Build a React frontend with TypeScript');\n console.log('embed:', emb ? emb.vector.length + 'd' : 'null');\n} catch (e) {\n console.error('ERROR:', e.message);\n}\n\" 2>&1","timeout":60000},"content":"Using Bash","token_count":217},{"step":24,"type":"observation","timestamp":1777354961.386,"content":"serviceUrl: https://api.groovedev.ai/v1/embed\ninit: 4.706s\nmode: http\nready: true\nlastError: null\ncentroids: 40\ntag result: {\"primary\":{\"domain\":\"react_frontend\",\"confidence\":0.685},\"secondary\":{\"domain\":\"typescript_node\",\"confidence\":0.4633},\"tertiary\":{\"domain\":\"vue_frontend\",\"confidence\":0.3264}}\nembed: 384d\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":97,"is_error":false,"tool":"Bash","token_count":94},{"step":25,"type":"thought","timestamp":1777354969.631,"content":"It works perfectly from this machine — `http` mode, 40 centroids, 0.685 confidence on React, 384d embedding. The code is correct.\n\nThe issue is that the **running daemon** was started before these changes were committed. The daemon process has the old code in memory where `DomainTagger` didn't import `EMBEDDING_SERVICE_URL` and defaulted `serviceUrl` to `null`.\n\nYou need to restart the Groove daemon to pick up the new code. The changes are in the files but the running Node process is still using the old version.","token_count":130},{"step":26,"type":"action","timestamp":1777354971.472,"tool":"Bash","arguments":{"command":"cd ~/Desktop/groove-project/groove && node -e \"\nimport { DomainTagger } from './moe-training/client/domain-tagger.js';\nconst t = new DomainTagger();\nconsole.log('Confirmed: serviceUrl =', t._serviceUrl);\nconsole.log('This proves the code is correct.');\nconsole.log('If live sessions show keyword mode, the running daemon has stale code in memory.');\nconsole.log('Fix: restart the daemon (groove stop && groove start)');\n\""},"content":"Using Bash","token_count":114},{"step":27,"type":"observation","timestamp":1777354971.549,"content":"Confirmed: serviceUrl = https://api.groovedev.ai/v1/embed\nThis proves the code is correct.\nIf live sessions show keyword mode, the running daemon has stale code in memory.\nFix: restart the daemon (groove stop && groove start)\nShell cwd was reset to ~/Desktop/groove-project/groove/training","truncated":false,"original_token_count":75,"is_error":false,"tool":"Bash","token_count":73},{"step":28,"type":"thought","timestamp":1777354976.411,"content":"Mystery solved. The code works — `http` mode, 40 centroids built in 4.7s, 0.685 confidence, 384d embeddings. The running daemon just needs a restart to pick up the new `EMBEDDING_SERVICE_URL` default. Run `groove stop && groove start` and the next session will have full embeddings.","token_count":71},{"step":29,"type":"resolution","timestamp":1777354976.457,"content":"Mystery solved. The code works — `http` mode, 40 centroids built in 4.7s, 0.685 confidence, 384d embeddings. The running daemon just needs a restart to pick up the new `EMBEDDING_SERVICE_URL` default. Run `groove stop && groove start` and the next session will have full embeddings.","token_count":71}]}
2
- {"envelope_id":"env_8c59a800-92c2-486e-aab2-d251958883da","session_id":"sess_54e35697-302f-45bc-bc3e-c4282b5f6034","type":"SESSION_CLOSE","attestation":{"session_hmac":"3fd6f3891108e43eb7482a0361fc5789ecfb9fdf40f637a63edb01e154c6f74f","sequence":1,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"metadata":{"model_engine":"claude-opus-4-6","provider":"claude-code","agent_role":"fullstack","agent_id":"e18a8fa4","task_complexity":"medium","team_size":2,"session_quality":70,"groove_version":"0.27.113","leaf_context":null,"domain_tags":{"primary":{"domain":"linux_admin","confidence":0.0769},"secondary":{"domain":"nlp_llm","confidence":0.0769},"tertiary":{"domain":"react_frontend","confidence":0.0667}},"session_embedding":null},"outcome":{"status":"SUCCESS","session_quality":70,"quality_tier":"TIER_A","quality_tier_reason":"high_quality_no_errors","user_interventions":0,"total_steps":29,"total_chunks":1,"total_tokens":2462,"duration_seconds":86,"files_modified":0,"errors_encountered":0,"errors_recovered":0,"coordination_events":0,"training_eligible":true,"training_exclusion_reason":null}}
3
- {"envelope_id":"env_eafaf868-6b85-46c8-b687-43a576aedc50","session_id":"sess_54e35697-302f-45bc-bc3e-c4282b5f6034","type":"USER_FEEDBACK","attestation":{"session_hmac":"a60cc84ce26d8714749bbaedd3d51a8fb153d008e3cb396d3413740d6970454c","sequence":2,"app_version_hash":"4a527565d85cc601d3c47c376e4f361d5af987de58f60cf71dbc263a0de91247"},"feedback":{"signal":"accepted","timestamp":1777354977.009,"context":"session completed successfully with no user interventions","target_step":29,"revision_rounds":0,"delta_summary":null}}
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}}
@@ -169,6 +169,26 @@ const DOMAIN_TAXONOMY = {
169
169
  keywords: ['scientific', 'simulation', 'matlab', 'scipy', 'julia', 'fortran', 'numerical', 'differential equation', 'finite element', 'linear algebra'],
170
170
  description: 'Scientific computing, numerical methods, MATLAB/SciPy/Julia, simulations, optimization, statistics',
171
171
  },
172
+ planning_strategy: {
173
+ keywords: ['plan', 'strategy', 'architect', 'design doc', 'breakdown', 'scope', 'roadmap', 'milestone', 'prioritize', 'tradeoff', 'approach', 'recommend', 'team', 'coordinate', 'delegate', 'assign'],
174
+ description: 'Project planning, task breakdown, architecture decisions, team coordination, strategy, roadmaps, scoping, prioritization',
175
+ },
176
+ conversational_reasoning: {
177
+ keywords: ['explain', 'why', 'how does', 'what is', 'clarify', 'understand', 'reason', 'think through', 'analyze', 'compare', 'evaluate', 'brainstorm', 'discuss', 'opinion', 'advice'],
178
+ description: 'Conversational reasoning, explanation, analysis, brainstorming, Q&A, decision-making, advice, evaluation',
179
+ },
180
+ documentation_writing: {
181
+ keywords: ['readme', 'documentation', 'docs', 'markdown', 'api docs', 'changelog', 'tutorial', 'guide', 'specification', 'wiki', 'jsdoc', 'docstring', 'technical writing'],
182
+ description: 'Documentation writing, READMEs, API docs, changelogs, tutorials, guides, technical writing, specifications',
183
+ },
184
+ product_design: {
185
+ keywords: ['product', 'feature', 'user story', 'requirements', 'ux', 'wireframe', 'prototype', 'feedback', 'iteration', 'mvp', 'spec', 'acceptance criteria', 'stakeholder'],
186
+ description: 'Product design, feature planning, user stories, requirements gathering, UX, prototyping, MVPs, stakeholder communication',
187
+ },
188
+ devops_general: {
189
+ keywords: ['deploy', 'deployment', 'release', 'rollback', 'staging', 'production', 'environment', 'migration', 'upgrade', 'maintenance', 'incident', 'postmortem', 'runbook'],
190
+ description: 'DevOps operations, deployments, releases, rollbacks, environment management, incident response, runbooks',
191
+ },
172
192
  };
173
193
 
174
194
  export class DomainTagger {
@@ -33,9 +33,11 @@ export class TrajectoryCapture {
33
33
  this._transmissionQueue = null;
34
34
  this._offlineRetryTimer = null;
35
35
  this._contexts = new Map();
36
+ this._shutdown = false;
36
37
  }
37
38
 
38
39
  async init() {
40
+ if (this._shutdown) return;
39
41
  if (!ConsentManager.isCaptureEnabled()) {
40
42
  this._enabled = false;
41
43
  return;
@@ -47,12 +49,16 @@ export class TrajectoryCapture {
47
49
  this._transmissionQueue.start();
48
50
  this._domainTagger = new DomainTagger();
49
51
  await this._domainTagger.init();
52
+ if (this._shutdown) return;
50
53
  this._offlineRetryTimer = setInterval(() => {
51
54
  this._retryOfflineQueue();
52
55
  }, OFFLINE_RETRY_INTERVAL_MS);
56
+ if (typeof this._offlineRetryTimer.unref === 'function') {
57
+ this._offlineRetryTimer.unref();
58
+ }
53
59
  }
54
60
 
55
- async onAgentSpawn(agentId, provider, model, role, teamSize) {
61
+ async onAgentSpawn(agentId, provider, model, role, teamSize, prompt) {
56
62
  if (!this._enabled) return;
57
63
 
58
64
  const parser = getParser(provider);
@@ -98,9 +104,20 @@ export class TrajectoryCapture {
98
104
  ctx.chunkTimer = setInterval(() => {
99
105
  this._flushContext(agentId);
100
106
  }, CHUNK_TIMEOUT_MS);
107
+ if (typeof ctx.chunkTimer.unref === 'function') {
108
+ ctx.chunkTimer.unref();
109
+ }
101
110
 
102
111
  this._contexts.set(agentId, ctx);
103
112
 
113
+ if (prompt && typeof prompt === 'string' && prompt.trim()) {
114
+ this._processStep(agentId, ctx, {
115
+ type: 'instruction',
116
+ content: prompt.slice(0, USER_MESSAGE_MAX_CHARS),
117
+ source: 'user',
118
+ });
119
+ }
120
+
104
121
  await this._attestation.openSession(sessionId, metadata);
105
122
  }
106
123
 
@@ -205,6 +222,7 @@ export class TrajectoryCapture {
205
222
  }
206
223
 
207
224
  async shutdown() {
225
+ this._shutdown = true;
208
226
  if (this._offlineRetryTimer) clearInterval(this._offlineRetryTimer);
209
227
  for (const agentId of this._contexts.keys()) {
210
228
  await this._closeAgent(agentId, 'SHUTDOWN');
@@ -368,6 +386,23 @@ export class TrajectoryCapture {
368
386
  }
369
387
 
370
388
  _computeTrainingEligibility(ctx, durationSeconds) {
389
+ const role = ctx.metadata.agent_role || '';
390
+ const isConversational = role === 'planner' || role === 'chat' || role === 'advisor';
391
+
392
+ if (ctx.totalTokens < TRAINING_MIN_TOKENS) {
393
+ return { eligible: false, exclusionReason: 'insufficient_tokens' };
394
+ }
395
+ if (durationSeconds < TRAINING_MIN_DURATION) {
396
+ return { eligible: false, exclusionReason: 'too_short' };
397
+ }
398
+
399
+ if (isConversational) {
400
+ if (ctx.stepCount < 2) {
401
+ return { eligible: false, exclusionReason: 'too_few_steps' };
402
+ }
403
+ return { eligible: true, exclusionReason: null };
404
+ }
405
+
371
406
  if (ctx.stepCount < TRAINING_MIN_STEPS) {
372
407
  return { eligible: false, exclusionReason: 'too_few_steps' };
373
408
  }
@@ -379,12 +414,6 @@ export class TrajectoryCapture {
379
414
  if (!hasObservation) {
380
415
  return { eligible: false, exclusionReason: 'no_observations' };
381
416
  }
382
- if (ctx.totalTokens < TRAINING_MIN_TOKENS) {
383
- return { eligible: false, exclusionReason: 'insufficient_tokens' };
384
- }
385
- if (durationSeconds < TRAINING_MIN_DURATION) {
386
- return { eligible: false, exclusionReason: 'too_short' };
387
- }
388
417
  return { eligible: true, exclusionReason: null };
389
418
  }
390
419
 
@@ -208,7 +208,7 @@ describe('TrajectoryCapture — training eligibility', () => {
208
208
  assert.equal(result.exclusionReason, null);
209
209
  });
210
210
 
211
- it('exclusion reasons follow priority order', () => {
211
+ it('exclusion reasons follow priority order: tokens before duration before steps', () => {
212
212
  const tc = makeTc();
213
213
  const ctx = makeCtx({
214
214
  stepCount: 3,
@@ -220,8 +220,189 @@ describe('TrajectoryCapture — training eligibility', () => {
220
220
  ],
221
221
  });
222
222
  const result = tc._computeTrainingEligibility(ctx, 5);
223
+ assert.equal(result.exclusionReason, 'insufficient_tokens');
224
+ });
225
+
226
+ it('duration checked before steps when tokens pass', () => {
227
+ const tc = makeTc();
228
+ const ctx = makeCtx({
229
+ stepCount: 3,
230
+ totalTokens: 5000,
231
+ allSteps: [
232
+ { step: 1, type: 'thought', content: 'thinking' },
233
+ { step: 2, type: 'thought', content: 'more' },
234
+ { step: 3, type: 'thought', content: 'done' },
235
+ ],
236
+ });
237
+ const result = tc._computeTrainingEligibility(ctx, 5);
238
+ assert.equal(result.exclusionReason, 'too_short');
239
+ });
240
+
241
+ it('steps checked after tokens and duration pass', () => {
242
+ const tc = makeTc();
243
+ const ctx = makeCtx({
244
+ stepCount: 3,
245
+ totalTokens: 5000,
246
+ allSteps: [
247
+ { step: 1, type: 'thought', content: 'thinking' },
248
+ { step: 2, type: 'thought', content: 'more' },
249
+ { step: 3, type: 'thought', content: 'done' },
250
+ ],
251
+ });
252
+ const result = tc._computeTrainingEligibility(ctx, 60);
253
+ assert.equal(result.exclusionReason, 'too_few_steps');
254
+ });
255
+ });
256
+
257
+ describe('TrajectoryCapture — planner/conversational eligibility', () => {
258
+ function makeConversationalCtx(role, overrides = {}) {
259
+ const ctx = makeCtx(overrides);
260
+ ctx.metadata.agent_role = role;
261
+ return ctx;
262
+ }
263
+
264
+ it('planner eligible with only thoughts (no actions/observations)', () => {
265
+ const tc = makeTc();
266
+ const ctx = makeConversationalCtx('planner', {
267
+ stepCount: 10,
268
+ totalTokens: 2000,
269
+ allSteps: Array.from({ length: 10 }, (_, i) => ({ step: i + 1, type: 'thought', content: 'planning' })),
270
+ });
271
+ const result = tc._computeTrainingEligibility(ctx, 60);
272
+ assert.equal(result.eligible, true);
273
+ assert.equal(result.exclusionReason, null);
274
+ });
275
+
276
+ it('chat role eligible with only thoughts', () => {
277
+ const tc = makeTc();
278
+ const ctx = makeConversationalCtx('chat', {
279
+ stepCount: 5,
280
+ totalTokens: 1000,
281
+ allSteps: [
282
+ { step: 1, type: 'instruction', content: 'explain React hooks' },
283
+ { step: 2, type: 'thought', content: 'explaining' },
284
+ { step: 3, type: 'thought', content: 'more detail' },
285
+ { step: 4, type: 'thought', content: 'examples' },
286
+ { step: 5, type: 'resolution', content: 'done' },
287
+ ],
288
+ });
289
+ const result = tc._computeTrainingEligibility(ctx, 30);
290
+ assert.equal(result.eligible, true);
291
+ });
292
+
293
+ it('advisor role eligible with only thoughts', () => {
294
+ const tc = makeTc();
295
+ const ctx = makeConversationalCtx('advisor', {
296
+ stepCount: 3,
297
+ totalTokens: 800,
298
+ allSteps: [
299
+ { step: 1, type: 'instruction', content: 'review approach' },
300
+ { step: 2, type: 'thought', content: 'analysis' },
301
+ { step: 3, type: 'resolution', content: 'recommendation' },
302
+ ],
303
+ });
304
+ const result = tc._computeTrainingEligibility(ctx, 20);
305
+ assert.equal(result.eligible, true);
306
+ });
307
+
308
+ it('planner still requires minimum tokens', () => {
309
+ const tc = makeTc();
310
+ const ctx = makeConversationalCtx('planner', {
311
+ stepCount: 10,
312
+ totalTokens: 100,
313
+ allSteps: Array.from({ length: 10 }, (_, i) => ({ step: i + 1, type: 'thought', content: 'plan' })),
314
+ });
315
+ const result = tc._computeTrainingEligibility(ctx, 60);
316
+ assert.equal(result.eligible, false);
317
+ assert.equal(result.exclusionReason, 'insufficient_tokens');
318
+ });
319
+
320
+ it('planner still requires minimum duration', () => {
321
+ const tc = makeTc();
322
+ const ctx = makeConversationalCtx('planner', {
323
+ stepCount: 10,
324
+ totalTokens: 2000,
325
+ allSteps: Array.from({ length: 10 }, (_, i) => ({ step: i + 1, type: 'thought', content: 'plan' })),
326
+ });
327
+ const result = tc._computeTrainingEligibility(ctx, 5);
328
+ assert.equal(result.eligible, false);
329
+ assert.equal(result.exclusionReason, 'too_short');
330
+ });
331
+
332
+ it('planner requires at least 2 steps', () => {
333
+ const tc = makeTc();
334
+ const ctx = makeConversationalCtx('planner', {
335
+ stepCount: 1,
336
+ totalTokens: 2000,
337
+ allSteps: [{ step: 1, type: 'thought', content: 'plan' }],
338
+ });
339
+ const result = tc._computeTrainingEligibility(ctx, 60);
340
+ assert.equal(result.eligible, false);
223
341
  assert.equal(result.exclusionReason, 'too_few_steps');
224
342
  });
343
+
344
+ it('coding role (fullstack) still requires actions and observations', () => {
345
+ const tc = makeTc();
346
+ const ctx = makeConversationalCtx('fullstack', {
347
+ stepCount: 10,
348
+ totalTokens: 2000,
349
+ allSteps: Array.from({ length: 10 }, (_, i) => ({ step: i + 1, type: 'thought', content: 'thinking' })),
350
+ });
351
+ const result = tc._computeTrainingEligibility(ctx, 60);
352
+ assert.equal(result.eligible, false);
353
+ assert.equal(result.exclusionReason, 'no_actions');
354
+ });
355
+ });
356
+
357
+ describe('TrajectoryCapture — initial prompt capture', () => {
358
+ function makeSpawnTc() {
359
+ const tc = makeTc();
360
+ tc._enabled = true;
361
+ tc._scrubber = { scrub: (s) => s };
362
+ tc._attestation = { openSession: async () => {}, signEnvelope: (sid, e) => e };
363
+ tc._transmissionQueue = { enqueue: () => {} };
364
+ tc._domainTagger = null;
365
+ return tc;
366
+ }
367
+
368
+ it('onAgentSpawn records prompt as instruction step', async () => {
369
+ const tc = makeSpawnTc();
370
+ await tc.onAgentSpawn('agent-p1', 'claude-code', 'opus', 'planner', 1, 'Build a React app');
371
+
372
+ const ctx = tc._contexts.get('agent-p1');
373
+ assert.ok(ctx);
374
+ assert.equal(ctx.stepCount, 1);
375
+ assert.equal(ctx.allSteps[0].type, 'instruction');
376
+ assert.ok(ctx.allSteps[0].content.includes('Build a React app'));
377
+ assert.equal(ctx.allSteps[0].source, 'user');
378
+ });
379
+
380
+ it('onAgentSpawn with no prompt creates no instruction step', async () => {
381
+ const tc = makeSpawnTc();
382
+ await tc.onAgentSpawn('agent-p2', 'claude-code', 'opus', 'fullstack', 1);
383
+
384
+ const ctx = tc._contexts.get('agent-p2');
385
+ assert.ok(ctx);
386
+ assert.equal(ctx.stepCount, 0);
387
+ assert.equal(ctx.allSteps.length, 0);
388
+ });
389
+
390
+ it('onAgentSpawn truncates long prompts', async () => {
391
+ const tc = makeSpawnTc();
392
+ const longPrompt = 'x'.repeat(50000);
393
+ await tc.onAgentSpawn('agent-p3', 'claude-code', 'opus', 'planner', 1, longPrompt);
394
+
395
+ const ctx = tc._contexts.get('agent-p3');
396
+ assert.ok(ctx.allSteps[0].content.length <= 10001);
397
+ });
398
+
399
+ it('onAgentSpawn ignores empty/whitespace prompts', async () => {
400
+ const tc = makeSpawnTc();
401
+ await tc.onAgentSpawn('agent-p4', 'claude-code', 'opus', 'planner', 1, ' ');
402
+
403
+ const ctx = tc._contexts.get('agent-p4');
404
+ assert.equal(ctx.stepCount, 0);
405
+ });
225
406
  });
226
407
 
227
408
  describe('TrajectoryCapture — user feedback emission', () => {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.115",
3
+ "version": "0.27.117",
4
4
  "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -5,10 +5,10 @@ import { createInterface } from 'readline';
5
5
  import chalk from 'chalk';
6
6
  import { apiCall } from '../client.js';
7
7
 
8
- function confirm(prompt) {
8
+ function prompt(question) {
9
9
  return new Promise((resolve) => {
10
10
  const rl = createInterface({ input: process.stdin, output: process.stdout });
11
- rl.question(prompt, (answer) => { rl.close(); resolve(answer.trim().toLowerCase() === 'y'); });
11
+ rl.question(question, (answer) => { rl.close(); resolve(answer.trim()); });
12
12
  });
13
13
  }
14
14
 
@@ -45,17 +45,32 @@ export async function teamList() {
45
45
  }
46
46
 
47
47
  export async function teamDelete(id) {
48
- const ok = await confirm(` This will archive the team directory. Continue? [y/N] `);
49
- if (!ok) {
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 {
50
73
  console.log(chalk.dim(' Cancelled.'));
51
- return;
52
- }
53
- try {
54
- await apiCall('DELETE', `/api/teams/${encodeURIComponent(id)}`);
55
- console.log(chalk.green(` Archived team "${id}"`) + chalk.dim(' — restore with `groove team restore <id>`'));
56
- } catch (err) {
57
- console.error(chalk.red(' Failed:'), err.message);
58
- process.exit(1);
59
74
  }
60
75
  }
61
76
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.115",
3
+ "version": "0.27.117",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1138,8 +1138,9 @@ export function createApi(app, daemon) {
1138
1138
 
1139
1139
  app.delete('/api/teams/:id', (req, res) => {
1140
1140
  try {
1141
- daemon.teams.delete(req.params.id);
1142
- daemon.audit.log('team.delete', { id: req.params.id });
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 });
1143
1144
  res.json({ ok: true });
1144
1145
  } catch (err) {
1145
1146
  res.status(400).json({ error: err.message });