aimeat 1.34.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/locales/en.json +52 -4
  2. package/dist/locales/fi.json +52 -4
  3. package/dist/public/css/views/secretary.css +52 -0
  4. package/dist/public/js/i18n.js +9 -0
  5. package/dist/public/js/services/secretary-helpers.js +8 -4
  6. package/dist/public/js/services/secretary-policy.js +28 -3
  7. package/dist/public/views/profile/agents/agent-card.js +6 -4
  8. package/dist/public/views/profile/agents/tab-integration.js +5 -2
  9. package/dist/public/views/secretary/cards.js +46 -15
  10. package/dist/public/views/secretary/dashboard.js +68 -2
  11. package/dist/public/views/secretary.js +208 -40
  12. package/dist/src/cli/connect/mcp/tools/organisms.d.ts +2 -0
  13. package/dist/src/cli/connect/mcp/tools/organisms.d.ts.map +1 -1
  14. package/dist/src/cli/connect/mcp/tools/organisms.js +9 -1
  15. package/dist/src/cli/connect/mcp/tools/organisms.js.map +1 -1
  16. package/dist/src/cli/connect/onboarding-prompt.d.ts +3 -0
  17. package/dist/src/cli/connect/onboarding-prompt.d.ts.map +1 -1
  18. package/dist/src/cli/connect/onboarding-prompt.js +10 -3
  19. package/dist/src/cli/connect/onboarding-prompt.js.map +1 -1
  20. package/dist/src/generated/api-types.d.ts +309 -2
  21. package/dist/src/generated/api-types.d.ts.map +1 -1
  22. package/dist/src/mcp/agent-onboarding.d.ts +4 -0
  23. package/dist/src/mcp/agent-onboarding.d.ts.map +1 -1
  24. package/dist/src/mcp/agent-onboarding.js +28 -2
  25. package/dist/src/mcp/agent-onboarding.js.map +1 -1
  26. package/dist/src/models/agent-onboarding-schemas.d.ts +47 -0
  27. package/dist/src/models/agent-onboarding-schemas.d.ts.map +1 -1
  28. package/dist/src/models/agent-onboarding-schemas.js +117 -0
  29. package/dist/src/models/agent-onboarding-schemas.js.map +1 -1
  30. package/dist/src/routes/agent-onboarding.d.ts +5 -0
  31. package/dist/src/routes/agent-onboarding.d.ts.map +1 -1
  32. package/dist/src/routes/agent-onboarding.js +21 -2
  33. package/dist/src/routes/agent-onboarding.js.map +1 -1
  34. package/dist/src/routes/secretary.d.ts +7 -2
  35. package/dist/src/routes/secretary.d.ts.map +1 -1
  36. package/dist/src/routes/secretary.js +119 -28
  37. package/dist/src/routes/secretary.js.map +1 -1
  38. package/dist/src/services/onboarding-guide.d.ts +53 -0
  39. package/dist/src/services/onboarding-guide.d.ts.map +1 -0
  40. package/dist/src/services/onboarding-guide.js +81 -0
  41. package/dist/src/services/onboarding-guide.js.map +1 -0
  42. package/dist/src/services/scheduler.d.ts +9 -0
  43. package/dist/src/services/scheduler.d.ts.map +1 -1
  44. package/dist/src/services/scheduler.js +48 -23
  45. package/dist/src/services/scheduler.js.map +1 -1
  46. package/dist/src/services/secretary-workbrief.d.ts +144 -0
  47. package/dist/src/services/secretary-workbrief.d.ts.map +1 -0
  48. package/dist/src/services/secretary-workbrief.js +315 -0
  49. package/dist/src/services/secretary-workbrief.js.map +1 -0
  50. package/dist/src/services/secretary-worktier.d.ts +118 -0
  51. package/dist/src/services/secretary-worktier.d.ts.map +1 -0
  52. package/dist/src/services/secretary-worktier.js +157 -0
  53. package/dist/src/services/secretary-worktier.js.map +1 -0
  54. package/dist/src/services/skill-bundle/generator.d.ts +3 -0
  55. package/dist/src/services/skill-bundle/generator.d.ts.map +1 -1
  56. package/dist/src/services/skill-bundle/generator.js +19 -0
  57. package/dist/src/services/skill-bundle/generator.js.map +1 -1
  58. package/package.json +1 -1
