openplanr 1.2.6 → 1.2.8

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 (149) hide show
  1. package/README.md +54 -1
  2. package/dist/ai/prompts/prompt-builder.d.ts +48 -0
  3. package/dist/ai/prompts/prompt-builder.d.ts.map +1 -1
  4. package/dist/ai/prompts/prompt-builder.js +57 -1
  5. package/dist/ai/prompts/prompt-builder.js.map +1 -1
  6. package/dist/ai/prompts/system-prompts.d.ts +23 -0
  7. package/dist/ai/prompts/system-prompts.d.ts.map +1 -1
  8. package/dist/ai/prompts/system-prompts.js +98 -0
  9. package/dist/ai/prompts/system-prompts.js.map +1 -1
  10. package/dist/ai/schemas/ai-response-schemas.d.ts +68 -0
  11. package/dist/ai/schemas/ai-response-schemas.d.ts.map +1 -1
  12. package/dist/ai/schemas/ai-response-schemas.js +81 -0
  13. package/dist/ai/schemas/ai-response-schemas.js.map +1 -1
  14. package/dist/ai/types.d.ts +2 -0
  15. package/dist/ai/types.d.ts.map +1 -1
  16. package/dist/ai/types.js +2 -0
  17. package/dist/ai/types.js.map +1 -1
  18. package/dist/cli/commands/context.d.ts +6 -0
  19. package/dist/cli/commands/context.d.ts.map +1 -0
  20. package/dist/cli/commands/context.js +45 -0
  21. package/dist/cli/commands/context.js.map +1 -0
  22. package/dist/cli/commands/export.d.ts.map +1 -1
  23. package/dist/cli/commands/export.js +8 -0
  24. package/dist/cli/commands/export.js.map +1 -1
  25. package/dist/cli/commands/report-linter.d.ts +6 -0
  26. package/dist/cli/commands/report-linter.d.ts.map +1 -0
  27. package/dist/cli/commands/report-linter.js +61 -0
  28. package/dist/cli/commands/report-linter.js.map +1 -0
  29. package/dist/cli/commands/report.d.ts +6 -0
  30. package/dist/cli/commands/report.d.ts.map +1 -0
  31. package/dist/cli/commands/report.js +150 -0
  32. package/dist/cli/commands/report.js.map +1 -0
  33. package/dist/cli/commands/revise.d.ts +23 -0
  34. package/dist/cli/commands/revise.d.ts.map +1 -0
  35. package/dist/cli/commands/revise.js +502 -0
  36. package/dist/cli/commands/revise.js.map +1 -0
  37. package/dist/cli/commands/story.d.ts.map +1 -1
  38. package/dist/cli/commands/story.js +31 -0
  39. package/dist/cli/commands/story.js.map +1 -1
  40. package/dist/cli/commands/voice.d.ts +6 -0
  41. package/dist/cli/commands/voice.d.ts.map +1 -0
  42. package/dist/cli/commands/voice.js +64 -0
  43. package/dist/cli/commands/voice.js.map +1 -0
  44. package/dist/cli/index.js +10 -0
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/models/schema.d.ts +63 -0
  47. package/dist/models/schema.d.ts.map +1 -1
  48. package/dist/models/schema.js +31 -0
  49. package/dist/models/schema.js.map +1 -1
  50. package/dist/models/types.d.ts +280 -0
  51. package/dist/models/types.d.ts.map +1 -1
  52. package/dist/services/atomic-write-service.d.ts +41 -0
  53. package/dist/services/atomic-write-service.d.ts.map +1 -0
  54. package/dist/services/atomic-write-service.js +87 -0
  55. package/dist/services/atomic-write-service.js.map +1 -0
  56. package/dist/services/audit-log-service.d.ts +50 -0
  57. package/dist/services/audit-log-service.d.ts.map +1 -0
  58. package/dist/services/audit-log-service.js +213 -0
  59. package/dist/services/audit-log-service.js.map +1 -0
  60. package/dist/services/cascade-service.d.ts +62 -0
  61. package/dist/services/cascade-service.d.ts.map +1 -0
  62. package/dist/services/cascade-service.js +189 -0
  63. package/dist/services/cascade-service.js.map +1 -0
  64. package/dist/services/context-pack-service.d.ts +12 -0
  65. package/dist/services/context-pack-service.d.ts.map +1 -0
  66. package/dist/services/context-pack-service.js +155 -0
  67. package/dist/services/context-pack-service.js.map +1 -0
  68. package/dist/services/diff-service.d.ts +18 -0
  69. package/dist/services/diff-service.d.ts.map +1 -0
  70. package/dist/services/diff-service.js +35 -0
  71. package/dist/services/diff-service.js.map +1 -0
  72. package/dist/services/distribution-service.d.ts +18 -0
  73. package/dist/services/distribution-service.d.ts.map +1 -0
  74. package/dist/services/distribution-service.js +104 -0
  75. package/dist/services/distribution-service.js.map +1 -0
  76. package/dist/services/evidence-service.d.ts +17 -0
  77. package/dist/services/evidence-service.d.ts.map +1 -0
  78. package/dist/services/evidence-service.js +85 -0
  79. package/dist/services/evidence-service.js.map +1 -0
  80. package/dist/services/evidence-verifier.d.ts +71 -0
  81. package/dist/services/evidence-verifier.d.ts.map +1 -0
  82. package/dist/services/evidence-verifier.js +171 -0
  83. package/dist/services/evidence-verifier.js.map +1 -0
  84. package/dist/services/git-service.d.ts +60 -0
  85. package/dist/services/git-service.d.ts.map +1 -0
  86. package/dist/services/git-service.js +137 -0
  87. package/dist/services/git-service.js.map +1 -0
  88. package/dist/services/github-service.d.ts +28 -1
  89. package/dist/services/github-service.d.ts.map +1 -1
  90. package/dist/services/github-service.js +95 -0
  91. package/dist/services/github-service.js.map +1 -1
  92. package/dist/services/graph-integrity.d.ts +36 -0
  93. package/dist/services/graph-integrity.d.ts.map +1 -0
  94. package/dist/services/graph-integrity.js +54 -0
  95. package/dist/services/graph-integrity.js.map +1 -0
  96. package/dist/services/prompt-service.d.ts +18 -0
  97. package/dist/services/prompt-service.d.ts.map +1 -1
  98. package/dist/services/prompt-service.js +47 -0
  99. package/dist/services/prompt-service.js.map +1 -1
  100. package/dist/services/report-linter-service.d.ts +10 -0
  101. package/dist/services/report-linter-service.d.ts.map +1 -0
  102. package/dist/services/report-linter-service.js +95 -0
  103. package/dist/services/report-linter-service.js.map +1 -0
  104. package/dist/services/report-service.d.ts +37 -0
  105. package/dist/services/report-service.d.ts.map +1 -0
  106. package/dist/services/report-service.js +173 -0
  107. package/dist/services/report-service.js.map +1 -0
  108. package/dist/services/revise-cache-service.d.ts +46 -0
  109. package/dist/services/revise-cache-service.d.ts.map +1 -0
  110. package/dist/services/revise-cache-service.js +88 -0
  111. package/dist/services/revise-cache-service.js.map +1 -0
  112. package/dist/services/revise-service.d.ts +108 -0
  113. package/dist/services/revise-service.d.ts.map +1 -0
  114. package/dist/services/revise-service.js +249 -0
  115. package/dist/services/revise-service.js.map +1 -0
  116. package/dist/services/standup-parser.d.ts +21 -0
  117. package/dist/services/standup-parser.d.ts.map +1 -0
  118. package/dist/services/standup-parser.js +104 -0
  119. package/dist/services/standup-parser.js.map +1 -0
  120. package/dist/services/story-standup-service.d.ts +7 -0
  121. package/dist/services/story-standup-service.d.ts.map +1 -0
  122. package/dist/services/story-standup-service.js +27 -0
  123. package/dist/services/story-standup-service.js.map +1 -0
  124. package/dist/services/template-sections.d.ts +28 -0
  125. package/dist/services/template-sections.d.ts.map +1 -0
  126. package/dist/services/template-sections.js +55 -0
  127. package/dist/services/template-sections.js.map +1 -0
  128. package/dist/services/template-service.d.ts.map +1 -1
  129. package/dist/services/template-service.js +1 -0
  130. package/dist/services/template-service.js.map +1 -1
  131. package/dist/services/voice-service.d.ts +12 -0
  132. package/dist/services/voice-service.d.ts.map +1 -0
  133. package/dist/services/voice-service.js +42 -0
  134. package/dist/services/voice-service.js.map +1 -0
  135. package/dist/templates/export/planning-report.html.hbs +10 -0
  136. package/dist/templates/export/planning-report.md.hbs +11 -0
  137. package/dist/templates/linter/linter-config.json.hbs +13 -0
  138. package/dist/templates/reports/executive.md.hbs +28 -0
  139. package/dist/templates/reports/release-notes.md.hbs +37 -0
  140. package/dist/templates/reports/retrospective.md.hbs +36 -0
  141. package/dist/templates/reports/sprint.md.hbs +91 -0
  142. package/dist/templates/reports/standup.md.hbs +27 -0
  143. package/dist/templates/reports/weekly.md.hbs +42 -0
  144. package/dist/templates/voice/standup.md.hbs +20 -0
  145. package/dist/utils/diff.d.ts +26 -0
  146. package/dist/utils/diff.d.ts.map +1 -0
  147. package/dist/utils/diff.js +143 -0
  148. package/dist/utils/diff.js.map +1 -0
  149. package/package.json +1 -1
