@rubytech/create-maxy-code 0.1.174 → 0.1.177

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 (66) hide show
  1. package/dist/index.js +13 -4
  2. package/package.json +1 -1
  3. package/payload/platform/neo4j/schema.cypher +49 -10
  4. package/payload/platform/plugins/docs/references/voice-mirror-guide.md +18 -16
  5. package/payload/platform/plugins/email/skills/email-composition/SKILL.md +1 -1
  6. package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
  7. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  8. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts +11 -2
  9. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts.map +1 -1
  10. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.d.ts +2 -0
  11. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.d.ts.map +1 -0
  12. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.js +95 -0
  13. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.js.map +1 -0
  14. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +1 -0
  15. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  16. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +98 -15
  17. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  18. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +3 -2
  19. package/payload/platform/plugins/substack-import/skills/substack-import/SKILL.md +1 -0
  20. package/payload/platform/scripts/setup-account.sh +8 -0
  21. package/payload/platform/scripts/verify-skill-tool-surface.sh +27 -8
  22. package/payload/premium-plugins/venture-studio/skills/investor-data-room/SKILL.md +1 -1
  23. package/payload/premium-plugins/writer-craft/PLUGIN.md +11 -7
  24. package/payload/premium-plugins/writer-craft/hooks/__tests__/voice-session-end-text.test.sh +284 -0
  25. package/payload/premium-plugins/writer-craft/hooks/voice-session-end-text.sh +75 -0
  26. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.d.ts +3 -0
  27. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.d.ts.map +1 -0
  28. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.js +58 -0
  29. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.js.map +1 -0
  30. package/payload/premium-plugins/writer-craft/mcp/dist/index.d.ts.map +1 -1
  31. package/payload/premium-plugins/writer-craft/mcp/dist/index.js +95 -18
  32. package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
  33. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts +47 -6
  34. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts.map +1 -1
  35. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js +69 -6
  36. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js.map +1 -1
  37. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts +8 -2
  38. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
  39. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js +82 -53
  40. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js.map +1 -1
  41. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts +23 -0
  42. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts.map +1 -0
  43. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js +191 -0
  44. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js.map +1 -0
  45. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.d.ts +6 -0
  46. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.d.ts.map +1 -1
  47. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.js +14 -6
  48. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.js.map +1 -1
  49. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.d.ts +12 -1
  50. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.d.ts.map +1 -1
  51. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js +23 -12
  52. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js.map +1 -1
  53. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.d.ts +3 -0
  54. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.d.ts.map +1 -1
  55. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.js +33 -5
  56. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.js.map +1 -1
  57. package/payload/premium-plugins/writer-craft/mcp/scripts/smoke.mjs +289 -28
  58. package/payload/premium-plugins/writer-craft/mcp/src/cli/ingest-session-text.ts +65 -0
  59. package/payload/premium-plugins/writer-craft/mcp/src/index.ts +108 -18
  60. package/payload/premium-plugins/writer-craft/mcp/src/lib/voice-corpus.ts +78 -6
  61. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-distil-profile.ts +115 -56
  62. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-ingest-session-text.ts +229 -0
  63. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-record-feedback.ts +20 -6
  64. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-retrieve-conditioning.ts +38 -13
  65. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-tag-content.ts +42 -5
  66. package/payload/premium-plugins/writer-craft/skills/voice-mirror/SKILL.md +65 -31
@@ -2,20 +2,30 @@
2
2
  * voice-distil-profile — walk the operator's `human-only` corpus and
3
3
  * persist a `:VoiceProfile` style card.
4
4
  *
5
+ * Task 462: one `:VoiceProfile` per `(accountId, userId, format)`.
6
+ * `format` ∈ `{text, email, social-post, article, marketing-copy, note}`.
7
+ *
8
+ * - When `format` is supplied, distils that format only.
9
+ * - When `format` is omitted, enumerates distinct format values present
10
+ * in the corpus (nodes where `n.format IS NOT NULL`) and distils each
11
+ * that fires the cadence guard. Returns `skipReason: 'no-format-tagged-content'`
12
+ * when enumeration yields zero formats.
13
+ *
5
14
  * Cadence guard: re-runs on ≥20% corpus growth since last profile, OR
6
15
  * ≥30 days since `generatedAt`. `force: true` overrides both.
7
16
  *
8
17
  * Body-text sampling caps at ~120k chars (rough proxy for tokens at
9
18
  * 4 chars/token = 30k tokens) — well inside Haiku's 200k context window
10
19
  * with headroom for the system prompt + tool schema.
