@goodandready/dsh-goal 0.2.9 → 0.2.10

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/lib/index.js CHANGED
@@ -22,6 +22,15 @@ export const Config = z.object({
22
22
  maxTokenBudget: z.number().default(0).description('Maximum token budget per goal session (0 to disable)'),
23
23
  budgetWarningThreshold: z.number().default(80).description('Percentage of token budget consumed before model warning injection (e.g. 80)'),
24
24
  autoCheckpointOnMilestone: z.boolean().default(false).description('Automatically create git commit checkpoint upon milestone completion'),
25
+ enableLiveActivityFeed: z.boolean().default(true).description('Display compact recent tool and control activity feed in details modal'),
26
+ enablePreplanning: z.boolean().default(true).description('Generate initial draft plan for approval before launching autonomous turns'),
27
+ autoBranchOnGoalStart: z.boolean().default(true).description('Automatically create dedicated isolated git branch for goal execution'),
28
+ enablePostGoalRetrospective: z.boolean().default(true).description('Generate structured retrospective and analytics card upon goal completion'),
29
+ autoScaleBudgetNearCompletion: z.boolean().default(false).description('Automatically grant token buffer extension if budget reaches 100% near completion'),
30
+ enableTemplatesDrawer: z.boolean().default(true).description('Provide pre-configured engineering goal templates in UI drawer'),
31
+ enableMilestoneDependencies: z.boolean().default(true).description('Enforce milestone dependency ordering and block premature execution'),
32
+ soundScheme: z.string().default('default').description('Audio theme for status and milestone notifications'),
33
+ enableVoiceAnnouncements: z.boolean().default(false).description('Use Web Speech API for voice announcements on milestone events'),
25
34
  storagePath: z.string().default('').description('Custom filesystem path for persistent state storage'),
26
35
  });
27
36
 
@@ -43,6 +52,15 @@ export function apply(ctx, config = {}) {
43
52
  maxTokenBudget: config?.maxTokenBudget ?? 0,
44
53
  budgetWarningThreshold: config?.budgetWarningThreshold ?? 80,
45
54
  autoCheckpointOnMilestone: config?.autoCheckpointOnMilestone ?? false,
55
+ enableLiveActivityFeed: config?.enableLiveActivityFeed ?? true,
56
+ enablePreplanning: config?.enablePreplanning ?? true,
57
+ autoBranchOnGoalStart: config?.autoBranchOnGoalStart ?? true,
58
+ enablePostGoalRetrospective: config?.enablePostGoalRetrospective ?? true,
59
+ autoScaleBudgetNearCompletion: config?.autoScaleBudgetNearCompletion ?? false,
60
+ enableTemplatesDrawer: config?.enableTemplatesDrawer ?? true,
61
+ enableMilestoneDependencies: config?.enableMilestoneDependencies ?? true,
62
+ soundScheme: config?.soundScheme ?? 'default',
63
+ enableVoiceAnnouncements: config?.enableVoiceAnnouncements ?? false,
46
64
  storagePath: config?.storagePath,
47
65
  };
48
66
 
@@ -60,6 +78,15 @@ export function apply(ctx, config = {}) {
60
78
  maxTokenBudget: currentSettings.maxTokenBudget,
61
79
  budgetWarningThreshold: currentSettings.budgetWarningThreshold,
62
80
  autoCheckpointOnMilestone: currentSettings.autoCheckpointOnMilestone,
81
+ enableLiveActivityFeed: currentSettings.enableLiveActivityFeed,
82
+ enablePreplanning: currentSettings.enablePreplanning,
83
+ autoBranchOnGoalStart: currentSettings.autoBranchOnGoalStart,
84
+ enablePostGoalRetrospective: currentSettings.enablePostGoalRetrospective,
85
+ autoScaleBudgetNearCompletion: currentSettings.autoScaleBudgetNearCompletion,
86
+ enableTemplatesDrawer: currentSettings.enableTemplatesDrawer,
87
+ enableMilestoneDependencies: currentSettings.enableMilestoneDependencies,
88
+ soundScheme: currentSettings.soundScheme,
89
+ enableVoiceAnnouncements: currentSettings.enableVoiceAnnouncements,
63
90
  storagePath,
64
91
  });
65
92
 
@@ -220,6 +247,15 @@ export function apply(ctx, config = {}) {
220
247
  maxTokenBudget: live.maxTokenBudget,
221
248
  budgetWarningThreshold: live.budgetWarningThreshold,
222
249
  autoCheckpointOnMilestone: live.autoCheckpointOnMilestone,
250
+ enableLiveActivityFeed: live.enableLiveActivityFeed,
251
+ enablePreplanning: live.enablePreplanning,
252
+ autoBranchOnGoalStart: live.autoBranchOnGoalStart,
253
+ enablePostGoalRetrospective: live.enablePostGoalRetrospective,
254
+ autoScaleBudgetNearCompletion: live.autoScaleBudgetNearCompletion,
255
+ enableTemplatesDrawer: live.enableTemplatesDrawer,
256
+ enableMilestoneDependencies: live.enableMilestoneDependencies,
257
+ soundScheme: live.soundScheme,
258
+ enableVoiceAnnouncements: live.enableVoiceAnnouncements,
223
259
  });
224
260
  };
225
261
 
package/lib/routes.js CHANGED
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { MilestoneStatus, detectLanguage, sessionIdOf } from './goal-engine-constants.js';
4
4
  import { saveGoalArtifact, rollbackToCheckpoint } from './engine-reports.js';
5
+ import { getTemplatesCatalogue } from './engine-templates.js';
5
6
 