@@ -0,0 +1,249 @@
1
+ /**
2
+ * `planr revise` — core service (EPIC-003, FEAT-010 + FEAT-011).
3
+ *
4
+ * Exposes composable primitives; the CLI and future cascade service
5
+ * orchestrate them. Phase 1 (FEAT-010) ships `reviseArtifact` for dry-run
6
+ * decision generation; Phase 2 (FEAT-011) adds `applyDecision` for the
7
+ * write path and exposes the verifier context so callers can run
8
+ * `verifyDecision` against the same inputs the agent saw.
9
+ */
10
+ import path from 'node:path';
11
+ import { buildCodebaseContext, extractKeywords, formatCodebaseContext, } from '../ai/codebase/context-builder.js';
12
+ import { buildRevisePrompt, } from '../ai/prompts/prompt-builder.js';
13
+ import { aiReviseDecisionSchema } from '../ai/schemas/ai-response-schemas.js';
14
+ import { TOKEN_BUDGETS } from '../ai/types.js';
15
+ import { logger } from '../utils/logger.js';
16
+ import { generateJSON } from './ai-service.js';
17
+ import { findArtifactTypeById, getArtifactDir, getParentChain, listArtifacts, readArtifact, readArtifactRaw, resolveArtifactFilename, } from './artifact-service.js';
18
+ import { atomicWriteFile } from './atomic-write-service.js';
19
+ import { renderDiff } from './diff-service.js';
20
+ import { getCanonicalSections } from './template-sections.js';
21
+ /**
22
+ * Error thrown when an artifact id cannot be resolved to an artifact type or
23
+ * the artifact file does not exist on disk.
24
+ */
25
+ export class ReviseArtifactNotFoundError extends Error {
26
+ artifactId;
27
+ constructor(artifactId, message) {
28
+ super(message);
29
+ this.name = 'ReviseArtifactNotFoundError';
30
+ this.artifactId = artifactId;
31
+ }
32
+ }
33
+ /**
34
+ * Revise a single artifact — Phase 1 dry-run.
35
+ *
36
+ * Does NOT write any files. The returned decision is the agent output after
37
+ * schema validation; evidence verification, diff preview, and write are all
38
+ * Phase 2 responsibilities (FEAT-011). Cascade, siblings, and declared
39
+ * sources are Phase 3 (FEAT-012) and onwards.
40
+ */
41
+ export async function reviseArtifact(projectDir, config, provider, artifactId, options) {
42
+ const artifactType = findArtifactTypeById(artifactId);
43
+ if (!artifactType) {
44
+ throw new ReviseArtifactNotFoundError(artifactId, `Cannot determine artifact type from ID: ${artifactId}. Expected format: EPIC-001, FEAT-001, US-001, TASK-001.`);
45
+ }
46
+ const artifactRaw = await readArtifactRaw(projectDir, config, artifactType, artifactId);
47
+ if (artifactRaw === null) {
48
+ throw new ReviseArtifactNotFoundError(artifactId, `Artifact ${artifactId} not found under ${artifactType}/ directory.`);
49
+ }
50
+ const parents = await loadParentPromptArtifacts(projectDir, config, artifactType, artifactId);
51
+ const siblings = options.noSiblingContext
52
+ ? []
53
+ : await loadSiblingPromptArtifacts(projectDir, config, artifactType, artifactId, options.maxSiblings ?? 8);
54
+ let codebaseContextFormatted;
55
+ let codebaseCtx;
56
+ if (!options.noCodeContext) {
57
+ const keywords = extractKeywords(artifactRaw);
58
+ codebaseCtx = await buildCodebaseContext(projectDir, keywords);
59
+ codebaseContextFormatted = formatCodebaseContext(codebaseCtx);
60
+ }
61
+ const messages = buildRevisePrompt({
62
+ artifact: { id: artifactId, type: artifactType, content: artifactRaw },
63
+ parents,
64
+ siblings,
65
+ codebaseContextFormatted,
66
+ sources: [], // Declared-sources loader lands with the revise.yaml config work
67
+ writableScope: options.writableScope ?? 'all',
68
+ canonicalSections: getCanonicalSections(artifactType),
69
+ });
70
+ logger.debug(`reviseArtifact: calling AI for ${artifactId}`);
71
+ const result = await generateJSON(provider, messages, aiReviseDecisionSchema, {
72
+ maxTokens: TOKEN_BUDGETS.revise,
73
+ });
74
+ // resolveArtifactFilename strips the `.md` extension (other callers want the
75
+ // slug form). Revise must write to the full `.md` file, so append the
76
+ // extension explicitly. Defensive fallback if a future version ever returns
77
+ // a filename with the extension intact.
78
+ const filenameNoExt = await resolveArtifactFilename(projectDir, config, artifactType, artifactId);
79
+ const artifactDir = path.join(projectDir, getArtifactDir(config, artifactType));
80
+ const fullFilename = filenameNoExt.endsWith('.md') ? filenameNoExt : `${filenameNoExt}.md`;
81
+ const artifactPath = path.join(artifactDir, fullFilename);
82
+ const verifierContext = {
83
+ projectDir,
84
+ config,
85
+ artifactDir: path.dirname(artifactPath),
86
+ codebaseContextFormatted,
87
+ knownSourceRefs: [], // Phase 2 sources loader will populate
88
+ knownPatternRuleIds: codebaseCtx ? codebaseCtx.patternRules.map((r) => r.name) : [],
89
+ };
90
+ return {
91
+ decision: result.result,
92
+ usage: result.usage ?? { inputTokens: 0, outputTokens: 0 },
93
+ contextStats: {
94
+ parentsLoaded: parents.length,
95
+ siblingsLoaded: siblings.length,
96
+ codebaseContextIncluded: !!codebaseContextFormatted,
97
+ sourcesLoaded: 0,
98
+ },
99
+ artifactPath,
100
+ originalContent: artifactRaw,
101
+ verifierContext,
102
+ };
103
+ }
104
+ /**
105
+ * Apply a (verified) decision: write the artifact atomically when
106
+ * `action === 'revise'` and `dryRun` is false, emit an audit entry
107
+ * describing the outcome either way.
108
+ *
109
+ * Caller is expected to have already run `verifyDecision` — `applyDecision`
110
+ * trusts that whatever decision arrives is allowed to be written.
111
+ */
112
+ export async function applyDecision(options) {
113
+ const { decision, audit, dryRun, originalContent, artifactPath, backupDir } = options;
114
+ const timestamp = new Date().toISOString();
115
+ if (decision.action === 'skip') {
116
+ audit.appendEntry({
117
+ artifactId: decision.artifactId,
118
+ artifactPath,
119
+ outcome: 'skipped-by-agent',
120
+ rationale: decision.rationale,
121
+ evidence: decision.evidence,
122
+ ambiguous: decision.ambiguous,
123
+ cascadeLevel: options.cascadeLevel,
124
+ timestamp,
125
+ });
126
+ return { outcome: 'skipped-by-agent', wrote: false, diff: '' };
127
+ }
128
+ if (decision.action === 'flag') {
129
+ audit.appendEntry({
130
+ artifactId: decision.artifactId,
131
+ artifactPath,
132
+ outcome: 'flagged',
133
+ rationale: decision.rationale,
134
+ evidence: decision.evidence,
135
+ ambiguous: decision.ambiguous,
136
+ cascadeLevel: options.cascadeLevel,
137
+ timestamp,
138
+ });
139
+ return { outcome: 'flagged', wrote: false, diff: '' };
140
+ }
141
+ // action === 'revise'
142
+ const diff = decision.revisedMarkdown
143
+ ? renderDiff(originalContent, decision.revisedMarkdown, {
144
+ color: false,
145
+ oldLabel: `${decision.artifactId} (before)`,
146
+ newLabel: `${decision.artifactId} (proposed)`,
147
+ })
148
+ : '';
149
+ if (dryRun) {
150
+ audit.appendEntry({
151
+ artifactId: decision.artifactId,
152
+ artifactPath,
153
+ outcome: 'would-apply',
154
+ rationale: decision.rationale,
155
+ evidence: decision.evidence,
156
+ ambiguous: decision.ambiguous,
157
+ cascadeLevel: options.cascadeLevel,
158
+ diff,
159
+ timestamp,
160
+ });
161
+ return { outcome: 'would-apply', wrote: false, diff };
162
+ }
163
+ // Real apply: atomic write + sidecar backup.
164
+ const backupPath = path.join(backupDir, `${decision.artifactId}.md.bak`);
165
+ await atomicWriteFile(artifactPath, decision.revisedMarkdown ?? '', { backupPath });
166
+ audit.appendEntry({
167
+ artifactId: decision.artifactId,
168
+ artifactPath,
169
+ outcome: 'applied',
170
+ rationale: decision.rationale,
171
+ evidence: decision.evidence,
172
+ ambiguous: decision.ambiguous,
173
+ cascadeLevel: options.cascadeLevel,
174
+ diff,
175
+ timestamp,
176
+ });
177
+ return { outcome: 'applied', wrote: true, diff };
178
+ }
179
+ /**
180
+ * Load immediate-sibling artifacts (same artifact type, same parent) as
181
+ * prompt entries. Lazy-reads each sibling's body only if it's going to be
182
+ * included — the listing check is cheap, the reads are budgeted by
183
+ * `maxSiblings` (default 8) so the prompt stays within token budget even on
184
+ * epics with many features.
185
+ *
186
+ * For epic scope, there are no siblings (epics live at the top). For types
187
+ * without a parent-id relationship (quick, backlog, etc.), returns empty.
188
+ */
189
+ export async function loadSiblingPromptArtifacts(projectDir, config, type, id, maxSiblings) {
190
+ const parentFieldByType = {
191
+ feature: 'epicId',
192
+ story: 'featureId',
193
+ task: 'storyId',
194
+ };
195
+ const parentField = parentFieldByType[type];
196
+ if (!parentField)
197
+ return [];
198
+ const self = await readArtifact(projectDir, config, type, id);
199
+ if (!self)
200
+ return [];
201
+ const parentId = self.data[parentField];
202
+ if (!parentId)
203
+ return [];
204
+ const siblings = [];
205
+ const listing = await listArtifacts(projectDir, config, type);
206
+ for (const entry of listing) {
207
+ if (siblings.length >= maxSiblings)
208
+ break;
209
+ if (entry.id === id)
210
+ continue;
211
+ const sib = await readArtifact(projectDir, config, type, entry.id);
212
+ if (sib && sib.data[parentField] === parentId) {
213
+ siblings.push({ id: entry.id, type, content: sib.content });
214
+ }
215
+ }
216
+ return siblings;
217
+ }
218
+ /**
219
+ * Resolve the parent chain for an artifact and return it as the ordered
220
+ * `RevisePromptArtifact[]` the prompt builder expects (epic → feature →
221
+ * story). Empty array for top-level artifacts (epic scope).
222
+ */
223
+ export async function loadParentPromptArtifacts(projectDir, config, type, id) {
224
+ const chain = await getParentChain(projectDir, config, type, id);
225
+ const parents = [];
226
+ if (chain.epic) {
227
+ parents.push({
228
+ id: String(chain.epic.data.id),
229
+ type: 'epic',
230
+ content: chain.epic.content,
231
+ });
232
+ }
233
+ if (chain.feature) {
234
+ parents.push({
235
+ id: String(chain.feature.data.id),
236
+ type: 'feature',
237
+ content: chain.feature.content,
238
+ });
239
+ }
240
+ if (chain.story) {
241
+ parents.push({
242
+ id: String(chain.story.data.id),
243
+ type: 'story',
244
+ content: chain.story.content,
245
+ });
246
+ }
247
+ return parents;
248
+ }
249
+ //# sourceMappingURL=revise-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revise-service.js","sourceRoot":"","sources":["../../src/services/revise-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Heuristic parsing of a standup transcript into yesterday / today / blockers.
3
+ */
4
+ export interface TranscriptSegment {
5
+ section: 'yesterday' | 'today' | 'blockers' | 'note';
6
+ text: string;
7
+ /** Placeholder for future audio/text sync (milliseconds from clip start) */
8
+ audioOffsetMs?: number;
9
+ }
10
+ export interface ParsedStandup {
11
+ yesterday: string[];
12
+ today: string[];
13
+ blockers: string[];
14
+ incomplete: boolean;
15
+ notes: string[];
16
+ /** Best-effort line segments (no audio yet — offsets unused until capture exists) */
17
+ segments: TranscriptSegment[];
18
+ }
19
+ export declare function parseStandupTranscript(raw: string): ParsedStandup;
20
+ export declare function formatStandupMarkdown(parsed: ParsedStandup): string;
21
+ //# sourceMappingURL=standup-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standup-parser.d.ts","sourceRoot":"","sources":["../../src/services/standup-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,qFAAqF;IACrF,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAMD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CA0EjE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAoBnE"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Heuristic parsing of a standup transcript into yesterday / today / blockers.
3
+ */
4
+ const YDAY = /^(yesterday|last day|previously|done)\s*[:-]?\s*(.+)$/i;
5
+ const TODAY = /^(today|now|this session|working on)\s*[:-]?\s*(.+)$/i;
6
+ const BLOCK = /^(blockers?|blocked|impediments?)\s*[:-]?\s*(.+)$/i;
7
+ export function parseStandupTranscript(raw) {
8
+ const yesterday = [];
9
+ const today = [];
10
+ const blockers = [];
11
+ const notes = [];
12
+ const segments = [];
13
+ const lines = raw
14
+ .split(/\r?\n/)
15
+ .map((l) => l.trim())
16
+ .filter(Boolean);
17
+ let mode = null;
18
+ for (const line of lines) {
19
+ let m = line.match(YDAY);
20
+ if (m) {
21
+ mode = 'y';
22
+ const t = m[2].trim();
23
+ yesterday.push(t);
24
+ segments.push({ section: 'yesterday', text: t });
25
+ continue;
26
+ }
27
+ m = line.match(TODAY);
28
+ if (m) {
29
+ mode = 't';
30
+ const t = m[2].trim();
31
+ today.push(t);
32
+ segments.push({ section: 'today', text: t });
33
+ continue;
34
+ }
35
+ m = line.match(BLOCK);
36
+ if (m) {
37
+ mode = 'b';
38
+ const t = m[2].trim();
39
+ blockers.push(t);
40
+ segments.push({ section: 'blockers', text: t });
41
+ continue;
42
+ }
43
+ if (/^[-*]\s+/.test(line)) {
44
+ const item = line.replace(/^[-*]\s+/, '').trim();
45
+ if (mode === 'y') {
46
+ yesterday.push(item);
47
+ segments.push({ section: 'yesterday', text: item });
48
+ }
49
+ else if (mode === 't') {
50
+ today.push(item);
51
+ segments.push({ section: 'today', text: item });
52
+ }
53
+ else if (mode === 'b') {
54
+ blockers.push(item);
55
+ segments.push({ section: 'blockers', text: item });
56
+ }
57
+ else {
58
+ notes.push(item);
59
+ segments.push({ section: 'note', text: item });
60
+ }
61
+ continue;
62
+ }
63
+ if (mode === 'y') {
64
+ yesterday.push(line);
65
+ segments.push({ section: 'yesterday', text: line });
66
+ }
67
+ else if (mode === 't') {
68
+ today.push(line);
69
+ segments.push({ section: 'today', text: line });
70
+ }
71
+ else if (mode === 'b') {
72
+ blockers.push(line);
73
+ segments.push({ section: 'blockers', text: line });
74
+ }
75
+ else {
76
+ notes.push(line);
77
+ segments.push({ section: 'note', text: line });
78
+ }
79
+ }
80
+ const incomplete = yesterday.length === 0 || today.length === 0;
81
+ return { yesterday, today, blockers, incomplete, notes, segments };
82
+ }
83
+ export function formatStandupMarkdown(parsed) {
84
+ const sec = (title, items) => {
85
+ const body = items.length > 0 ? items.map((i) => `- ${i}`).join('\n') : '_— none recorded —_';
86
+ return `## ${title}\n\n${body}`;
87
+ };
88
+ return [
89
+ '# Standup',
90
+ '',
91
+ sec('Yesterday', parsed.yesterday),
92
+ '',
93
+ sec('Today', parsed.today),
94
+ '',
95
+ sec('Blockers', parsed.blockers),
96
+ parsed.notes.length > 0 ? `\n## Notes\n\n${parsed.notes.map((n) => `- ${n}`).join('\n')}` : '',
97
+ parsed.incomplete
98
+ ? '\n> **Note:** Some standup sections look incomplete. Fill in missing parts before sending.\n'
99
+ : '',
100
+ ]
101
+ .filter(Boolean)
102
+ .join('\n');
103
+ }
104
+ //# sourceMappingURL=standup-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standup-parser.js","sourceRoot":"","sources":["../../src/services/standup-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Append generated standup markdown to a user story file.
3
+ */
4
+ import type { OpenPlanrConfig } from '../models/types.js';
5
+ export declare function injectStandupSection(raw: string, standupMarkdown: string, date: string): string;
6
+ export declare function appendStandupToStory(projectDir: string, config: OpenPlanrConfig, storyId: string, standupMarkdown: string): Promise<void>;
7
+ //# sourceMappingURL=story-standup-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"story-standup-service.d.ts","sourceRoot":"","sources":["../../src/services/story-standup-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAK1D,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAe/F;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Append generated standup markdown to a user story file.
3
+ */
4
+ import { readArtifactRaw, updateArtifact } from './artifact-service.js';
5
+ const STANDUP_SECTION = '## Standup notes';
6
+ export function injectStandupSection(raw, standupMarkdown, date) {
7
+ const block = `\n### ${date}\n\n${standupMarkdown.trim()}\n`;
8
+ if (raw.includes(STANDUP_SECTION)) {
9
+ const idx = raw.indexOf(STANDUP_SECTION) + STANDUP_SECTION.length;
10
+ return `${raw.slice(0, idx)}${block}${raw.slice(idx)}`;
11
+ }
12
+ const tasksMatch = /\n## Tasks\b/m.exec(raw);
13
+ if (tasksMatch?.index !== undefined) {
14
+ const i = tasksMatch.index;
15
+ return `${raw.slice(0, i)}\n\n${STANDUP_SECTION}\n${block}\n${raw.slice(i)}`;
16
+ }
17
+ return `${raw.trimEnd()}\n\n${STANDUP_SECTION}\n${block}\n`;
18
+ }
19
+ export async function appendStandupToStory(projectDir, config, storyId, standupMarkdown) {
20
+ const raw = await readArtifactRaw(projectDir, config, 'story', storyId);
21
+ if (!raw)
22
+ throw new Error(`Story ${storyId} not found.`);
23
+ const date = new Date().toISOString().split('T')[0];
24
+ const next = injectStandupSection(raw, standupMarkdown, date);
25
+ await updateArtifact(projectDir, config, 'story', storyId, next);
26
+ }
27
+ //# sourceMappingURL=story-standup-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"story-standup-service.js","sourceRoot":"","sources":["../../src/services/story-standup-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAExE,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAE3C,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAE,eAAuB,EAAE,IAAY;IACrF,MAAM,KAAK,GAAG,SAAS,IAAI,OAAO,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC;IAE7D,IAAI,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC;QAClE,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,UAAU,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC;QAC3B,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,eAAe,KAAK,KAAK,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,CAAC;IAED,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,OAAO,eAAe,KAAK,KAAK,IAAI,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAAkB,EAClB,MAAuB,EACvB,OAAe,EACf,eAAuB;IAEvB,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACxE,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,aAAa,CAAC,CAAC;IAEzD,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,CAAC,CAAC;IAC9D,MAAM,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Canonical section lists per artifact type (EPIC-003, FEAT-014 follow-up).
3
+ *
4
+ * The revise prompt uses these to give the agent a *soft* conformance hint:
5
+ * "these are the sections a ${type} artifact canonically has — don't invent
6
+ * new ones; flag instead." This prevents the failure mode where the agent
7
+ * helpfully adds something like `## Relevant Files` to an epic (a task-level
8
+ * convention) when there is no drift justifying it.
9
+ *
10
+ * The lists mirror what the Handlebars templates in `src/templates/<type>/`
11
+ * actually emit. Kept hardcoded rather than parsed from the .hbs files at
12
+ * runtime because:
13
+ *
14
+ * 1. Handlebars templates contain `{{ }}` interpolation that would need
15
+ * stripping before we could grep `## ` headings.
16
+ * 2. If a template gains a new section, we want an explicit review step
17
+ * in this file, not silent pickup.
18
+ * 3. Parsing templates would couple revise to handlebars internals.
19
+ *
20
+ * When you add or rename a template section, update the matching entry here.
21
+ */
22
+ import type { ArtifactType } from '../models/types.js';
23
+ /**
24
+ * Return the canonical section list for an artifact type, or `undefined`
25
+ * when the type has no enforced convention (e.g., `backlog`).
26
+ */
27
+ export declare function getCanonicalSections(type: ArtifactType): readonly string[] | undefined;
28
+ //# sourceMappingURL=template-sections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-sections.d.ts","sourceRoot":"","sources":["../../src/services/template-sections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA6BvD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAEtF"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Canonical section lists per artifact type (EPIC-003, FEAT-014 follow-up).
3
+ *
4
+ * The revise prompt uses these to give the agent a *soft* conformance hint:
5
+ * "these are the sections a ${type} artifact canonically has — don't invent
6
+ * new ones; flag instead." This prevents the failure mode where the agent
7
+ * helpfully adds something like `## Relevant Files` to an epic (a task-level
8
+ * convention) when there is no drift justifying it.
9
+ *
10
+ * The lists mirror what the Handlebars templates in `src/templates/<type>/`
11
+ * actually emit. Kept hardcoded rather than parsed from the .hbs files at
12
+ * runtime because:
13
+ *
14
+ * 1. Handlebars templates contain `{{ }}` interpolation that would need
15
+ * stripping before we could grep `## ` headings.
16
+ * 2. If a template gains a new section, we want an explicit review step
17
+ * in this file, not silent pickup.
18
+ * 3. Parsing templates would couple revise to handlebars internals.
19
+ *
20
+ * When you add or rename a template section, update the matching entry here.
21
+ */
22
+ const CANONICAL_SECTIONS = {
23
+ epic: [
24
+ 'Business Value',
25
+ 'Target Users',
26
+ 'Problem Statement',
27
+ 'Solution Overview',
28
+ 'Success Criteria',
29
+ 'Key Features',
30
+ 'Dependencies',
31
+ 'Risks',
32
+ 'Features',
33
+ ],
34
+ feature: [
35
+ 'Overview',
36
+ 'Functional Requirements',
37
+ 'User Stories',
38
+ 'Dependencies',
39
+ 'Technical Considerations',
40
+ 'Risks',
41
+ 'Success Metrics',
42
+ ],
43
+ story: ['User Story', 'Acceptance Criteria', 'Additional Notes', 'Tasks'],
44
+ task: ['Artifact Sources', 'Tasks', 'Acceptance Criteria Mapping', 'Relevant Files', 'Notes'],
45
+ // `quick`, `backlog`, `sprint`, `adr`, `checklist` — no canonical list
46
+ // enforced. Revise will skip the template-structure hint for these types.
47
+ };
48
+ /**
49
+ * Return the canonical section list for an artifact type, or `undefined`
50
+ * when the type has no enforced convention (e.g., `backlog`).
51
+ */
52
+ export function getCanonicalSections(type) {
53
+ return CANONICAL_SECTIONS[type];
54
+ }
55
+ //# sourceMappingURL=template-sections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-sections.js","sourceRoot":"","sources":["../../src/services/template-sections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,MAAM,kBAAkB,GAAqD;IAC3E,IAAI,EAAE;QACJ,gBAAgB;QAChB,cAAc;QACd,mBAAmB;QACnB,mBAAmB;QACnB,kBAAkB;QAClB,cAAc;QACd,cAAc;QACd,OAAO;QACP,UAAU;KACX;IACD,OAAO,EAAE;QACP,UAAU;QACV,yBAAyB;QACzB,cAAc;QACd,cAAc;QACd,0BAA0B;QAC1B,OAAO;QACP,iBAAiB;KAClB;IACD,KAAK,EAAE,CAAC,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,OAAO,CAAC;IACzE,IAAI,EAAE,CAAC,kBAAkB,EAAE,OAAO,EAAE,6BAA6B,EAAE,gBAAgB,EAAE,OAAO,CAAC;IAC7F,uEAAuE;IACvE,0EAA0E;CAC3E,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAkB;IACrD,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"template-service.d.ts","sourceRoot":"","sources":["../../src/services/template-service.ts"],"names":[],"mappings":"AAyBA,uFAAuF;AACvF,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,sCAAsC;AACrE,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAYjB"}
1
+ {"version":3,"file":"template-service.d.ts","sourceRoot":"","sources":["../../src/services/template-service.ts"],"names":[],"mappings":"AA2BA,uFAAuF;AACvF,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,sCAAsC;AACrE,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAYjB"}
@@ -13,6 +13,7 @@ Handlebars.registerHelper('checkboxList', (items) => {
13
13
  });