20
+ *
21
+ * Task 424 — the Haiku style-card composition moved into the calling agent's
22
+ * turn. The agent reads the corpus exemplars and feedback intents (this tool
23
+ * returns them when called with `mode='sample'`), composes the style-card
24
+ * YAML, then calls this tool again with `mode='write'` + `styleCardYaml` set.
11
25
  */
12
26
  import neo4j from "neo4j-driver";
13
27
  import { getSession } from "../lib/neo4j.js";
14
- import { VOICE_CORPUS_WHERE } from "../lib/voice-corpus.js";
15
- // Task 424 — the Haiku style-card composition moved into the calling agent's
16
- // turn. The agent reads the corpus exemplars and feedback intents (this tool
17
- // returns them when called with `mode='sample'`), composes the style-card YAML,
18
- // then calls this tool again with `mode='write'` + `styleCardYaml` set.
28
+ import { VOICE_CORPUS_WHERE, voiceCorpusWhereWithFormat, FORMAT_VALUES, } from "../lib/voice-corpus.js";
19
29
  /**
20
30
  * Coerce a neo4j cypher RETURN value to a plain JS number.
21
31
  *
@@ -45,34 +55,32 @@ const RE_RUN_AGE_DAYS = 30;
45
55
  // sentenceLengthDistribution, register, favoured, avoided, taboos,
46
56
  // openingPattern, closingPattern, exemplarSentences
47
57
  // Exemplar sentences should be quoted verbatim from the returned corpus.
48
- export async function voiceDistilProfile(params) {
49
- const { accountId, userId, force = false } = params;
50
- if (!accountId || !userId) {
51
- throw new Error("voice-distil-profile: accountId and userId required");
52
- }
58
+ /**
59
+ * Single-format distil. Opens a new session for each call.
60
+ */
61
+ async function distilForFormat(params) {
62
+ const { accountId, userId, format, force = false } = params;
53
63
  const session = getSession();
54
64
  const now = new Date();
55
65
  const nowIso = now.toISOString();
56
66
  try {
57
- // 1. Read existing profile (if any) for cadence-guard comparison.
67
+ // 1. Read existing per-format profile (if any) for cadence-guard comparison.
58
68
  const existing = await session.run(`MATCH (a:AdminUser {accountId: $accountId, userId: $userId})
59
- OPTIONAL MATCH (a)-[:HAS_VOICE_PROFILE]->(p:VoiceProfile)
69
+ OPTIONAL MATCH (a)-[:HAS_VOICE_PROFILE]->(p:VoiceProfile {accountId: $accountId, userId: $userId, format: $format})
60
70
  RETURN elementId(p) AS profileId, p.corpusSize AS corpusSize,
61
- p.generatedAt AS generatedAt`, { accountId, userId });
71
+ p.generatedAt AS generatedAt`, { accountId, userId, format });
62
72
  const existingRow = existing.records[0];
63
73
  const prevProfileId = existingRow?.get("profileId") ?? null;
64
74
  const prevCorpusSize = toJsNumber(existingRow?.get("corpusSize"));
65
75
  const prevGeneratedAt = existingRow?.get("generatedAt") ?? null;
66
- // 2. Count corpus. Filter matches human-only + human-led-agent-assisted
67
- // across the four primary content labels plus conversation-document
68
- // :Section chunks (chat archives — children of a :KnowledgeDocument
69
- // with `conversationIdentity` set). See VOICE_CORPUS_WHERE above.
76
+ // 2. Count corpus for this specific format.
77
+ const corpusWhere = voiceCorpusWhereWithFormat(format);
70
78
  const countResult = await session.run(`MATCH (n)
71
- WHERE ${VOICE_CORPUS_WHERE}
72
- RETURN count(n) AS c`, { accountId });
79
+ WHERE ${corpusWhere}
80
+ RETURN count(n) AS c`, { accountId, format });
73
81
  const corpusSize = toJsNumber(countResult.records[0]?.get("c")) ?? 0;
74
82
  if (corpusSize === 0) {
75
- process.stderr.write(`[voice-distil] adminUser=${userId} skip reason=empty-corpus\n`);
83
+ process.stderr.write(`[voice-distil] adminUser=${userId} format=${format} skip reason=empty-corpus\n`);
76
84
  return {
77
85
  profileId: prevProfileId,
78
86
  corpusSize: 0,
@@ -86,9 +94,6 @@ export async function voiceDistilProfile(params) {
86
94
  if (!force && prevProfileId && prevCorpusSize !== null && prevGeneratedAt) {
87
95
  const ageMs = now.getTime() - new Date(prevGeneratedAt).getTime();
88
96
  const ageDays = ageMs / (24 * 60 * 60 * 1000);
89
- // prevCorpusSize is non-null here (the guard above checks). When it's
90
- // zero we treat growth as infinite — first real corpus always triggers
91
- // a re-run.
92
97
  const growth = prevCorpusSize > 0
93
98
  ? (corpusSize - prevCorpusSize) / prevCorpusSize
94
99
  : 1;
@@ -96,7 +101,7 @@ export async function voiceDistilProfile(params) {
96
101
  const growthTrigger = growth >= RE_RUN_GROWTH_FRACTION;
97
102
  if (!ageTrigger && !growthTrigger) {
98
103
  const reason = ageDays < 1 ? "recent" : "below-threshold";
99
- process.stderr.write(`[voice-distil] adminUser=${userId} skip reason=${reason} corpusSize=${corpusSize} prevCorpus=${prevCorpusSize} ageDays=${ageDays.toFixed(1)}\n`);
104
+ process.stderr.write(`[voice-distil] adminUser=${userId} format=${format} skip reason=${reason} corpusSize=${corpusSize} prevCorpus=${prevCorpusSize} ageDays=${ageDays.toFixed(1)}\n`);
100
105
  return {
101
106
  profileId: prevProfileId,
102
107
  corpusSize,
@@ -108,11 +113,8 @@ export async function voiceDistilProfile(params) {
108
113
  }
109
114
  }
110
115
  // 4. Sample corpus bodies up to the char cap. Pick recent first.
111
- // Timestamp coalesces include `firstMessageAt` for conversation-document
112
- // :Section chunks so chat archives sort by when the conversation
113
- // actually happened.
114
116
  const sampled = await session.run(`MATCH (n)
115
- WHERE ${VOICE_CORPUS_WHERE}
117
+ WHERE ${corpusWhere}
116
118
  WITH n, coalesce(n.dateSent, n.datePublished, n.firstMessageAt, n.dateCreated, n.createdAt) AS ts
117
119
  OPTIONAL MATCH (parent:KnowledgeDocument)-[:HAS_SECTION]->(n)
118
120
  WHERE 'Section' IN labels(n) AND parent.conversationIdentity IS NOT NULL
@@ -122,16 +124,12 @@ export async function voiceDistilProfile(params) {
122
124
  parent.conversationIdentity IS NOT NULL AS isConversationChunk,
123
125
  ts
124
126
  ORDER BY ts IS NULL, ts DESC
125
- LIMIT 500`, { accountId });
127
+ LIMIT 500`, { accountId, format });
126
128
  const samples = [];
127
129
  let charBudget = SAMPLE_CHAR_CAP;
128
130
  for (const r of sampled.records) {
129
131
  const body = r.get("body") ?? "";
130
132
  const labels = r.get("labels") ?? [];
131
- // Conversation-document sections carry `:Section` only after the Task
132
- // 324 collapse; surface "Conversation" via the parent's
133
- // `conversationIdentity` so the LLM exemplar header still says "this
134
- // is chat" rather than the bare base label.
135
133
  const isConversationChunk = Boolean(r.get("isConversationChunk"));
136
134
  const label = isConversationChunk
137
135
  ? "Conversation"
@@ -144,21 +142,16 @@ export async function voiceDistilProfile(params) {
144
142
  if (charBudget <= 0)
145
143
  break;
146
144
  }
147
- // 5. Pull feedback intents from existing :VoiceEdit nodes for this operator.
148
- const feedback = await session.run(`MATCH (a:AdminUser {accountId: $accountId, userId: $userId})
149
- MATCH (e:VoiceEdit {userId: $userId, accountId: $accountId})
150
- RETURN e.intent AS intent ORDER BY e.occurredAt DESC LIMIT 50`, { accountId, userId });
145
+ // 5. Pull feedback intents from existing :VoiceEdit nodes for this format.
146
+ const feedback = await session.run(`MATCH (e:VoiceEdit {userId: $userId, accountId: $accountId, format: $format})
147
+ RETURN e.intent AS intent ORDER BY e.occurredAt DESC LIMIT 50`, { accountId, userId, format });
151
148
  const feedbackIntents = feedback.records
152
149
  .map((r) => r.get("intent"))
153
150
  .filter((x) => typeof x === "string" && x.length > 0);
154
151
  // 6. Mode branch (Task 424).
155
- // - `sample` (default): return the exemplars + feedback intents to the
156
- // calling agent. The agent composes the YAML style card in its own
157
- // turn and re-invokes with mode='write'.
158
- // - `write`: persist the agent-produced style card.
159
152
  const mode = params.mode ?? "sample";
160
153
  if (mode === "sample") {
161
- process.stderr.write(`[voice-distil] adminUser=${userId} mode=sample corpusSize=${corpusSize} ` +
154
+ process.stderr.write(`[voice-distil] adminUser=${userId} format=${format} mode=sample corpusSize=${corpusSize} ` +
162
155
  `exemplars=${samples.length} feedbackEntries=${feedbackIntents.length}\n`);
163
156
  return {
164
157
  profileId: prevProfileId,
@@ -175,15 +168,10 @@ export async function voiceDistilProfile(params) {
175
168
  if (!styleCardYaml) {
176
169
  throw new Error("voice-distil-profile: mode='write' requires styleCardYaml (the YAML you composed from the sample-mode response).");
177
170
  }
178
- // 7. Write the :VoiceProfile node + LEARNED_FROM edges to every sampled node.
179
- //
180
- // The :AdminUser must already exist (onboarding/auth is the only
181
- // legitimate origin for :AdminUser). MATCH not MERGE: a typo in
182
- // userId, an env mismatch, or a dropped credential surfaces
183
- // here as a typed error rather than silently minting an orphan
184
- // AdminUser that bypasses the platform's label-origin protection.
171
+ // 7. Write the :VoiceProfile node keyed on (accountId, userId, format)
172
+ // plus LEARNED_FROM edges to every sampled node.
185
173
  const writeResult = await session.run(`MATCH (a:AdminUser {accountId: $accountId, userId: $userId})
186
- MERGE (a)-[:HAS_VOICE_PROFILE]->(p:VoiceProfile {accountId: $accountId, userId: $userId})
174
+ MERGE (a)-[:HAS_VOICE_PROFILE]->(p:VoiceProfile {accountId: $accountId, userId: $userId, format: $format})
187
175
  ON CREATE SET p.createdAt = $now
188
176
  SET p.styleCard = $styleCard,
189
177
  p.generatedAt = $now,
@@ -197,19 +185,18 @@ export async function voiceDistilProfile(params) {
197
185
  RETURN elementId(p) AS profileId`, {
198
186
  accountId,
199
187
  userId,
188
+ format,
200
189
  styleCard: styleCardYaml,
201
190
  now: nowIso,
202
191
  corpusSize,
203
192
  feedbackEntries: feedbackIntents.length,
204
193
  sampleIds: samples.map((s) => s.id),
205
194
  });
206
- // MATCH-on-:AdminUser failure yields zero records. Throw the typed
207
- // error here rather than returning a half-baked result.
208
195
  if (writeResult.records.length === 0) {
209
196
  throw new Error(`voice-mirror: :AdminUser {accountId='${accountId}', userId='${userId}'} not found. Onboarding must promote the operator to :AdminUser before distillation.`);
210
197
  }
211
198
  const profileId = writeResult.records[0].get("profileId");
212
- process.stderr.write(`[voice-distil] adminUser=${userId} mode=write corpusSize=${corpusSize} generatedAt=${nowIso} feedbackEntries=${feedbackIntents.length}\n`);
199
+ process.stderr.write(`[voice-distil] adminUser=${userId} format=${format} mode=write corpusSize=${corpusSize} generatedAt=${nowIso} feedbackEntries=${feedbackIntents.length}\n`);
213
200
  return {
214
201
  profileId,
215
202
  corpusSize,
@@ -222,4 +209,46 @@ export async function voiceDistilProfile(params) {
222
209
  await session.close();
223
210
  }
224
211
  }
212
+ export async function voiceDistilProfile(params) {
213
+ const { accountId, userId, force = false } = params;
214
+ if (!accountId || !userId) {
215
+ throw new Error("voice-distil-profile: accountId and userId required");
216
+ }
217
+ // Single-format path.
218
+ if (params.format !== undefined) {
219
+ return distilForFormat({ ...params, format: params.format, force });
220
+ }
221
+ // Multi-format path: enumerate distinct format values present in the corpus.
222
+ const session = getSession();
223
+ let formats = [];
224
+ try {
225
+ const enumResult = await session.run(`MATCH (n)
226
+ WHERE ${VOICE_CORPUS_WHERE} AND n.format IS NOT NULL
227
+ RETURN DISTINCT n.format AS fmt`, { accountId });
228
+ formats = enumResult.records
229
+ .map((r) => r.get("fmt"))
230
+ .filter((f) => FORMAT_VALUES.includes(f));
231
+ }
232
+ finally {
233
+ await session.close();
234
+ }
235
+ if (formats.length === 0) {
236
+ process.stderr.write(`[voice-distil] adminUser=${userId} skip reason=no-format-tagged-content\n`);
237
+ return {
238
+ profileId: null,
239
+ corpusSize: 0,
240
+ generatedAt: null,
241
+ feedbackEntries: 0,
242
+ skipped: true,
243
+ skipReason: "no-format-tagged-content",
244
+ };
245
+ }
246
+ // Distil each discovered format sequentially.
247
+ const results = [];
248
+ for (const format of formats) {
249
+ const result = await distilForFormat({ ...params, format, force });
250
+ results.push(result);
251
+ }
252
+ return results;
253
+ }
225
254
  //# sourceMappingURL=voice-distil-profile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"voice-distil-profile.js","sourceRoot":"","sources":["../../src/tools/voice-distil-profile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"voice-distil-profile.js","sourceRoot":"","sources":["../../src/tools/voice-distil-profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface VoiceIngestSessionTextParams {
2
+ sessionJsonlPath: string;
3
+ accountId: string;
4
+ userId: string;
5
+ sessionId?: string;
6
+ }
7
+ export interface VoiceIngestSessionTextResult {
8
+ ingestedCount: number;
9
+ skippedCount: number;
10
+ sessionId: string | null;
11
+ }
12
+ /**
13
+ * Extracts text content from a "real operator" user record.
14
+ * Returns null when the record should be skipped.
15
+ */
16
+ export declare function extractOperatorText(record: unknown): string | null;
17
+ /**
18
+ * Parse a session JSONL file and return all real operator turn texts.
19
+ * Exported for testability (no DB required).
20
+ */
21
+ export declare function extractOperatorTurns(jsonlPath: string): Promise<string[]>;
22
+ export declare function voiceIngestSessionText(params: VoiceIngestSessionTextParams): Promise<VoiceIngestSessionTextResult>;
23
+ //# sourceMappingURL=voice-ingest-session-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-ingest-session-text.d.ts","sourceRoot":"","sources":["../../src/tools/voice-ingest-session-text.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CA8ClE;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAwB/E;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,4BAA4B,CAAC,CAsGvC"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * voice-ingest-session-text — extract operator turns from a Claude Code
3
+ * session JSONL and write them as :Message {format:'text', source:'admin-pty'}
4
+ * corpus nodes.
5
+ *
6
+ * Called by the SessionEnd hook (via the CLI wrapper) after each admin PTY
7
+ * session. Re-running against the same JSONL is a no-op — MERGE on
8
+ * (contentHash, accountId) is the deduplication primitive.
9
+ *
10
+ * After ingest, triggers voice-distil-profile {format:'text'} so the cadence
11
+ * guard decides whether distillation runs.
12
+ *
13
+ * JSONL record shape expected (Claude Code session format):
14
+ * { "type": "user" | "assistant", "message": { "role": "...", "content": ... }, ... }
15
+ *
16
+ * "Real operator text" extraction rules (excludes):
17
+ * - type != "user" or message.role != "user" → not the operator
18
+ * - content is tool_result-only → tool reply, not turn
19
+ * - text starts with "/" → slash command
20
+ * - text contains "<system-reminder>" → harness injection
21
+ * - text.length >= 4096 → likely pasted content
22
+ * - text is empty after trimming → nothing to ingest
23
+ */
24
+ import { createHash } from "node:crypto";
25
+ import { createReadStream } from "node:fs";
26
+ import { createInterface } from "node:readline";
27
+ import { getSession } from "../lib/neo4j.js";
28
+ import { voiceDistilProfile } from "./voice-distil-profile.js";
29
+ /**
30
+ * Extracts text content from a "real operator" user record.
31
+ * Returns null when the record should be skipped.
32
+ */
33
+ export function extractOperatorText(record) {
34
+ if (!record || typeof record !== "object")
35
+ return null;
36
+ const rec = record;
37
+ if (rec["type"] !== "user")
38
+ return null;
39
+ const msg = rec["message"];
40
+ if (!msg || typeof msg !== "object")
41
+ return null;
42
+ const message = msg;
43
+ if (message["role"] !== "user")
44
+ return null;
45
+ const content = message["content"];
46
+ let text = "";
47
+ if (typeof content === "string") {
48
+ text = content;
49
+ }
50
+ else if (Array.isArray(content)) {
51
+ // Must have at least one non-tool_result block to be a real turn.
52
+ const nonToolResult = content.filter((b) => typeof b === "object" && b !== null && b["type"] !== "tool_result");
53
+ if (nonToolResult.length === 0)
54
+ return null;
55
+ // Collect text from all text-type content blocks.
56
+ const parts = [];
57
+ for (const block of content) {
58
+ if (typeof block !== "object" || block === null)
59
+ continue;
60
+ const b = block;
61
+ if (b["type"] === "text" && typeof b["text"] === "string") {
62
+ parts.push(b["text"]);
63
+ }
64
+ }
65
+ text = parts.join("");
66
+ }
67
+ else {
68
+ return null;
69
+ }
70
+ text = text.trim();
71
+ if (text.length === 0)
72
+ return null;
73
+ // Exclusions.
74
+ if (text.startsWith("/"))
75
+ return null; // slash command
76
+ if (text.includes("<system-reminder>"))
77
+ return null; // harness injection
78
+ if (text.length >= 4096)
79
+ return null; // paste block
80
+ return text;
81
+ }
82
+ /**
83
+ * Parse a session JSONL file and return all real operator turn texts.
84
+ * Exported for testability (no DB required).
85
+ */
86
+ export async function extractOperatorTurns(jsonlPath) {
87
+ const turns = [];
88
+ const rl = createInterface({
89
+ input: createReadStream(jsonlPath, { encoding: "utf-8" }),
90
+ crlfDelay: Infinity,
91
+ });
92
+ for await (const line of rl) {
93
+ const trimmed = line.trim();
94
+ if (!trimmed)
95
+ continue;
96
+ let record;
97
+ try {
98
+ record = JSON.parse(trimmed);
99
+ }
100
+ catch {
101
+ continue;
102
+ }
103
+ const text = extractOperatorText(record);
104
+ if (text !== null) {
105
+ turns.push(text);
106
+ }
107
+ }
108
+ return turns;
109
+ }
110
+ export async function voiceIngestSessionText(params) {
111
+ const { sessionJsonlPath, accountId, userId, sessionId = null } = params;
112
+ if (!accountId || !userId) {
113
+ throw new Error("voice-ingest-session-text: accountId and userId required");
114
+ }
115
+ if (!sessionJsonlPath) {
116
+ throw new Error("voice-ingest-session-text: sessionJsonlPath required");
117
+ }
118
+ // 1. Extract operator turns from the JSONL.
119
+ let allTurns;
120
+ try {
121
+ allTurns = await extractOperatorTurns(sessionJsonlPath);
122
+ }
123
+ catch (err) {
124
+ throw new Error(`voice-ingest-session-text: failed to read JSONL at '${sessionJsonlPath}': ${err instanceof Error ? err.message : String(err)}`);
125
+ }
126
+ if (allTurns.length === 0) {
127
+ process.stderr.write(`[voice-ingest-session-text] sessionId=${sessionId ?? "unknown"} adminUser=${userId} turns=0 bytes=0\n`);
128
+ return { ingestedCount: 0, skippedCount: 0, sessionId };
129
+ }
130
+ // 2. Write each turn as a :Message node. MERGE on contentHash+accountId dedupes.
131
+ const session = getSession();
132
+ const now = new Date().toISOString();
133
+ let ingestedCount = 0;
134
+ let skippedCount = 0;
135
+ let totalBytes = 0;
136
+ try {
137
+ for (const body of allTurns) {
138
+ const contentHash = createHash("sha256")
139
+ .update(body, "utf-8")
140
+ .digest("hex");
141
+ const result = await session.run(`MATCH (a:AdminUser {accountId: $accountId, userId: $userId})
142
+ MERGE (n:Message {contentHash: $contentHash, accountId: $accountId})
143
+ ON CREATE SET
144
+ n.userId = $userId,
145
+ n.body = $body,
146
+ n.occurredAt = $now,
147
+ n.sessionId = $sessionId,
148
+ n.source = 'admin-pty',
149
+ n.authorshipMode = 'human-only',
150
+ n.format = 'text',
151
+ n.createdAt = $now
152
+ MERGE (a)-[:AUTHORED]->(n)
153
+ RETURN n.createdAt = $now AS isNew`, {
154
+ accountId,
155
+ userId,
156
+ contentHash,
157
+ body,
158
+ now,
159
+ sessionId,
160
+ });
161
+ if (result.records.length === 0) {
162
+ // :AdminUser not found — abort rather than orphan nodes.
163
+ throw new Error(`voice-ingest-session-text: :AdminUser {accountId='${accountId}', userId='${userId}'} not found. Onboarding must promote the operator to :AdminUser before ingest.`);
164
+ }
165
+ const isNew = result.records[0].get("isNew") === true;
166
+ if (isNew) {
167
+ ingestedCount++;
168
+ totalBytes += body.length;
169
+ }
170
+ else {
171
+ skippedCount++;
172
+ }
173
+ }
174
+ }
175
+ finally {
176
+ await session.close();
177
+ }
178
+ process.stderr.write(`[voice-ingest-session-text] sessionId=${sessionId ?? "unknown"} adminUser=${userId} turns=${ingestedCount} bytes=${totalBytes} skipped=${skippedCount}\n`);
179
+ // 3. Trigger text-format distillation (cadence guard decides whether to run).
180
+ if (ingestedCount > 0) {
181
+ try {
182
+ await voiceDistilProfile({ accountId, userId, format: "text" });
183
+ }
184
+ catch (err) {
185
+ // Distil failure must not fail the ingest.
186
+ process.stderr.write(`[voice-ingest-session-text] distil-after-ingest error: ${err instanceof Error ? err.message : String(err)}\n`);
187
+ }
188
+ }
189
+ return { ingestedCount, skippedCount, sessionId };
190
+ }
191
+ //# sourceMappingURL=voice-ingest-session-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-ingest-session-text.js","sourceRoot":"","sources":["../../src/tools/voice-ingest-session-text.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,14 @@
1
+ import type { VoiceFormat } from "../lib/voice-corpus.js";
1
2
  export interface VoiceRecordFeedbackParams {
2
3
  accountId: string;
3
4
  userId: string;
4
5
  originalText: string;
5
6
  editedText: string;
7
+ /**
8
+ * Writing format of the draft being edited. Routes feedback to the
9
+ * matching per-format :VoiceProfile.
10
+ */
11
+ format: VoiceFormat;
6
12
  /**
7
13
  * One sentence describing what changed and what voice preference it reveals.
8
14
  * The calling agent summarises this from `originalText` vs `editedText` in
@@ -1 +1 @@
1
- {"version":3,"file":"voice-record-feedback.d.ts","sourceRoot":"","sources":["../../src/tools/voice-record-feedback.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,yBAAyB,CAAC,CAoEpC"}
1
+ {"version":3,"file":"voice-record-feedback.d.ts","sourceRoot":"","sources":["../../src/tools/voice-record-feedback.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,yBAAyB,CAAC,CAyEpC"}
@@ -7,21 +7,27 @@
7
7
  * and passes the resulting `intent` string as a required parameter. The
8
8
  * tool now does the graph writes only.
9
9
  *
10
+ * Task 462: `format` is required. `:VoiceEdit` carries the format; the
11
+ * `FEEDBACK_FOR` edge targets the per-format `:VoiceProfile`.
12
+ *
10
13
  * Side effects:
11
- * 1. Write `(:VoiceEdit)-[:FEEDBACK_FOR]->(:VoiceProfile)` if the profile
12
- * exists; otherwise write the :VoiceEdit alone so the next distillation
13
- * back-fills the edge.
14
+ * 1. Write `(:VoiceEdit)-[:FEEDBACK_FOR]->(:VoiceProfile {format})` if the
15
+ * per-format profile exists; otherwise write the :VoiceEdit alone so the
16
+ * next distillation back-fills the edge.
14
17
  */
15
18
  import { randomUUID } from "node:crypto";
16
19
  import { getSession } from "../lib/neo4j.js";
17
20
  export async function voiceRecordFeedback(params) {
18
- const { accountId, userId, originalText, editedText, intent: rawIntent, context } = params;
21
+ const { accountId, userId, originalText, editedText, format, intent: rawIntent, context } = params;
19
22
  if (!accountId || !userId) {
20
23
  throw new Error("voice-record-feedback: accountId and userId required");
21
24
  }
22
25
  if (!originalText || !editedText) {
23
26
  throw new Error("voice-record-feedback: originalText and editedText required");
24
27
  }
28
+ if (!format) {
29
+ throw new Error("voice-record-feedback: format is required");
30
+ }
25
31
  const intent = (rawIntent ?? "").trim();
26
32
  if (!intent) {
27
33
  throw new Error("voice-record-feedback: intent is required — summarise what the operator changed in-turn before calling this tool (Task 424).");
@@ -36,6 +42,7 @@ export async function voiceRecordFeedback(params) {
36
42
  editId: $editId,
37
43
  accountId: $accountId,
38
44
  userId: $userId,
45
+ format: $format,
39
46
  originalText: $originalText,
40
47
  editedText: $editedText,
41
48
  intent: $intent,
@@ -45,13 +52,14 @@ export async function voiceRecordFeedback(params) {
45
52
  })
46
53
  CREATE (a)-[:AUTHORED]->(e)
47
54
  WITH e
48
- OPTIONAL MATCH (:AdminUser {accountId: $accountId, userId: $userId})-[:HAS_VOICE_PROFILE]->(p:VoiceProfile)
55
+ OPTIONAL MATCH (:AdminUser {accountId: $accountId, userId: $userId})-[:HAS_VOICE_PROFILE]->(p:VoiceProfile {accountId: $accountId, userId: $userId, format: $format})
49
56
  FOREACH (_ IN CASE WHEN p IS NULL THEN [] ELSE [1] END |
50
57
  MERGE (e)-[:FEEDBACK_FOR]->(p)
51
58
  )
52
59
  RETURN elementId(e) AS editId, (p IS NOT NULL) AS hadProfile`, {
53
60
  accountId,
54
61
  userId,
62
+ format,
55
63
  editId,
56
64
  originalText,
57
65
  editedText,
@@ -64,7 +72,7 @@ export async function voiceRecordFeedback(params) {
64
72
  throw new Error(`voice-mirror: :AdminUser {accountId='${accountId}', userId='${userId}'} not found. Onboarding must promote the operator to :AdminUser before feedback can be recorded.`);
65
73
  }
66
74
  const hadProfile = result.records[0].get("hadProfile") === true;
67
- process.stderr.write(`[voice-record-feedback] adminUser=${userId} intent="${cappedIntent.replace(/"/g, "'")}" diffBytes=${editedText.length - originalText.length}\n`);
75
+ process.stderr.write(`[voice-record-feedback] adminUser=${userId} format=${format} intent="${cappedIntent.replace(/"/g, "'")}" diffBytes=${editedText.length - originalText.length}\n`);
68
76
  return { editId, intent: cappedIntent, occurredAt, hadProfile };
69
77
  }
70
78
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"voice-record-feedback.js","sourceRoot":"","sources":["../../src/tools/voice-record-feedback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA4B7C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAiC;IAEjC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAC3F,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,8HAA8H,CAC/H,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;;;;;;;;;;;;;;;oEAkB8D,EAC9D;YACE,SAAS;YACT,MAAM;YACN,MAAM;YACN,YAAY;YACZ,UAAU;YACV,MAAM,EAAE,YAAY;YACpB,UAAU;YACV,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;YAC7B,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;SAC9B,CACF,CAAC;QACF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,wCAAwC,SAAS,cAAc,MAAM,mGAAmG,CACzK,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;QAEhE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qCAAqC,MAAM,YAAY,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,eAAe,UAAU,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,IAAI,CACjJ,CAAC;QAEF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;IAClE,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"voice-record-feedback.js","sourceRoot":"","sources":["../../src/tools/voice-record-feedback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAkC7C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAiC;IAEjC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACnG,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,8HAA8H,CAC/H,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;;;;;;;;;;;;;;;;oEAmB8D,EAC9D;YACE,SAAS;YACT,MAAM;YACN,MAAM;YACN,MAAM;YACN,YAAY;YACZ,UAAU;YACV,MAAM,EAAE,YAAY;YACpB,UAAU;YACV,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;YAC7B,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;SAC9B,CACF,CAAC;QACF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,wCAAwC,SAAS,cAAc,MAAM,mGAAmG,CACzK,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;QAEhE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qCAAqC,MAAM,WAAW,MAAM,YAAY,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,eAAe,UAAU,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,IAAI,CAClK,CAAC;QAEF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;IAClE,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -1,9 +1,20 @@
1
+ import { type VoiceFormat } from "../lib/voice-corpus.js";
1
2
  export interface VoiceRetrieveConditioningParams {
2
3
  accountId: string;
3
4
  userId: string;
4
5
  brief: {
5
6
  topic?: string;
6
- format: "short" | "long";
7
+ /**
8
+ * Writing format for corpus and profile scoping (required, Task 462).
9
+ * One :VoiceProfile per (accountId, userId, format).
10
+ */
11
+ format: VoiceFormat;
12
+ /**
13
+ * K-selector: 'short' = K=5 (16k token budget, email/post);
14
+ * 'long' = K=15 (96k token budget, brochure/prospectus).
15
+ * Renamed from `format` in Task 462 to free the name for VoiceFormat.
16
+ */
17
+ length?: "short" | "long";
7
18
  register?: string;
8
19
  };
9
20
  tokenBudget?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"voice-retrieve-conditioning.d.ts","sourceRoot":"","sources":["../../src/tools/voice-retrieve-conditioning.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,+BAA+B;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,+BAA+B;IAC9C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAID,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,+BAA+B,CAAC,CA2F1C"}
1
+ {"version":3,"file":"voice-retrieve-conditioning.d.ts","sourceRoot":"","sources":["../../src/tools/voice-retrieve-conditioning.ts"],"names":[],"mappings":"AA2BA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AAMhC,MAAM,WAAW,+BAA+B;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC;QACf;;;WAGG;QACH,MAAM,EAAE,WAAW,CAAC;QACpB;;;;WAIG;QACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,+BAA+B;IAC9C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAID,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,+BAA+B,CAAC,CA+F1C"}