6
7
  export function isLoopback(value) {
7
8
  if (!value) return false;
@@ -194,6 +195,12 @@ export function registerRoutes(ctx, {
194
195
 
195
196
  res.setHeader('Content-Type', 'application/json; charset=utf-8');
196
197
 
198
+ // GET /dsh-goal/templates
199
+ if (req.method === 'GET' && (pathname === '/dsh-goal/templates' || pathname === '/dsh-goal/templates/')) {
200
+ res.statusCode = 200;
201
+ return res.end(JSON.stringify({ ok: true, templates: getTemplatesCatalogue() }));
202
+ }
203
+
197
204
  // GET /dsh-goal/state
198
205
  if (req.method === 'GET' && (pathname === '/dsh-goal/state' || pathname === '/dsh-goal/state/')) {
199
206
  const sid = sessionIdOf(req, 'default');
@@ -421,6 +428,51 @@ export function registerRoutes(ctx, {
421
428
  return res.end(JSON.stringify({ ok: true, artifact, state: snap }));
422
429
  }
423
430
 
431
+ case 'intervene': {
432
+ result = engine.intervene(data, sid);
433
+ if (data.resume) {
434
+ engine.resume(sid);
435
+ const prompt = engine.getStatePromptInjection(sid);
436
+ if (typeof resumeActiveAgent === 'function') {
437
+ resumeActiveAgent(prompt, sid);
438
+ }
439
+ }
440
+ break;
441
+ }
442
+
443
+ case 'preplan_approve': {
444
+ result = engine.approvePreplan(sid);
445
+ const prompt = engine.getStatePromptInjection(sid);
446
+ if (typeof resumeActiveAgent === 'function') {
447
+ resumeActiveAgent(prompt, sid);
448
+ }
449
+ break;
450
+ }
451
+
452
+ case 'branch_action': {
453
+ const op = String(data.operation || data.branchOperation || 'merge').toLowerCase();
454
+ const targetBranch = String(data.targetBranch || 'main');
455
+ if (op === 'merge') {
456
+ const ok = engine.mergeGoalBranch(targetBranch, sid);
457
+ if (!ok) {
458
+ res.statusCode = 500;
459
+ return res.end(JSON.stringify({ error: `Failed to merge goal branch into ${targetBranch}` }));
460
+ }
461
+ } else if (op === 'discard') {
462
+ const ok = engine.discardGoalBranch(targetBranch, sid);
463
+ if (!ok) {
464
+ res.statusCode = 500;
465
+ return res.end(JSON.stringify({ error: 'Failed to discard goal branch' }));
466
+ }
467
+ }
468
+ result = engine.getSnapshot(sid);
469
+ break;
470
+ }
471
+
472
+ case 'templates':
473
+ res.statusCode = 200;
474
+ return res.end(JSON.stringify({ ok: true, templates: getTemplatesCatalogue() }));
475
+
424
476
  default:
425
477
  res.statusCode = 400;
426
478
  return res.end(JSON.stringify({ error: `Unknown action: ${action}` }));
package/lib/tools.js CHANGED
@@ -195,6 +195,9 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
195
195
  const handleSetMilestones = async ({ milestones }, toolCtx) => {
196
196
  const sid = sessionIdOf(toolCtx, 'default');
197
197
  const snap = engine.setMilestones(milestones, sid);
198
+ if (typeof engine.recordToolActivity === 'function') {
199
+ engine.recordToolActivity('goal_set_milestones', 'success', 'Defined milestones', sid);
200
+ }
198
201
  return {
199
202
  success: true,
200
203
  count: snap.milestones?.length || 0,
@@ -215,6 +218,7 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
215
218
  properties: {
216
219
  id: { type: 'string', description: 'Short identifier, e.g. M1, step-1' },
217
220
  title: { type: 'string', description: 'Concise actionable title' },
221
+ dependsOn: { type: 'array', items: { type: 'string' }, description: 'Prerequisite milestone IDs' },
218
222
  },
219
223
  required: ['id', 'title'],
220
224
  },
@@ -231,7 +235,10 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
231
235
  // Tool 5: goal_update_progress
232
236
  const handleUpdateProgress = async ({ milestone_id, status, notes, checklist }, toolCtx) => {
233
237
  const sid = sessionIdOf(toolCtx, 'default');
234
- engine.updateMilestone(milestone_id, status, notes, sid, checklist);
238
+ const ok = engine.updateMilestone(milestone_id, status, notes, sid, checklist);
239
+ if (typeof engine.recordToolActivity === 'function') {
240
+ engine.recordToolActivity('goal_update_progress', ok ? 'success' : 'error', String(milestone_id) + ' -> ' + String(status), sid);
241
+ }
235
242
  const snap = engine.getSnapshot(sid);
236
243
  const targetMilestone = snap.milestones?.find((m) => m.id === String(milestone_id) || m.id.toLowerCase().replace(/[^a-z0-9]/g, '') === String(milestone_id).toLowerCase().replace(/[^a-z0-9]/g, '') || m.id.toLowerCase().replace(/[^0-9]/g, '') === String(milestone_id).toLowerCase().replace(/[^0-9]/g, ''));
237
244
  return {
@@ -282,6 +289,9 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
282
289
  const handleGoalFinish = async ({ summary }, toolCtx) => {
283
290
  const sid = sessionIdOf(toolCtx, 'default');
284
291
  const snap = engine.completeGoal(summary, sid);
292
+ if (typeof engine.recordToolActivity === 'function') {
293
+ engine.recordToolActivity('goal_finish', 'success', summary ? summary.slice(0, 80) : 'Goal finished', sid);
294
+ }
285
295
  return {
286
296
  success: true,
287
297
  completed: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-goal",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Autonomous Goal Execution & Multi-Turn Task Tracking Engine with Sticky Header for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",