14
14
  Handlebars.registerHelper('join', (arr, sep) => Array.isArray(arr) ? arr.join(typeof sep === 'string' ? sep : ', ') : '');
15
15
  Handlebars.registerHelper('eq', (a, b) => a === b);
16
+ Handlebars.registerHelper('length', (arr) => (Array.isArray(arr) ? arr.length : 0));
16
17
  /** Compile and render a Handlebars template, checking the override directory first. */
17
18
  export async function renderTemplate(templatePath, data, // Template data is inherently untyped
18
19
  overrideDir) {
@@ -1 +1 @@
1
- {"version":3,"file":"template-service.js","sourceRoot":"","sources":["../../src/services/template-service.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsC,CAAC;AAEpE,UAAU,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF,UAAU,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CACrD,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CACjD,CAAC;AAEF,UAAU,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,KAAe,EAAE,EAAE;IAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,GAAa,EAAE,GAAY,EAAE,EAAE,CAChE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CACzE,CAAC;AAEF,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAU,EAAE,CAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAErE,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,YAAoB,EACpB,IAA6B,EAAE,sCAAsC;AACrE,WAAoB;IAEpB,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACtE,IAAI,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrC,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,YAAoB,EAAE,WAAoB;IAC3E,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC1D,IAAI,MAAM,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACnC,OAAO,YAAY,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,YAAY,CAAC,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"template-service.js","sourceRoot":"","sources":["../../src/services/template-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Voice-oriented standup workflow: consume transcript text from file or stdin.
3
+ * Live microphone capture can be added later without changing the parser.
4
+ */
5
+ import type { VoiceStandupSession } from '../models/types.js';
6
+ export declare function loadTranscriptFromFile(path: string): Promise<VoiceStandupSession>;
7
+ export declare function transcriptToStandupMarkdown(transcript: string): string;
8
+ /** Read transcript from `--file` or stdin (must not be empty). */
9
+ export declare function readStandupTranscriptSource(opts: {
10
+ file?: string;
11
+ }): Promise<string>;
12
+ //# sourceMappingURL=voice-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-service.d.ts","sourceRoot":"","sources":["../../src/services/voice-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG9D,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAWvF;AAED,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,kEAAkE;AAClE,wBAAsB,2BAA2B,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAe1F"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Voice-oriented standup workflow: consume transcript text from file or stdin.
3
+ * Live microphone capture can be added later without changing the parser.
4
+ */
5
+ import { readFile } from 'node:fs/promises';
6
+ import { formatStandupMarkdown, parseStandupTranscript } from './standup-parser.js';
7
+ export async function loadTranscriptFromFile(path) {
8
+ try {
9
+ const transcript = await readFile(path, 'utf-8');
10
+ return { status: 'done', transcript: transcript.trim() };
11
+ }
12
+ catch (err) {
13
+ return {
14
+ status: 'error',
15
+ transcript: '',
16
+ errorMessage: err.message,
17
+ };
18
+ }
19
+ }
20
+ export function transcriptToStandupMarkdown(transcript) {
21
+ const parsed = parseStandupTranscript(transcript);
22
+ return formatStandupMarkdown(parsed);
23
+ }
24
+ /** Read transcript from `--file` or stdin (must not be empty). */
25
+ export async function readStandupTranscriptSource(opts) {
26
+ if (opts.file) {
27
+ const session = await loadTranscriptFromFile(opts.file);
28
+ if (session.status === 'error') {
29
+ throw new Error(session.errorMessage || 'Failed to read transcript file');
30
+ }
31
+ return session.transcript;
32
+ }
33
+ const chunks = [];
34
+ for await (const c of process.stdin)
35
+ chunks.push(c);
36
+ const text = Buffer.concat(chunks).toString('utf-8').trim();
37
+ if (!text) {
38
+ throw new Error('Provide --file <path> or pipe transcript text on stdin.');
39
+ }
40
+ return text;
41
+ }
42
+ //# sourceMappingURL=voice-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-service.js","sourceRoot":"","sources":["../../src/services/voice-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAEpF,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAAY;IACvD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,OAAO;YACf,UAAU,EAAE,EAAE;YACd,YAAY,EAAG,GAAa,CAAC,OAAO;SACrC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,UAAkB;IAC5D,MAAM,MAAM,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,IAAuB;IACvE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,IAAI,gCAAgC,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,OAAO,CAAC,UAAU,CAAC;IAC5B,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,CAAW,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}