@@ -0,0 +1,315 @@
1
+ /**
2
+ * @file secretary-workbrief.ts
3
+ * @description Build a WORK BRIEF — the artifact that makes a Builder (a connected big AI via the appdev
4
+ * MCP tools, e.g. Claude Desktop) succeed at HEAVY work the cheap Secretary must NOT do itself. This
5
+ * RELOCATES the grounding that secretary-authoring.ts used to feed a cheap one-shot model (the Current
6
+ * picture, real Discovery sources, the exact JSON Schemas, the strategy focus) OUT of a cheap-model prompt
7
+ * and INTO a brief handed to a capable model. The Secretary detects a structural gap (assessGaps) and
8
+ * proposes a brief; it never authors the content. The Builder executes the brief via MCP — server-side
9
+ * schema validation keeps it honest — either by the owner pasting the brief into Claude Desktop or by a
10
+ * connected Builder agent picking up a queued task (POST /v1/secretary/brief/:id/dispatch).
11
+ *
12
+ * Brief assembly is DETERMINISTIC (no AI) so it stays firmly "light": gaps + overview + sources + schemas
13
+ * are real data. An optional `phrase` seam lets the caller refine the one-line objective with a single
14
+ * cheap completion (explicitly told NOT to author facts); omit it for a fully deterministic brief.
15
+ * @structure WorkBrief · BRIEF_KEY_PREFIX · renderBriefMarkdown (pure) · buildWorkBrief · saveWorkBrief
16
+ * @usage import { buildWorkBrief, saveWorkBrief } from './secretary-workbrief.js';
17
+ * @version-history
18
+ * v0.1.0 — 2026-07-01 — Initial: deterministic Work Brief builder (objective + current picture + real
19
+ * Discovery sources + exact record schemas + MCP playbook + definition-of-done + boundaries),
20
+ * persisted as secretary.brief.{id}; replaces the cheap one-shot authoring as the heavy-work path.
21
+ */
22
+ import { randomUUID } from 'node:crypto';
23
+ import { buildWorkspaceOverview, buildOrganismOverview, collectWorkspaceSummary } from './structure-overview.js';
24
+ import { buildDiscoveryRegistry, runDiscovery } from './discovery/index.js';
25
+ import { logger } from '../utils/logger.js';
26
+ import { assessGaps, gapKey } from './secretary-worktier.js';
27
+ /** Memory key prefix for persisted Work Briefs (mirrors secretary.clarify.* / secretary.trigger.*). */
28
+ export const BRIEF_KEY_PREFIX = 'secretary.brief.';
29
+ /** Derive a deterministic one-line objective from the gaps (the `phrase` seam may refine it later). */
30
+ export function deriveObjective(gaps, wsName) {
31
+ const where = wsName ? `workspace "${wsName}"` : 'this organism';
32
+ const kinds = new Set(gaps.map((g) => g.kind));
33
+ if (kinds.has('empty-workspace'))
34
+ return `Build out ${where}: create the structure it needs and fill it with real, grounded content.`;
35
+ if (kinds.has('empty-space')) {
36
+ const names = gaps.filter((g) => g.kind === 'empty-space' && g.spaceName).map((g) => `"${g.spaceName}"`);
37
+ return `Fill the empty space${names.length === 1 ? '' : 's'} in ${where} with real data: ${names.join(', ') || 'the empty spaces'}.`;
38
+ }
39
+ if (kinds.has('kpi-off-target')) {
40
+ const names = gaps.filter((g) => g.kind === 'kpi-off-target' && g.kpiName).map((g) => `"${g.kpiName}"`);
41
+ return `Move the off-target KPI${names.length === 1 ? '' : 's'} in ${where} toward target: ${names.join(', ')}.`;
42
+ }
43
+ if (kinds.has('stale'))
44
+ return `Review and refresh ${where} — its content has gone stale; bring it up to date.`;
45
+ return `Improve ${where}.`;
46
+ }
47
+ /** Build the MCP playbook hints appropriate to the gap kinds present. */
48
+ export function deriveMcpHints(gaps, organismId, ws) {
49
+ const kinds = new Set(gaps.map((g) => g.kind));
50
+ const hints = [];
51
+ hints.push(`Start: \`aimeat_organism_overview({ organism_id: "${organismId}" })\` to see the whole picture.`);
52
+ if (ws)
53
+ hints.push(`Read the target: \`aimeat_workspace_read({ organism_id: "${organismId}", ws: "${ws}" })\` — manifest + existing objects.`);
54
+ if (kinds.has('empty-workspace')) {
55
+ hints.push(`If the workspace needs more structure: \`aimeat_workspace_update({ organism_id, ws, add_spaces: [...] })\` (additive) or \`aimeat_workspace_create({ organism_id, name, manifest, schemas })\` for a new one.`);
56
+ }
57
+ hints.push(`Write each item as a DRAFT: \`aimeat_workspace_write({ organism_id, ws, space, value, id? })\` — the space is the objectType NAME. The write is validated against the locked schema; fix and re-write on any error.`);
58
+ hints.push(`Publish when ready: \`aimeat_workspace_publish({ organism_id, ws, namespace, id })\` (skip if a publish gate requires human approval — leave drafts).`);
59
+ hints.push(`Records spaces: write ONLY real, grounded entries. If there is no real data for a space, leave it empty — do not invent.`);
60
+ return hints;
61
+ }
62
+ /**
63
+ * Render the brief markdown PURELY from its parts (no storage/AI) so it unit-tests directly. This is the
64
+ * exact text a Builder receives — objective, why, current picture, real sources, target schemas, the MCP
65
+ * playbook, definition-of-done, and the one load-bearing boundary ("leave a records space empty rather than
66
+ * invent"). The cheap Secretary never executes any of this; it only assembles it from real data.
67
+ */
68
+ export function renderBriefMarkdown(p) {
69
+ const out = [];
70
+ out.push(`# Work brief — ${p.objective}`);
71
+ out.push('');
72
+ out.push(`_For: ${p.ownerName} · context "${p.contextName}"${p.wsName ? ` · workspace "${p.wsName}"` : ''} · organism \`${p.organismId}\`${p.ws ? ` · ws \`${p.ws}\`` : ''}_`);
73
+ out.push('');
74
+ out.push('## Objective');
75
+ out.push(p.objective);
76
+ out.push('');
77
+ if (p.whyLines.length) {
78
+ out.push('## Why / context');
79
+ for (const l of p.whyLines)
80
+ out.push(`- ${l}`);
81
+ out.push('');
82
+ }
83
+ out.push('## Current picture');
84
+ out.push(p.currentPicture.trim() || '_(empty)_');
85
+ out.push('');
86
+ if (p.sources.length) {
87
+ out.push('## Real sources — ground your work in these (cite by title; do not reinvent what already exists)');
88
+ for (const s of p.sources)
89
+ out.push(`- [${s.type}] ${s.title}${s.description ? ` — ${s.description}` : ''}`);
90
+ out.push('');
91
+ }
92
+ else {
93
+ out.push('## Real sources');
94
+ out.push('_No existing material was found for this. If you cannot ground the work in something real, ask the owner for the facts rather than inventing them._');
95
+ out.push('');
96
+ }
97
+ if (p.recordSchemas.length) {
98
+ out.push('## Exact record schemas (each record MUST satisfy its schema)');
99
+ for (const rs of p.recordSchemas)
100
+ out.push(`- space **"${rs.space}"** (namespace \`${rs.namespace}\`):\n \`\`\`json\n ${JSON.stringify(rs.schema)}\n \`\`\``);
101
+ out.push('');
102
+ }
103
+ out.push('## How (appdev MCP playbook)');
104
+ for (const h of p.mcpHints)
105
+ out.push(`- ${h}`);
106
+ out.push('');
107
+ out.push('## Definition of done');
108
+ out.push('- The gaps below are closed with real, grounded content (documents = your reasoning/plans; records = real data only).');
109
+ out.push('- Each write passed schema validation; published items where no publish gate blocks it, drafts otherwise.');
110
+ out.push('- You verified your output against the sources and flagged any assumption explicitly.');
111
+ out.push('');
112
+ if (p.gaps.length) {
113
+ out.push('### Gaps this brief addresses');
114
+ for (const g of p.gaps)
115
+ out.push(`- ${g.detail}`);
116
+ out.push('');
117
+ }
118
+ out.push('## Boundaries');
119
+ out.push('- Stay inside this workspace\'s purpose; do not pull other areas\' topics in.');
120
+ out.push('- Do NOT fabricate facts, numbers, names, dates or record entries. Leave a records space empty rather than invent.');
121
+ return out.join('\n');
122
+ }
123
+ /**
124
+ * Build a Work Brief for a set of gaps in ONE workspace (or organism-level when `ws` is omitted). Collects
125
+ * the Current picture (overview), real Discovery sources, and the exact record schemas for any empty record
126
+ * spaces, then renders the brief markdown. Deterministic unless `phrase` is supplied to refine the objective.
127
+ * Does NOT persist — the caller (route/tick) persists via saveWorkBrief so it controls the write list.
128
+ */
129
+ export async function buildWorkBrief(storage, config, opts) {
130
+ const { owner, ownerName, active, ws, gaps } = opts;
131
+ const organismId = String(active.organismId || '');
132
+ const now = opts.now ?? new Date().toISOString();
133
+ // 1) Objective (deterministic; optionally refined by a single cheap call).
134
+ let objective = deriveObjective(gaps, opts.wsName);
135
+ if (opts.phrase) {
136
+ try {
137
+ const refined = (await opts.phrase(objective)).trim();
138
+ if (refined)
139
+ objective = refined.slice(0, 300);
140
+ }
141
+ catch (e) {
142
+ logger.warn('[secretary] brief phrase failed, using deterministic objective', { error: e?.message });
143
+ }
144
+ }
145
+ // 2) Why / context — open goals + the strategy focus milestone.
146
+ const whyLines = [];
147
+ for (const g of (opts.openGoals ?? [])) {
148
+ const title = String(g.title || '').trim();
149
+ if (title)
150
+ whyLines.push(`Goal: ${title}${g.why ? ` (why: ${String(g.why)})` : ''}`);
151
+ }
152
+ const strat = active.strategy;
153
+ if (strat?.enabled) {
154
+ const focus = (strat.milestones || []).find((m) => m && m.status !== 'reached');
155
+ if (focus?.title)
156
+ whyLines.push(`Focus milestone: ${focus.title}${focus.enables ? ` (${focus.enables})` : ''}`);
157
+ if (strat.target)
158
+ whyLines.push(`Target state: ${strat.target}`);
159
+ }
160
+ // 3) Current picture — the deterministic, never-stale overview of the target workspace (or organism).
161
+ let currentPicture = '';
162
+ try {
163
+ if (ws)
164
+ currentPicture = (await buildWorkspaceOverview(storage, config, { orgId: organismId, ws, name: opts.wsName, viewerGaii: owner })).markdown;
165
+ else
166
+ currentPicture = (await buildOrganismOverview(storage, config, { orgId: organismId, viewerGaii: owner })).markdown;
167
+ }
168
+ catch (e) {
169
+ logger.warn('[secretary] brief overview failed', { error: e?.message });
170
+ }
171
+ // 4) Real sources — Discovery scope=own (the same grounding the old authoring used, now for the Builder).
172
+ const sources = [];
173
+ try {
174
+ const registry = buildDiscoveryRegistry(storage, config);
175
+ const q = [opts.wsName || '', strat?.target || '', ...gaps.map((g) => g.spaceName || '')].filter(Boolean).join(' ').slice(0, 200);
176
+ const discCtx = {
177
+ caller: { ownerName, sub: ownerName, gaii: owner, isOwnerSession: true, scopes: [] },
178
+ scope: 'own', filters: { q, limit: 12 }, nodeId: config.nodeId,
179
+ };
180
+ for (const e of (await runDiscovery(registry, discCtx)).slice(0, 12)) {
181
+ sources.push({ type: String(e.type), title: String(e.title), description: e.description ? String(e.description).replace(/\s+/g, ' ').slice(0, 160) : undefined });
182
+ }
183
+ }
184
+ catch (e) {
185
+ logger.warn('[secretary] brief discovery failed', { error: e?.message });
186
+ }
187
+ // 5) Exact record schemas for any empty RECORD spaces in the gaps (so the Builder conforms first shot).
188
+ const recordSchemas = [];
189
+ if (ws) {
190
+ const root = `organism.${organismId}.w.${ws}`;
191
+ for (const g of gaps) {
192
+ if (g.kind !== 'empty-space' || g.spaceMode !== 'records' || !g.namespace)
193
+ continue;
194
+ try {
195
+ const sc = await storage.findApplicableSchema(`${root}.${g.namespace}.__probe`);
196
+ if (sc?.schemaJson)
197
+ recordSchemas.push({ space: g.spaceName || g.namespace, namespace: g.namespace, schema: sc.schemaJson });
198
+ }
199
+ catch { /* best-effort */ }
200
+ }
201
+ }
202
+ const mcpHints = deriveMcpHints(gaps, organismId, ws);
203
+ const brief = renderBriefMarkdown({
204
+ objective, ownerName, contextName: active.name || 'personal', organismId, ws, wsName: opts.wsName,
205
+ whyLines, currentPicture, sources, recordSchemas, gaps, mcpHints,
206
+ });
207
+ return {
208
+ id: randomUUID(), contextId: active.id, contextName: active.name || 'personal', organismId,
209
+ ws, wsName: opts.wsName, tier: 'heavy', status: 'proposed', objective, gaps, brief, sources, mcpHints,
210
+ createdAt: now, updatedAt: now,
211
+ };
212
+ }
213
+ /** Persist a Work Brief at secretary.brief.{id} (mirrors the clarify-job write). Returns the memory key. */
214
+ export async function saveWorkBrief(storage, ownerGhii, brief) {
215
+ const key = `${BRIEF_KEY_PREFIX}${brief.id}`;
216
+ await storage.setMemory({
217
+ key, ownerGaii: ownerGhii, value: brief,
218
+ visibility: 'private', tags: ['secretary', 'brief', brief.status], ttlHours: null,
219
+ version: 1, createdAt: brief.createdAt, updatedAt: brief.updatedAt,
220
+ });
221
+ return key;
222
+ }
223
+ /**
224
+ * Detect structural gaps across a context's workspaces and propose Work Briefs for the NEW ones (deduped
225
+ * against existing OPEN briefs by gap key), bounded. Deterministic + idempotent: repeated calls converge
226
+ * instead of spamming. Shared by the autonomous tick (free, every run) and the setup / on-demand route, so
227
+ * both produce identical briefs. No paid AI call (storage reads + best-effort Discovery only).
228
+ */
229
+ export async function proposeWorkBriefs(storage, config, opts) {
230
+ const { ownerGhii, ownerName, active, wsList } = opts;
231
+ const out = { writes: [], briefs: [] };
232
+ if (!active.organismId || !wsList.length)
233
+ return out;
234
+ const maxWs = opts.maxWs ?? 12;
235
+ const maxNew = opts.maxNewBriefs ?? 3;
236
+ // Gaps already covered by an EXISTING brief in this context (proposed/dispatched, OR 'done' so a brief the
237
+ // owner resolved/dismissed isn't re-proposed every tick) — don't re-propose. Once a gap is genuinely
238
+ // closed (workspace filled), assessGaps no longer reports it, so this only suppresses live duplicates.
239
+ const existing = await storage.listMemory(ownerGhii, { prefix: BRIEF_KEY_PREFIX }).catch(() => []);
240
+ const covered = new Set();
241
+ for (const rec of existing) {
242
+ const b = rec.value;
243
+ if (!b || b.contextId !== active.id)
244
+ continue;
245
+ for (const g of (b.gaps || []))
246
+ covered.add(gapKey(g));
247
+ }
248
+ // A structural summary per workspace → assess gaps (pure), minus what's already covered by an open brief.
249
+ const summaries = [];
250
+ const nameByWs = new Map();
251
+ for (const ws of wsList.slice(0, maxWs)) {
252
+ nameByWs.set(ws.id, ws.name);
253
+ summaries.push(await collectWorkspaceSummary(storage, config, { orgId: active.organismId, ws: ws.id, name: ws.name, viewerGaii: ownerGhii }));
254
+ }
255
+ const gaps = assessGaps(summaries, {}).filter((g) => !covered.has(gapKey(g)));
256
+ if (!gaps.length)
257
+ return out;
258
+ // One brief per workspace, folding that workspace's new gaps, bounded.
259
+ const byWs = new Map();
260
+ for (const g of gaps) {
261
+ const arr = byWs.get(g.ws) ?? [];
262
+ arr.push(g);
263
+ byWs.set(g.ws, arr);
264
+ }
265
+ let made = 0;
266
+ for (const [ws, wsGaps] of byWs) {
267
+ if (made >= maxNew)
268
+ break;
269
+ const brief = await buildWorkBrief(storage, config, {
270
+ owner: ownerGhii, ownerName, active, ws, wsName: nameByWs.get(ws), gaps: wsGaps, openGoals: opts.openGoals, phrase: opts.phrase,
271
+ });
272
+ out.writes.push(await saveWorkBrief(storage, ownerGhii, brief));
273
+ out.briefs.push(brief);
274
+ made++;
275
+ }
276
+ return out;
277
+ }
278
+ /**
279
+ * Auto-resolve dispatched briefs whose Builder task has finished: a brief with status 'dispatched' + a
280
+ * taskId whose agent task is 'done' is flipped to 'done' so it leaves the tray on its own (no manual Done
281
+ * needed). Best-effort + idempotent. Returns the number resolved. A 'failed' task is left dispatched so the
282
+ * owner can see it stalled and re-handle it.
283
+ */
284
+ export async function resolveCompletedBriefs(storage, ownerGhii) {
285
+ const recs = await storage.listMemory(ownerGhii, { prefix: BRIEF_KEY_PREFIX }).catch(() => []);
286
+ let resolved = 0;
287
+ for (const rec of recs) {
288
+ const b = rec.value;
289
+ if (!b || b.status !== 'dispatched' || !b.taskId)
290
+ continue;
291
+ const task = await storage.getAgentTask(b.taskId).catch(() => null);
292
+ if (task && task.status === 'done') {
293
+ await updateBriefStatus(storage, ownerGhii, b.id, { status: 'done' }).catch(() => null);
294
+ resolved++;
295
+ }
296
+ }
297
+ return resolved;
298
+ }
299
+ /** Mark an existing brief dispatched/done (read-modify-write). Returns the updated brief, or null if gone. */
300
+ export async function updateBriefStatus(storage, ownerGhii, briefId, patch) {
301
+ const key = `${BRIEF_KEY_PREFIX}${briefId}`;
302
+ const rec = await storage.getMemory(ownerGhii, key);
303
+ if (!rec)
304
+ return null;
305
+ const brief = rec.value;
306
+ const now = new Date().toISOString();
307
+ const next = { ...brief, ...patch, updatedAt: now };
308
+ await storage.setMemory({
309
+ key, ownerGaii: ownerGhii, value: next,
310
+ visibility: 'private', tags: ['secretary', 'brief', next.status], ttlHours: null,
311
+ version: 1, createdAt: brief.createdAt, updatedAt: now,
312
+ });
313
+ return next;
314
+ }
315
+ //# sourceMappingURL=secretary-workbrief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretary-workbrief.js","sourceRoot":"","sources":["../../../src/services/secretary-workbrief.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @file secretary-worktier.ts
3
+ * @description Pure (storage-free, AI-free) helpers that encode the Secretary's LIGHT-vs-HEAVY work seam —
4
+ * the single most important rule of the redesign: the cheap node-local Secretary only does LIGHT work
5
+ * (monitor / detect gaps / remind / route / short notes / keep the Current picture fresh) and PROPOSES a
6
+ * Work Brief for anything HEAVY (build structure, change schema, author substantial content, synthesize
7
+ * strategy, multi-step research). Heavy work is executed by a Builder — a connected big AI via the appdev
8
+ * MCP tools (Claude Desktop, or a queued task a connected agent picks up) — never by inventing content on
9
+ * the cheap model. SPECIALIST work is the narrow middle: produce one short artifact FROM supplied facts.
10
+ *
11
+ * Two responsibilities, both deterministic so they unit-test directly (like secretary-tick.ts):
12
+ * - classifyWork() / classifyIntent() — map a capability id or a free-text intent to a tier.
13
+ * - assessGaps() — scan collected workspace summaries for the structural gaps that justify a Work Brief
14
+ * (empty workspace, empty space, stale workspace, off-target KPI). The "no real source → escalate"
15
+ * rule lives in the impure brief builder (it needs Discovery); the structural gap scan is here.
16
+ *
17
+ * Inputs are loose structural shapes (a WorkspaceSummary from structure-overview.ts satisfies GapInput),
18
+ * so this module imports NOTHING from the rest of the codebase and tests with plain object vectors.
19
+ * @structure WORK_TIERS · classifyWork · classifyIntent · needsHeavyEscalation · assessGaps · gapKey
20
+ * @usage import { classifyWork, assessGaps } from './secretary-worktier.js';
21
+ * @version-history
22
+ * v0.1.0 — 2026-07-01 — Initial: the light/specialist/heavy classifier + structural gap scan that turns
23
+ * the Secretary from a one-shot content inventor into a watcher that proposes Work Briefs.
24
+ */
25
+ /** The three work tiers. light = cheap, here · specialist = cheap bounded, here · heavy = dispatch to a Builder. */
26
+ export type WorkTier = 'light' | 'specialist' | 'heavy';
27
+ export declare const WORK_TIERS: readonly ["light", "specialist", "heavy"];
28
+ /**
29
+ * Classify a capability id into a work tier. Unknown capabilities default to 'light' — the tick's
30
+ * model-proposed action verbs are note/feed shaped, and genuinely structural intent is caught by
31
+ * classifyIntent() + the impure "no real source → heavy" escalation in the brief builder. The seam's bias
32
+ * (false-heavy is a mild annoyance, false-light is the failure we're eliminating) is applied where a real
33
+ * decision is made (assessGaps + escalation), not by defaulting every unknown verb to heavy.
34
+ */
35
+ export declare function classifyWork(capability: string | null | undefined): WorkTier;
36
+ /**
37
+ * Classify a free-text intent (a "Plan/Find/Note" composer line, a goal description). Heavy when it asks to
38
+ * build/structure/research/strategize; otherwise light. Conservative on purpose — only clearly-heavy verbs
39
+ * escalate, so everyday notes/reminders stay cheap.
40
+ */
41
+ export declare function classifyIntent(text: string | null | undefined): WorkTier;
42
+ /**
43
+ * The hallucination-killer predicate (the impure brief builder supplies the facts): a task escalates to a
44
+ * HEAVY Work Brief — never authored here — when it is structural, OR substantial, OR there is no real source
45
+ * to ground it (Discovery scope=own returned nothing). Only a non-structural, non-substantial task WITH a
46
+ * real source can be done cheaply. Pure: the caller computes the three booleans.
47
+ */
48
+ export declare function needsHeavyEscalation(opts: {
49
+ isStructural?: boolean;
50
+ isSubstantial?: boolean;
51
+ hasRealSource?: boolean;
52
+ }): boolean;
53
+ /** Default: a workspace whose newest content is older than this is "stale" and worth a refresh brief. */
54
+ export declare const STALE_AFTER_DAYS = 30;
55
+ /** Loose structural view of one workspace (structure-overview.ts WorkspaceSummary satisfies this). */
56
+ export interface GapInput {
57
+ ws: string;
58
+ name: string;
59
+ readable: boolean;
60
+ spaces: Array<{
61
+ name: string;
62
+ namespace: string;
63
+ mode: 'records' | 'document';
64
+ total: number;
65
+ }>;
66
+ objectives: Array<{
67
+ statement?: string;
68
+ kpis: Array<{
69
+ name: string;
70
+ current: number | null;
71
+ target?: {
72
+ op?: string;
73
+ value?: number;
74
+ values?: number[];
75
+ };
76
+ }>;
77
+ }>;
78
+ totalRecords: number;
79
+ totalDocuments: number;
80
+ lastActivity: string | null;
81
+ }
82
+ export type GapKind = 'empty-workspace' | 'empty-space' | 'stale' | 'kpi-off-target';
83
+ /** One structural gap the Secretary can surface as (or fold into) a Work Brief. */
84
+ export interface WorkspaceGap {
85
+ ws: string;
86
+ wsName: string;
87
+ kind: GapKind;
88
+ /** A short, deterministic phrasing seed (the brief builder may rephrase via a cheap call). */
89
+ detail: string;
90
+ namespace?: string;
91
+ spaceName?: string;
92
+ spaceMode?: 'records' | 'document';
93
+ kpiName?: string;
94
+ }
95
+ /**
96
+ * Scan collected workspace summaries for the structural gaps that justify proposing a Work Brief. A gap is
97
+ * heavy by nature (filling a workspace = authoring real content = a Builder's job), so each gap becomes a
98
+ * brief suggestion, NOT cheap-authored content. Deterministic (the caller passes `now` for tests):
99
+ * - empty-workspace — readable workspace with zero records AND zero documents.
100
+ * - empty-space — a memory-backed space with total === 0 (only reported when the workspace as a whole
101
+ * has SOME content, so a brand-new all-empty workspace yields one 'empty-workspace'
102
+ * gap, not one per space).
103
+ * - stale — newest content older than `freshnessDays` (workspaces with content only).
104
+ * - kpi-off-target — a measured KPI that does not meet its declared target (meetsTarget === false).
105
+ * Unreadable workspaces are skipped (nothing to brief about what you can't see).
106
+ */
107
+ export declare function assessGaps(summaries: GapInput[], opts?: {
108
+ now?: number;
109
+ freshnessDays?: number;
110
+ }): WorkspaceGap[];
111
+ /** A stable key for a gap so the tick doesn't re-propose the same brief every run. */
112
+ export declare function gapKey(g: {
113
+ ws?: string;
114
+ kind?: string;
115
+ namespace?: string;
116
+ kpiName?: string;
117
+ }): string;
118
+ //# sourceMappingURL=secretary-worktier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretary-worktier.d.ts","sourceRoot":"","sources":["../../../src/services/secretary-worktier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,oHAAoH;AACpH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,OAAO,CAAC;AACxD,eAAO,MAAM,UAAU,2CAA4C,CAAC;AAmBpE;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAK5E;AAKD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAIxE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAKhI;AAID,yGAAyG;AACzG,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,sGAAsG;AACtG,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,GAAG,UAAU,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChG,UAAU,EAAE,KAAK,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;YAAC,MAAM,CAAC,EAAE;gBAAE,EAAE,CAAC,EAAE,MAAM,CAAC;gBAAC,KAAK,CAAC,EAAE,MAAM,CAAC;gBAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;aAAE,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAC9J,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,MAAM,OAAO,GAAG,iBAAiB,GAAG,aAAa,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAErF,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,8FAA8F;IAC9F,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAoBD;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,QAAQ,EAAE,EACrB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,YAAY,EAAE,CAkChB;AAED,sFAAsF;AACtF,wBAAgB,MAAM,CAAC,CAAC,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEtG"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * @file secretary-worktier.ts
3
+ * @description Pure (storage-free, AI-free) helpers that encode the Secretary's LIGHT-vs-HEAVY work seam —
4
+ * the single most important rule of the redesign: the cheap node-local Secretary only does LIGHT work
5
+ * (monitor / detect gaps / remind / route / short notes / keep the Current picture fresh) and PROPOSES a
6
+ * Work Brief for anything HEAVY (build structure, change schema, author substantial content, synthesize
7
+ * strategy, multi-step research). Heavy work is executed by a Builder — a connected big AI via the appdev
8
+ * MCP tools (Claude Desktop, or a queued task a connected agent picks up) — never by inventing content on
9
+ * the cheap model. SPECIALIST work is the narrow middle: produce one short artifact FROM supplied facts.
10
+ *
11
+ * Two responsibilities, both deterministic so they unit-test directly (like secretary-tick.ts):
12
+ * - classifyWork() / classifyIntent() — map a capability id or a free-text intent to a tier.
13
+ * - assessGaps() — scan collected workspace summaries for the structural gaps that justify a Work Brief
14
+ * (empty workspace, empty space, stale workspace, off-target KPI). The "no real source → escalate"
15
+ * rule lives in the impure brief builder (it needs Discovery); the structural gap scan is here.
16
+ *
17
+ * Inputs are loose structural shapes (a WorkspaceSummary from structure-overview.ts satisfies GapInput),
18
+ * so this module imports NOTHING from the rest of the codebase and tests with plain object vectors.
19
+ * @structure WORK_TIERS · classifyWork · classifyIntent · needsHeavyEscalation · assessGaps · gapKey
20
+ * @usage import { classifyWork, assessGaps } from './secretary-worktier.js';
21
+ * @version-history
22
+ * v0.1.0 — 2026-07-01 — Initial: the light/specialist/heavy classifier + structural gap scan that turns
23
+ * the Secretary from a one-shot content inventor into a watcher that proposes Work Briefs.
24
+ */
25
+ export const WORK_TIERS = ['light', 'specialist', 'heavy'];
26
+ /** Capabilities the cheap Secretary may carry out itself: watch, surface, remind, route, short notes. */
27
+ const LIGHT_CAPS = new Set([
28
+ 'briefing', 'reminders', 'file_intake', 'curate_knowledge', 'discover',
29
+ 'note', 'feed', 'remind', 'route', 'monitor', 'triage', 'plan', 'find',
30
+ ]);
31
+ /** Bounded, single-shot "produce from supplied facts" work — the specialist's lane (no structure, no invention). */
32
+ const SPECIALIST_CAPS = new Set([
33
+ 'delegate', 'summarize', 'summarise', 'draft', 'extract', 'prep', 'condense', 'transform', 'specialist',
34
+ ]);
35
+ /** High-judgment / expensive work that the cheap model must NOT do one-shot — propose a Work Brief instead. */
36
+ const HEAVY_CAPS = new Set([
37
+ 'author_content', 'create_resource', 'create_workspace', 'create_organism', 'create_structure',
38
+ 'schema_change', 'manifest_change', 'research', 'strategy', 'strategy_synthesis', 'build', 'populate',
39
+ ]);
40
+ /**
41
+ * Classify a capability id into a work tier. Unknown capabilities default to 'light' — the tick's
42
+ * model-proposed action verbs are note/feed shaped, and genuinely structural intent is caught by
43
+ * classifyIntent() + the impure "no real source → heavy" escalation in the brief builder. The seam's bias
44
+ * (false-heavy is a mild annoyance, false-light is the failure we're eliminating) is applied where a real
45
+ * decision is made (assessGaps + escalation), not by defaulting every unknown verb to heavy.
46
+ */
47
+ export function classifyWork(capability) {
48
+ const c = String(capability ?? '').trim().toLowerCase();
49
+ if (HEAVY_CAPS.has(c))
50
+ return 'heavy';
51
+ if (SPECIALIST_CAPS.has(c))
52
+ return 'specialist';
53
+ return 'light';
54
+ }
55
+ /** Verbs in a free-text intent that imply building structure, sourcing real data, or synthesizing strategy. */
56
+ const HEAVY_INTENT = /\b(build|create|set ?up|design|architect|structure|schema|manifest|migrat\w*|research|investigat\w*|strateg\w*|roadmap|populate|fill (in|out)?|model out|flesh out|draft (a |the )?(full|complete|whole))\b/i;
57
+ /**
58
+ * Classify a free-text intent (a "Plan/Find/Note" composer line, a goal description). Heavy when it asks to
59
+ * build/structure/research/strategize; otherwise light. Conservative on purpose — only clearly-heavy verbs
60
+ * escalate, so everyday notes/reminders stay cheap.
61
+ */
62
+ export function classifyIntent(text) {
63
+ const t = String(text ?? '').trim();
64
+ if (!t)
65
+ return 'light';
66
+ return HEAVY_INTENT.test(t) ? 'heavy' : 'light';
67
+ }
68
+ /**
69
+ * The hallucination-killer predicate (the impure brief builder supplies the facts): a task escalates to a
70
+ * HEAVY Work Brief — never authored here — when it is structural, OR substantial, OR there is no real source
71
+ * to ground it (Discovery scope=own returned nothing). Only a non-structural, non-substantial task WITH a
72
+ * real source can be done cheaply. Pure: the caller computes the three booleans.
73
+ */
74
+ export function needsHeavyEscalation(opts) {
75
+ if (opts.isStructural)
76
+ return true;
77
+ if (opts.isSubstantial)
78
+ return true;
79
+ if (opts.hasRealSource === false)
80
+ return true; // no source → cannot do well without inventing → brief
81
+ return false;
82
+ }
83
+ // ── Structural gap scan ───────────────────────────────────────────────────────────────────────────
84
+ /** Default: a workspace whose newest content is older than this is "stale" and worth a refresh brief. */
85
+ export const STALE_AFTER_DAYS = 30;
86
+ /**
87
+ * Does `current` meet `target`? null = undecidable. MIRROR of structure-overview.ts::meetsTarget — kept
88
+ * inline so this module stays dependency-free and unit-testable with plain objects. Keep the two in sync.
89
+ */
90
+ function meetsTarget(current, t) {
91
+ if (current === null || !t || typeof t.op !== 'string')
92
+ return null;
93
+ const v = t.value;
94
+ switch (t.op) {
95
+ case '<': return typeof v === 'number' ? current < v : null;
96
+ case '<=': return typeof v === 'number' ? current <= v : null;
97
+ case '>': return typeof v === 'number' ? current > v : null;
98
+ case '>=': return typeof v === 'number' ? current >= v : null;
99
+ case '==': return typeof v === 'number' ? current === v : null;
100
+ case 'between': return Array.isArray(t.values) && t.values.length === 2 ? current >= t.values[0] && current <= t.values[1] : null;
101
+ default: return null;
102
+ }
103
+ }
104
+ /**
105
+ * Scan collected workspace summaries for the structural gaps that justify proposing a Work Brief. A gap is
106
+ * heavy by nature (filling a workspace = authoring real content = a Builder's job), so each gap becomes a
107
+ * brief suggestion, NOT cheap-authored content. Deterministic (the caller passes `now` for tests):
108
+ * - empty-workspace — readable workspace with zero records AND zero documents.
109
+ * - empty-space — a memory-backed space with total === 0 (only reported when the workspace as a whole
110
+ * has SOME content, so a brand-new all-empty workspace yields one 'empty-workspace'
111
+ * gap, not one per space).
112
+ * - stale — newest content older than `freshnessDays` (workspaces with content only).
113
+ * - kpi-off-target — a measured KPI that does not meet its declared target (meetsTarget === false).
114
+ * Unreadable workspaces are skipped (nothing to brief about what you can't see).
115
+ */
116
+ export function assessGaps(summaries, opts) {
117
+ const now = opts?.now ?? Date.now();
118
+ const freshnessMs = (opts?.freshnessDays ?? STALE_AFTER_DAYS) * 86400000;
119
+ const gaps = [];
120
+ for (const s of summaries) {
121
+ if (!s || s.readable === false)
122
+ continue;
123
+ const hasContent = (s.totalRecords + s.totalDocuments) > 0;
124
+ if (!hasContent) {
125
+ gaps.push({ ws: s.ws, wsName: s.name, kind: 'empty-workspace', detail: `Workspace "${s.name}" has no content yet.` });
126
+ }
127
+ else {
128
+ for (const sp of (s.spaces ?? [])) {
129
+ if (sp.total === 0) {
130
+ gaps.push({ ws: s.ws, wsName: s.name, kind: 'empty-space', detail: `Space "${sp.name}" is empty.`, namespace: sp.namespace, spaceName: sp.name, spaceMode: sp.mode });
131
+ }
132
+ }
133
+ // Staleness only applies to a workspace that already has content (an empty one is covered above).
134
+ if (s.lastActivity) {
135
+ const last = Date.parse(s.lastActivity);
136
+ if (!Number.isNaN(last) && (now - last) >= freshnessMs) {
137
+ const days = Math.floor((now - last) / 86400000);
138
+ gaps.push({ ws: s.ws, wsName: s.name, kind: 'stale', detail: `Workspace "${s.name}" had no activity for ${days} days.` });
139
+ }
140
+ }
141
+ }
142
+ // Off-target KPIs apply whether or not the workspace has other content.
143
+ for (const o of (s.objectives ?? [])) {
144
+ for (const k of (o.kpis ?? [])) {
145
+ if (meetsTarget(k.current, k.target) === false) {
146
+ gaps.push({ ws: s.ws, wsName: s.name, kind: 'kpi-off-target', detail: `KPI "${k.name}" is off target${o.statement ? ` for "${o.statement}"` : ''}.`, kpiName: k.name });
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return gaps;
152
+ }
153
+ /** A stable key for a gap so the tick doesn't re-propose the same brief every run. */
154
+ export function gapKey(g) {
155
+ return `${g.ws ?? ''}:${g.kind ?? ''}:${g.namespace ?? g.kpiName ?? ''}`;
156
+ }
157
+ //# sourceMappingURL=secretary-worktier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretary-worktier.js","sourceRoot":"","sources":["../../../src/services/secretary-worktier.ts"],"names":[],"mappings":"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"}