@goodandready/dsh-goal 0.2.15 → 0.2.17

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/client.js CHANGED
@@ -5228,16 +5228,9 @@ window.__ModuleLoader__.load({
5228
5228
  GoalSettingsCard,
5229
5229
  );
5230
5230
 
5231
- registerSlotSafe(
5232
- 'settings.plugin.item',
5233
- {
5234
- name: 'settings.plugin.item',
5235
- key: NS,
5236
- locale: NS,
5237
- inject: () => ({ ctx, scope: configForms }),
5238
- },
5239
- GoalSettingsCard,
5240
- );
5231
+ // settings.plugin.item is gone: it was retired before DSH 0.1.7-rc.2, so
5232
+ // it only mounted GoalSettingsCard a second time on a seat that no longer
5233
+ // exists. plugins.item and plugins.row.config above cover both releases.
5241
5234
 
5242
5235
  return () => {
5243
5236
  for (const dispose of disposers) {
@@ -5305,16 +5298,8 @@ window.__ModuleLoader__.load({
5305
5298
  GoalSettingsCard,
5306
5299
  );
5307
5300
 
5308
- registerSlotSafe(
5309
- 'settings.plugin.item',
5310
- {
5311
- name: 'settings.plugin.item',
5312
- key: NS,
5313
- locale: NS,
5314
- inject: () => ({ ctx, scope: configForms }),
5315
- },
5316
- GoalSettingsCard,
5317
- );
5301
+ // settings.plugin.item is gone for the same reason: retired before DSH
5302
+ // 0.1.7-rc.2, it mounted GoalSettingsCard a second time on a dead seat.
5318
5303
  }
5319
5304
  };
5320
5305
 
package/lib/index.js CHANGED
@@ -18,27 +18,38 @@ export const inject = ['webServer', 'settings'];
18
18
  const NS = 'dsh-goal';
19
19
 
20
20
  export const Config = z.object({
21
- maxIterations: z.number().default(25).description('Safety limit: max autonomous iterations per goal'),
22
- autoDrive: z.boolean().default(true).description('Automatically continue the loop after each turn'),
23
- enableSound: z.boolean().default(true).description('Play synthesized audio chime on goal completion or failure'),
24
- showQuickLaunchButton: z.boolean().default(true).description('Show quick launch goal button above composer dock'),
25
- consecutiveToolFailureLimit: z.number().default(3).description('Auto-pause goal if N consecutive turns encounter tool execution errors (0 to disable)'),
26
- enableBrowserNotifications: z.boolean().default(true).description('Show desktop notifications on goal completion or failure'),
27
- maxTokenBudget: z.number().default(0).description('Maximum token budget per goal session (0 to disable)'),
28
- budgetWarningThreshold: z.number().default(80).description('Percentage of token budget consumed before model warning injection (e.g. 80)'),
29
- autoCheckpointOnMilestone: z.boolean().default(false).description('Automatically create git commit checkpoint upon milestone completion'),
30
- enableLiveActivityFeed: z.boolean().default(true).description('Display compact recent tool and control activity feed in details modal'),
31
- enablePreplanning: z.boolean().default(true).description('Generate initial draft plan for approval before launching autonomous turns'),
32
- autoBranchOnGoalStart: z.boolean().default(true).description('Automatically create dedicated isolated git branch for goal execution'),
33
- enablePostGoalRetrospective: z.boolean().default(true).description('Generate structured retrospective and analytics card upon goal completion'),
34
- autoScaleBudgetNearCompletion: z.boolean().default(false).description('Automatically grant token buffer extension if budget reaches 100% near completion'),
35
- enableTemplatesDrawer: z.boolean().default(true).description('Provide pre-configured engineering goal templates in UI drawer'),
36
- enableMilestoneDependencies: z.boolean().default(true).description('Enforce milestone dependency ordering and block premature execution'),
37
- soundScheme: z.string().default('default').description('Audio theme for status and milestone notifications'),
38
- enableVoiceAnnouncements: z.boolean().default(false).description('Use Web Speech API for voice announcements on milestone events'),
39
- storagePath: z.string().default('').description('Custom filesystem path for persistent state storage'),
21
+ maxIterations: z.number().default(25).volatile().description('Safety limit: max autonomous iterations per goal'),
22
+ autoDrive: z.boolean().default(true).volatile().description('Automatically continue the loop after each turn'),
23
+ enableSound: z.boolean().default(true).volatile().description('Play synthesized audio chime on goal completion or failure'),
24
+ showQuickLaunchButton: z.boolean().default(true).volatile().description('Show quick launch goal button above composer dock'),
25
+ consecutiveToolFailureLimit: z.number().default(3).volatile().description('Auto-pause goal if N consecutive turns encounter tool execution errors (0 to disable)'),
26
+ enableBrowserNotifications: z.boolean().default(true).volatile().description('Show desktop notifications on goal completion or failure'),
27
+ maxTokenBudget: z.number().default(0).volatile().description('Maximum token budget per goal session (0 to disable)'),
28
+ budgetWarningThreshold: z.number().default(80).volatile().description('Percentage of token budget consumed before model warning injection (e.g. 80)'),
29
+ autoCheckpointOnMilestone: z.boolean().default(false).volatile().description('Automatically create git commit checkpoint upon milestone completion'),
30
+ enableLiveActivityFeed: z.boolean().default(true).volatile().description('Display compact recent tool and control activity feed in details modal'),
31
+ enablePreplanning: z.boolean().default(true).volatile().description('Generate initial draft plan for approval before launching autonomous turns'),
32
+ autoBranchOnGoalStart: z.boolean().default(true).volatile().description('Automatically create dedicated isolated git branch for goal execution'),
33
+ enablePostGoalRetrospective: z.boolean().default(true).volatile().description('Generate structured retrospective and analytics card upon goal completion'),
34
+ autoScaleBudgetNearCompletion: z.boolean().default(false).volatile().description('Automatically grant token buffer extension if budget reaches 100% near completion'),
35
+ enableTemplatesDrawer: z.boolean().default(true).volatile().description('Provide pre-configured engineering goal templates in UI drawer'),
36
+ enableMilestoneDependencies: z.boolean().default(true).volatile().description('Enforce milestone dependency ordering and block premature execution'),
37
+ soundScheme: z.string().default('default').volatile().description('Audio theme for status and milestone notifications'),
38
+ enableVoiceAnnouncements: z.boolean().default(false).volatile().description('Use Web Speech API for voice announcements on milestone events'),
39
+ storagePath: z.string().default('').volatile().description('Custom filesystem path for persistent state storage'),
40
40
  });
41
41
 
42
+ // DSH serves a namespace's settings form from the volatile fields of its profile
43
+ // entry schema, and a volatile field holds a Volatile box rather than its value.
44
+ // Unwrap before any caller reads one, and read lazily: the Loader mutates the
45
+ // boxes in place and re-announces them with loader/volatile-update.
46
+ export function plainConfig(value) {
47
+ if (value === null || typeof value !== 'object') return value
48
+ if (Array.isArray(value)) return value.map(plainConfig)
49
+ if (typeof value.get === 'function') return plainConfig(value.get())
50
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, plainConfig(v)]))
51
+ }
52
+
42
53
  /**
43
54
  * Safely access a service from Cordis context without throwing if un-injected.
44
55
  * @param {any} ctx
@@ -58,7 +69,6 @@ export function safeService(ctx, name) {
58
69
  }
59
70
 
60
71
  export function apply(ctx, config = {}) {
61
- let settingsScope = null;
62
72
  const sseClients = new Map();
63
73
 
64
74
  let currentSettings = {
@@ -290,31 +300,26 @@ export function apply(ctx, config = {}) {
290
300
  }
291
301
  };
292
302
 
293
- if (typeof ctx?.inject === 'function') {
294
- ctx.inject(['settings'], (sctx) => {
295
- try {
296
- const scope = sctx.settings?.register?.(NS, Config, { base: currentSettings });
297
- if (scope) {
298
- settingsScope = scope;
299
- if (typeof scope.get === 'function') {
300
- applySettings(scope.get());
301
- }
302
- if (typeof scope.subscribe === 'function') {
303
- sctx.effect?.(() => {
304
- const off = scope.subscribe(() => {
305
- if (typeof scope.get === 'function') applySettings(scope.get());
306
- });
307
- return () => {
308
- if (typeof off === 'function') off();
309
- settingsScope = null;
310
- };
311
- }, 'dsh-goal: settings subscription');
312
- }
303
+ // DSH hands the plugin the entry config, whose .volatile() fields hold Volatile
304
+ // boxes. The settings service re-merges that config and announces it with
305
+ // loader/volatile-update, which both 0.1.7-rc.2 and 0.2.0 emit. settings.register
306
+ // exists in neither release, so the scope it returned never existed and every
307
+ // setting changed in the card had no effect on the running engine.
308
+ const readEntrySettings = () => plainConfig(config || {});
309
+ applySettings(readEntrySettings());
310
+
311
+ if (typeof ctx?.on === 'function') {
312
+ try {
313
+ ctx.on('loader/volatile-update', () => {
314
+ try {
315
+ applySettings(readEntrySettings());
316
+ } catch (err) {
317
+ logger.warn?.('dsh-goal: settings refresh failed:', err?.message || err);
313
318
  }
314
- } catch (err) {
315
- logger.warn?.('Settings register skipped:', err.message);
316
- }
317
- });
319
+ });
320
+ } catch (err) {
321
+ logger.warn?.('dsh-goal: volatile-update subscription failed:', err?.message || err);
322
+ }
318
323
  }
319
324
 
320
325
  if (typeof ctx?.effect === 'function') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-goal",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
4
4
  "description": "Core Goal Addon (Token Budget, Milestones, Git Snapshots & Retrospective Reports) for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -55,14 +55,14 @@
55
55
  "peerDependencies": {
56
56
  "@deepseek-ai/cordis": "^4.0.1",
57
57
  "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1",
58
- "@deepseek-ai/schemastery": "^3.18.1",
58
+ "@deepseek-ai/schemastery": "^3.18.4",
59
59
  "@deepseek-ai/dsh-goal": "^0.1.7-rc.2 || ^0.2.0-rc.1"
60
60
  },
61
61
  "devDependencies": {
62
- "@deepseek-ai/schemastery": "^3.18.1"
62
+ "@deepseek-ai/schemastery": "^3.18.4"
63
63
  },
64
64
  "dependencies": {
65
- "@deepseek-ai/schemastery": "^3.18.1"
65
+ "@deepseek-ai/schemastery": "^3.18.4"
66
66
  },
67
67
  "peerDependenciesMeta": {
68
68
  "@deepseek-ai/dsh-goal": {