@riotprompt/riotdoc 1.0.1-dev.0 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -10,6 +10,64 @@ export declare type AssistanceLevel = "generate" | "expand" | "revise" | "cleanu
10
10
  */
11
11
  export declare function buildVoicePrompt(voice: VoiceConfig): string;
12
12
 
13
+ /**
14
+ * Checkpoint created event
15
+ */
16
+ export declare interface CheckpointCreatedEvent extends TimelineEvent {
17
+ type: "checkpoint_created";
18
+ data: {
19
+ /** Checkpoint name (kebab-case) */
20
+ name: string;
21
+ /** Description of checkpoint */
22
+ message: string;
23
+ /** Path to checkpoint snapshot (relative) */
24
+ snapshotPath?: string;
25
+ /** Path to prompt context (relative) */
26
+ promptPath?: string;
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Checkpoint metadata structure
32
+ */
33
+ export declare interface CheckpointMetadata {
34
+ /** Checkpoint name */
35
+ name: string;
36
+ /** When created (ISO 8601) */
37
+ timestamp: string;
38
+ /** User-provided description */
39
+ message: string;
40
+ /** Current status */
41
+ status: string;
42
+ /** Snapshot of document files */
43
+ snapshot: {
44
+ timestamp: string;
45
+ config?: FileSnapshot;
46
+ outline?: FileSnapshot;
47
+ currentDraft?: FileSnapshot;
48
+ };
49
+ /** Context information */
50
+ context: {
51
+ /** List of .md files at checkpoint */
52
+ filesChanged: string[];
53
+ /** Timeline events since last checkpoint */
54
+ eventsSinceLastCheckpoint: number;
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Checkpoint restored event
60
+ */
61
+ export declare interface CheckpointRestoredEvent extends TimelineEvent {
62
+ type: "checkpoint_restored";
63
+ data: {
64
+ /** Name of restored checkpoint */
65
+ checkpoint: string;
66
+ /** Timestamp of original checkpoint */
67
+ restoredFrom: string;
68
+ };
69
+ }
70
+
13
71
  /**
14
72
  * Create a new RiotDoc workspace
15
73
  */
@@ -61,6 +119,12 @@ export declare interface DocumentConfig {
61
119
  type: DocumentType;
62
120
  /** Current status */
63
121
  status: DocumentStatus;
122
+ /** Current version (e.g., "0.1", "1.0") */
123
+ version: string;
124
+ /** Whether document is published (v1.0+) or draft (v0.x) */
125
+ published: boolean;
126
+ /** Version history */
127
+ versionHistory: VersionHistoryEntry[];
64
128
  /** Creation timestamp */
65
129
  createdAt: Date;
66
130
  /** Last modified timestamp */
@@ -76,34 +140,27 @@ export declare interface DocumentConfig {
76
140
  export declare const DocumentConfigSchema: z.ZodObject<{
77
141
  id: z.ZodString;
78
142
  title: z.ZodString;
79
- type: z.ZodEnum<["blog-post", "podcast-script", "technical-doc", "newsletter", "custom"]>;
80
- status: z.ZodEnum<["idea", "outlined", "drafting", "revising", "final", "exported"]>;
81
- createdAt: z.ZodDate;
82
- updatedAt: z.ZodDate;
143
+ type: z.ZodEnum<{
144
+ "blog-post": "blog-post";
145
+ "podcast-script": "podcast-script";
146
+ "technical-doc": "technical-doc";
147
+ newsletter: "newsletter";
148
+ custom: "custom";
149
+ }>;
150
+ status: z.ZodEnum<{
151
+ idea: "idea";
152
+ outlined: "outlined";
153
+ drafting: "drafting";
154
+ revising: "revising";
155
+ final: "final";
156
+ exported: "exported";
157
+ }>;
158
+ createdAt: z.ZodCoercedDate<unknown>;
159
+ updatedAt: z.ZodCoercedDate<unknown>;
83
160
  targetWordCount: z.ZodOptional<z.ZodNumber>;
84
161
  audience: z.ZodOptional<z.ZodString>;
85
162
  metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
86
- }, "strip", z.ZodTypeAny, {
87
- id: string;
88
- title: string;
89
- type: "blog-post" | "podcast-script" | "technical-doc" | "newsletter" | "custom";
90
- status: "idea" | "outlined" | "drafting" | "revising" | "final" | "exported";
91
- createdAt: Date;
92
- updatedAt: Date;
93
- targetWordCount?: number | undefined;
94
- audience?: string | undefined;
95
- metadata?: Record<string, unknown> | undefined;
96
- }, {
97
- id: string;
98
- title: string;
99
- type: "blog-post" | "podcast-script" | "technical-doc" | "newsletter" | "custom";
100
- status: "idea" | "outlined" | "drafting" | "revising" | "final" | "exported";
101
- createdAt: Date;
102
- updatedAt: Date;
103
- targetWordCount?: number | undefined;
104
- audience?: string | undefined;
105
- metadata?: Record<string, unknown> | undefined;
106
- }>;
163
+ }, z.core.$strip>;
107
164
 
108
165
  /**
109
166
  * Document objectives
@@ -123,23 +180,11 @@ export declare interface DocumentObjectives {
123
180
 
124
181
  export declare const DocumentObjectivesSchema: z.ZodObject<{
125
182
  primaryGoal: z.ZodString;
126
- secondaryGoals: z.ZodArray<z.ZodString, "many">;
183
+ secondaryGoals: z.ZodArray<z.ZodString>;
127
184
  callToAction: z.ZodOptional<z.ZodString>;
128
- keyTakeaways: z.ZodArray<z.ZodString, "many">;
185
+ keyTakeaways: z.ZodArray<z.ZodString>;
129
186
  emotionalArc: z.ZodOptional<z.ZodString>;
130
- }, "strip", z.ZodTypeAny, {
131
- primaryGoal: string;
132
- secondaryGoals: string[];
133
- keyTakeaways: string[];
134
- callToAction?: string | undefined;
135
- emotionalArc?: string | undefined;
136
- }, {
137
- primaryGoal: string;
138
- secondaryGoals: string[];
139
- keyTakeaways: string[];
140
- callToAction?: string | undefined;
141
- emotionalArc?: string | undefined;
142
- }>;
187
+ }, z.core.$strip>;
143
188
 
144
189
  export declare interface DocumentStats {
145
190
  wordCount: number;
@@ -195,6 +240,16 @@ export declare interface EvidenceItem {
195
240
  incorporatedIn?: string;
196
241
  }
197
242
 
243
+ /**
244
+ * File snapshot in checkpoint
245
+ */
246
+ export declare interface FileSnapshot {
247
+ /** Whether file exists */
248
+ exists: boolean;
249
+ /** File content (if exists) */
250
+ content?: string;
251
+ }
252
+
198
253
  /**
199
254
  * Format style validation result for terminal
200
255
  */
@@ -215,6 +270,23 @@ export declare function loadGlossary(workspacePath: string): Promise<Map<string,
215
270
  */
216
271
  export declare function loadVoice(workspacePath: string): Promise<VoiceConfig>;
217
272
 
273
+ /**
274
+ * Narrative chunk event - captures raw conversational input
275
+ */
276
+ export declare interface NarrativeChunkEvent extends TimelineEvent {
277
+ type: "narrative_chunk";
278
+ data: {
279
+ /** Raw user input */
280
+ content: string;
281
+ /** Source of input */
282
+ source?: "typing" | "voice" | "paste" | "import";
283
+ /** Context about what prompted this */
284
+ context?: string;
285
+ /** Who is speaking */
286
+ speaker?: "user" | "assistant" | "system";
287
+ };
288
+ }
289
+
218
290
  /**
219
291
  * Parse style rules markdown
220
292
  */
@@ -317,11 +389,42 @@ export declare interface StyleViolation {
317
389
  severity: "error" | "warning" | "info";
318
390
  }
319
391
 
392
+ /**
393
+ * Base timeline event structure
394
+ */
395
+ export declare interface TimelineEvent {
396
+ /** ISO 8601 timestamp */
397
+ timestamp: string;
398
+ /** Event type identifier */
399
+ type: TimelineEventType;
400
+ /** Event-specific data */
401
+ data: Record<string, any>;
402
+ }
403
+
404
+ /**
405
+ * Timeline event types for document lifecycle
406
+ */
407
+ export declare type TimelineEventType = "document_created" | "outline_created" | "draft_created" | "revision_added" | "evidence_added" | "exported" | "version_incremented" | "version_published" | "narrative_chunk" | "checkpoint_created" | "checkpoint_restored";
408
+
320
409
  /**
321
410
  * Validate document content against style rules
322
411
  */
323
412
  export declare function validateStyle(content: string, rules: StyleRules): StyleValidationResult;
324
413
 
414
+ /**
415
+ * Version history entry
416
+ */
417
+ export declare interface VersionHistoryEntry {
418
+ /** Version number (e.g., "0.1", "1.0") */
419
+ version: string;
420
+ /** When this version was created */
421
+ timestamp: string;
422
+ /** Draft file path for this version */
423
+ draftPath?: string;
424
+ /** Notes about this version */
425
+ notes?: string;
426
+ }
427
+
325
428
  /**
326
429
  * Voice and tone configuration
327
430
  */
@@ -340,22 +443,14 @@ export declare interface VoiceConfig {
340
443
 
341
444
  export declare const VoiceConfigSchema: z.ZodObject<{
342
445
  tone: z.ZodString;
343
- pointOfView: z.ZodEnum<["first", "second", "third"]>;
344
- styleNotes: z.ZodArray<z.ZodString, "many">;
345
- avoid: z.ZodArray<z.ZodString, "many">;
346
- examplePhrases: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
347
- }, "strip", z.ZodTypeAny, {
348
- tone: string;
349
- pointOfView: "first" | "second" | "third";
350
- styleNotes: string[];
351
- avoid: string[];
352
- examplePhrases?: string[] | undefined;
353
- }, {
354
- tone: string;
355
- pointOfView: "first" | "second" | "third";
356
- styleNotes: string[];
357
- avoid: string[];
358
- examplePhrases?: string[] | undefined;
359
- }>;
446
+ pointOfView: z.ZodEnum<{
447
+ first: "first";
448
+ second: "second";
449
+ third: "third";
450
+ }>;
451
+ styleNotes: z.ZodArray<z.ZodString>;
452
+ avoid: z.ZodArray<z.ZodString>;
453
+ examplePhrases: z.ZodOptional<z.ZodArray<z.ZodString>>;
454
+ }, z.core.$strip>;
360
455
 
361
456
  export { }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { D, a, R, c, h, l, b, p, d } from "./loader-B7ZeTPQg.js";
2
+ import { D, a, R, c, h, l, b, p, d } from "./loader-DJHV70rz.js";
3
3
  import chalk from "chalk";
4
4
  const DocumentConfigSchema = z.object({
5
5
  id: z.string(),
@@ -10,7 +10,7 @@ const DocumentConfigSchema = z.object({
10
10
  updatedAt: z.coerce.date(),
11
11
  targetWordCount: z.number().optional(),
12
12
  audience: z.string().optional(),
13
- metadata: z.record(z.unknown()).optional()
13
+ metadata: z.record(z.string(), z.unknown()).optional()
14
14
  });
15
15
  const VoiceConfigSchema = z.object({
16
16
  tone: z.string(),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/schema.ts","../src/voice/prompt-builder.ts","../src/style/validator.ts","../src/style/reporter.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const DocumentConfigSchema = z.object({\n id: z.string(),\n title: z.string(),\n type: z.enum([\"blog-post\", \"podcast-script\", \"technical-doc\", \"newsletter\", \"custom\"]),\n status: z.enum([\"idea\", \"outlined\", \"drafting\", \"revising\", \"final\", \"exported\"]),\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n targetWordCount: z.number().optional(),\n audience: z.string().optional(),\n metadata: z.record(z.unknown()).optional(),\n});\n\nexport const VoiceConfigSchema = z.object({\n tone: z.string(),\n pointOfView: z.enum([\"first\", \"second\", \"third\"]),\n styleNotes: z.array(z.string()),\n avoid: z.array(z.string()),\n examplePhrases: z.array(z.string()).optional(),\n});\n\nexport const DocumentObjectivesSchema = z.object({\n primaryGoal: z.string(),\n secondaryGoals: z.array(z.string()),\n callToAction: z.string().optional(),\n keyTakeaways: z.array(z.string()),\n emotionalArc: z.string().optional(),\n});\n","import type { VoiceConfig } from \"../types.js\";\n\n/**\n * Build a prompt section describing the voice/tone\n */\nexport function buildVoicePrompt(voice: VoiceConfig): string {\n const sections: string[] = [];\n \n sections.push(`## Writing Voice\\n`);\n sections.push(`Tone: ${voice.tone}`);\n sections.push(`Point of view: ${formatPointOfView(voice.pointOfView)}`);\n \n if (voice.styleNotes.length > 0) {\n sections.push(`\\n### Style Guidelines\\n`);\n sections.push(`Do:\\n${voice.styleNotes.map(n => `- ${n}`).join(\"\\n\")}`);\n }\n \n if (voice.avoid.length > 0) {\n sections.push(`\\nAvoid:\\n${voice.avoid.map(a => `- ${a}`).join(\"\\n\")}`);\n }\n \n if (voice.examplePhrases && voice.examplePhrases.length > 0) {\n sections.push(`\\n### Example Phrases\\n`);\n sections.push(voice.examplePhrases.map(p => `\"${p}\"`).join(\"\\n\"));\n }\n \n return sections.join(\"\\n\");\n}\n\nfunction formatPointOfView(pov: \"first\" | \"second\" | \"third\"): string {\n switch (pov) {\n case \"first\": return \"First person (I, we)\";\n case \"second\": return \"Second person (you)\";\n case \"third\": return \"Third person (they, it)\";\n }\n}\n","export interface StyleViolation {\n rule: string;\n message: string;\n line?: number;\n severity: \"error\" | \"warning\" | \"info\";\n}\n\nexport interface StyleValidationResult {\n valid: boolean;\n violations: StyleViolation[];\n stats: DocumentStats;\n}\n\nexport interface DocumentStats {\n wordCount: number;\n sentenceCount: number;\n paragraphCount: number;\n avgWordsPerSentence: number;\n avgSentencesPerParagraph: number;\n}\n\n/**\n * Validate document content against style rules\n */\nexport function validateStyle(\n content: string,\n rules: StyleRules\n): StyleValidationResult {\n const violations: StyleViolation[] = [];\n const stats = calculateStats(content);\n \n // Check word count\n if (rules.maxWordCount && stats.wordCount > rules.maxWordCount) {\n violations.push({\n rule: \"max-word-count\",\n message: `Document has ${stats.wordCount} words, exceeds max of ${rules.maxWordCount}`,\n severity: \"warning\",\n });\n }\n \n if (rules.minWordCount && stats.wordCount < rules.minWordCount) {\n violations.push({\n rule: \"min-word-count\",\n message: `Document has ${stats.wordCount} words, below min of ${rules.minWordCount}`,\n severity: \"warning\",\n });\n }\n \n // Check sentence length\n if (rules.maxSentenceLength) {\n const longSentences = findLongSentences(content, rules.maxSentenceLength);\n for (const sentence of longSentences) {\n violations.push({\n rule: \"sentence-length\",\n message: `Sentence has ${sentence.wordCount} words: \"${sentence.preview}...\"`,\n line: sentence.line,\n severity: \"info\",\n });\n }\n }\n \n // Check passive voice\n if (rules.checkPassiveVoice) {\n const passiveInstances = findPassiveVoice(content);\n for (const instance of passiveInstances) {\n violations.push({\n rule: \"passive-voice\",\n message: `Possible passive voice: \"${instance.text}\"`,\n line: instance.line,\n severity: \"info\",\n });\n }\n }\n \n // Check for avoid patterns\n if (rules.avoidPatterns) {\n for (const pattern of rules.avoidPatterns) {\n const regex = new RegExp(pattern, \"gi\");\n const matches = content.matchAll(regex);\n for (const match of matches) {\n violations.push({\n rule: \"avoid-pattern\",\n message: `Found \"${match[0]}\" which should be avoided`,\n severity: \"warning\",\n });\n }\n }\n }\n \n return {\n valid: violations.filter(v => v.severity === \"error\").length === 0,\n violations,\n stats,\n };\n}\n\nexport interface StyleRules {\n maxWordCount?: number;\n minWordCount?: number;\n maxSentenceLength?: number;\n checkPassiveVoice?: boolean;\n avoidPatterns?: string[];\n}\n\n/**\n * Calculate document statistics\n */\nfunction calculateStats(content: string): DocumentStats {\n const words = content.split(/\\s+/).filter(w => w.length > 0);\n const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 0);\n const paragraphs = content.split(/\\n\\n+/).filter(p => p.trim().length > 0);\n \n return {\n wordCount: words.length,\n sentenceCount: sentences.length,\n paragraphCount: paragraphs.length,\n avgWordsPerSentence: sentences.length > 0 \n ? Math.round(words.length / sentences.length) \n : 0,\n avgSentencesPerParagraph: paragraphs.length > 0 \n ? Math.round(sentences.length / paragraphs.length) \n : 0,\n };\n}\n\n/**\n * Find sentences exceeding word limit\n */\nfunction findLongSentences(\n content: string, \n maxWords: number\n): Array<{ wordCount: number; preview: string; line: number }> {\n const results: Array<{ wordCount: number; preview: string; line: number }> = [];\n const lines = content.split(\"\\n\");\n \n let lineNum = 0;\n for (const line of lines) {\n lineNum++;\n const sentences = line.split(/[.!?]+/);\n for (const sentence of sentences) {\n const words = sentence.trim().split(/\\s+/).filter(w => w.length > 0);\n if (words.length > maxWords) {\n results.push({\n wordCount: words.length,\n preview: sentence.trim().slice(0, 50),\n line: lineNum,\n });\n }\n }\n }\n \n return results;\n}\n\n/**\n * Simple passive voice detection\n */\nfunction findPassiveVoice(content: string): Array<{ text: string; line: number }> {\n const results: Array<{ text: string; line: number }> = [];\n const lines = content.split(\"\\n\");\n \n // Common passive voice patterns\n const passivePatterns = [\n /\\b(was|were|been|being|is|are|am)\\s+\\w+ed\\b/gi,\n /\\b(was|were|been|being|is|are|am)\\s+\\w+en\\b/gi,\n ];\n \n let lineNum = 0;\n for (const line of lines) {\n lineNum++;\n for (const pattern of passivePatterns) {\n const matches = line.matchAll(pattern);\n for (const match of matches) {\n results.push({\n text: match[0],\n line: lineNum,\n });\n }\n }\n }\n \n return results;\n}\n","import chalk from \"chalk\";\nimport type { StyleValidationResult, StyleViolation } from \"./validator.js\";\n\n/**\n * Format style validation result for terminal\n */\nexport function formatStyleReport(result: StyleValidationResult): string {\n const lines: string[] = [];\n \n lines.push(chalk.cyan(\"\\n📊 Document Statistics\"));\n lines.push(chalk.gray(` Words: ${result.stats.wordCount}`));\n lines.push(chalk.gray(` Sentences: ${result.stats.sentenceCount}`));\n lines.push(chalk.gray(` Paragraphs: ${result.stats.paragraphCount}`));\n lines.push(chalk.gray(` Avg words/sentence: ${result.stats.avgWordsPerSentence}`));\n \n if (result.violations.length === 0) {\n lines.push(chalk.green(\"\\n✅ No style violations found.\"));\n return lines.join(\"\\n\");\n }\n \n lines.push(chalk.yellow(`\\n⚠️ Style Issues (${result.violations.length}):`));\n \n const grouped = groupViolations(result.violations);\n \n for (const [severity, violations] of Object.entries(grouped)) {\n if (violations.length === 0) continue;\n \n const icon = severity === \"error\" ? \"❌\" : severity === \"warning\" ? \"⚠️\" : \"ℹ️\";\n const color = severity === \"error\" ? chalk.red : severity === \"warning\" ? chalk.yellow : chalk.gray;\n \n lines.push(color(`\\n${icon} ${severity.toUpperCase()} (${violations.length}):`));\n for (const v of violations.slice(0, 5)) {\n const lineInfo = v.line ? ` (line ${v.line})` : \"\";\n lines.push(color(` - ${v.message}${lineInfo}`));\n }\n if (violations.length > 5) {\n lines.push(color(` ... and ${violations.length - 5} more`));\n }\n }\n \n return lines.join(\"\\n\");\n}\n\nfunction groupViolations(violations: StyleViolation[]): Record<string, StyleViolation[]> {\n return {\n error: violations.filter(v => v.severity === \"error\"),\n warning: violations.filter(v => v.severity === \"warning\"),\n info: violations.filter(v => v.severity === \"info\"),\n };\n}\n"],"names":["a","p"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/schema.ts","../src/voice/prompt-builder.ts","../src/style/validator.ts","../src/style/reporter.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const DocumentConfigSchema = z.object({\n id: z.string(),\n title: z.string(),\n type: z.enum([\"blog-post\", \"podcast-script\", \"technical-doc\", \"newsletter\", \"custom\"]),\n status: z.enum([\"idea\", \"outlined\", \"drafting\", \"revising\", \"final\", \"exported\"]),\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n targetWordCount: z.number().optional(),\n audience: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const VoiceConfigSchema = z.object({\n tone: z.string(),\n pointOfView: z.enum([\"first\", \"second\", \"third\"]),\n styleNotes: z.array(z.string()),\n avoid: z.array(z.string()),\n examplePhrases: z.array(z.string()).optional(),\n});\n\nexport const DocumentObjectivesSchema = z.object({\n primaryGoal: z.string(),\n secondaryGoals: z.array(z.string()),\n callToAction: z.string().optional(),\n keyTakeaways: z.array(z.string()),\n emotionalArc: z.string().optional(),\n});\n","import type { VoiceConfig } from \"../types.js\";\n\n/**\n * Build a prompt section describing the voice/tone\n */\nexport function buildVoicePrompt(voice: VoiceConfig): string {\n const sections: string[] = [];\n \n sections.push(`## Writing Voice\\n`);\n sections.push(`Tone: ${voice.tone}`);\n sections.push(`Point of view: ${formatPointOfView(voice.pointOfView)}`);\n \n if (voice.styleNotes.length > 0) {\n sections.push(`\\n### Style Guidelines\\n`);\n sections.push(`Do:\\n${voice.styleNotes.map(n => `- ${n}`).join(\"\\n\")}`);\n }\n \n if (voice.avoid.length > 0) {\n sections.push(`\\nAvoid:\\n${voice.avoid.map(a => `- ${a}`).join(\"\\n\")}`);\n }\n \n if (voice.examplePhrases && voice.examplePhrases.length > 0) {\n sections.push(`\\n### Example Phrases\\n`);\n sections.push(voice.examplePhrases.map(p => `\"${p}\"`).join(\"\\n\"));\n }\n \n return sections.join(\"\\n\");\n}\n\nfunction formatPointOfView(pov: \"first\" | \"second\" | \"third\"): string {\n switch (pov) {\n case \"first\": return \"First person (I, we)\";\n case \"second\": return \"Second person (you)\";\n case \"third\": return \"Third person (they, it)\";\n }\n}\n","export interface StyleViolation {\n rule: string;\n message: string;\n line?: number;\n severity: \"error\" | \"warning\" | \"info\";\n}\n\nexport interface StyleValidationResult {\n valid: boolean;\n violations: StyleViolation[];\n stats: DocumentStats;\n}\n\nexport interface DocumentStats {\n wordCount: number;\n sentenceCount: number;\n paragraphCount: number;\n avgWordsPerSentence: number;\n avgSentencesPerParagraph: number;\n}\n\n/**\n * Validate document content against style rules\n */\nexport function validateStyle(\n content: string,\n rules: StyleRules\n): StyleValidationResult {\n const violations: StyleViolation[] = [];\n const stats = calculateStats(content);\n \n // Check word count\n if (rules.maxWordCount && stats.wordCount > rules.maxWordCount) {\n violations.push({\n rule: \"max-word-count\",\n message: `Document has ${stats.wordCount} words, exceeds max of ${rules.maxWordCount}`,\n severity: \"warning\",\n });\n }\n \n if (rules.minWordCount && stats.wordCount < rules.minWordCount) {\n violations.push({\n rule: \"min-word-count\",\n message: `Document has ${stats.wordCount} words, below min of ${rules.minWordCount}`,\n severity: \"warning\",\n });\n }\n \n // Check sentence length\n if (rules.maxSentenceLength) {\n const longSentences = findLongSentences(content, rules.maxSentenceLength);\n for (const sentence of longSentences) {\n violations.push({\n rule: \"sentence-length\",\n message: `Sentence has ${sentence.wordCount} words: \"${sentence.preview}...\"`,\n line: sentence.line,\n severity: \"info\",\n });\n }\n }\n \n // Check passive voice\n if (rules.checkPassiveVoice) {\n const passiveInstances = findPassiveVoice(content);\n for (const instance of passiveInstances) {\n violations.push({\n rule: \"passive-voice\",\n message: `Possible passive voice: \"${instance.text}\"`,\n line: instance.line,\n severity: \"info\",\n });\n }\n }\n \n // Check for avoid patterns\n if (rules.avoidPatterns) {\n for (const pattern of rules.avoidPatterns) {\n const regex = new RegExp(pattern, \"gi\");\n const matches = content.matchAll(regex);\n for (const match of matches) {\n violations.push({\n rule: \"avoid-pattern\",\n message: `Found \"${match[0]}\" which should be avoided`,\n severity: \"warning\",\n });\n }\n }\n }\n \n return {\n valid: violations.filter(v => v.severity === \"error\").length === 0,\n violations,\n stats,\n };\n}\n\nexport interface StyleRules {\n maxWordCount?: number;\n minWordCount?: number;\n maxSentenceLength?: number;\n checkPassiveVoice?: boolean;\n avoidPatterns?: string[];\n}\n\n/**\n * Calculate document statistics\n */\nfunction calculateStats(content: string): DocumentStats {\n const words = content.split(/\\s+/).filter(w => w.length > 0);\n const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 0);\n const paragraphs = content.split(/\\n\\n+/).filter(p => p.trim().length > 0);\n \n return {\n wordCount: words.length,\n sentenceCount: sentences.length,\n paragraphCount: paragraphs.length,\n avgWordsPerSentence: sentences.length > 0 \n ? Math.round(words.length / sentences.length) \n : 0,\n avgSentencesPerParagraph: paragraphs.length > 0 \n ? Math.round(sentences.length / paragraphs.length) \n : 0,\n };\n}\n\n/**\n * Find sentences exceeding word limit\n */\nfunction findLongSentences(\n content: string, \n maxWords: number\n): Array<{ wordCount: number; preview: string; line: number }> {\n const results: Array<{ wordCount: number; preview: string; line: number }> = [];\n const lines = content.split(\"\\n\");\n \n let lineNum = 0;\n for (const line of lines) {\n lineNum++;\n const sentences = line.split(/[.!?]+/);\n for (const sentence of sentences) {\n const words = sentence.trim().split(/\\s+/).filter(w => w.length > 0);\n if (words.length > maxWords) {\n results.push({\n wordCount: words.length,\n preview: sentence.trim().slice(0, 50),\n line: lineNum,\n });\n }\n }\n }\n \n return results;\n}\n\n/**\n * Simple passive voice detection\n */\nfunction findPassiveVoice(content: string): Array<{ text: string; line: number }> {\n const results: Array<{ text: string; line: number }> = [];\n const lines = content.split(\"\\n\");\n \n // Common passive voice patterns\n const passivePatterns = [\n /\\b(was|were|been|being|is|are|am)\\s+\\w+ed\\b/gi,\n /\\b(was|were|been|being|is|are|am)\\s+\\w+en\\b/gi,\n ];\n \n let lineNum = 0;\n for (const line of lines) {\n lineNum++;\n for (const pattern of passivePatterns) {\n const matches = line.matchAll(pattern);\n for (const match of matches) {\n results.push({\n text: match[0],\n line: lineNum,\n });\n }\n }\n }\n \n return results;\n}\n","import chalk from \"chalk\";\nimport type { StyleValidationResult, StyleViolation } from \"./validator.js\";\n\n/**\n * Format style validation result for terminal\n */\nexport function formatStyleReport(result: StyleValidationResult): string {\n const lines: string[] = [];\n \n lines.push(chalk.cyan(\"\\n📊 Document Statistics\"));\n lines.push(chalk.gray(` Words: ${result.stats.wordCount}`));\n lines.push(chalk.gray(` Sentences: ${result.stats.sentenceCount}`));\n lines.push(chalk.gray(` Paragraphs: ${result.stats.paragraphCount}`));\n lines.push(chalk.gray(` Avg words/sentence: ${result.stats.avgWordsPerSentence}`));\n \n if (result.violations.length === 0) {\n lines.push(chalk.green(\"\\n✅ No style violations found.\"));\n return lines.join(\"\\n\");\n }\n \n lines.push(chalk.yellow(`\\n⚠️ Style Issues (${result.violations.length}):`));\n \n const grouped = groupViolations(result.violations);\n \n for (const [severity, violations] of Object.entries(grouped)) {\n if (violations.length === 0) continue;\n \n const icon = severity === \"error\" ? \"❌\" : severity === \"warning\" ? \"⚠️\" : \"ℹ️\";\n const color = severity === \"error\" ? chalk.red : severity === \"warning\" ? chalk.yellow : chalk.gray;\n \n lines.push(color(`\\n${icon} ${severity.toUpperCase()} (${violations.length}):`));\n for (const v of violations.slice(0, 5)) {\n const lineInfo = v.line ? ` (line ${v.line})` : \"\";\n lines.push(color(` - ${v.message}${lineInfo}`));\n }\n if (violations.length > 5) {\n lines.push(color(` ... and ${violations.length - 5} more`));\n }\n }\n \n return lines.join(\"\\n\");\n}\n\nfunction groupViolations(violations: StyleViolation[]): Record<string, StyleViolation[]> {\n return {\n error: violations.filter(v => v.severity === \"error\"),\n warning: violations.filter(v => v.severity === \"warning\"),\n info: violations.filter(v => v.severity === \"info\"),\n };\n}\n"],"names":["a","p"],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { R as RIOTDOC_STRUCTURE } from "./loader-DJHV70rz.js";
4
+ import { parse } from "yaml";
5
+ async function loadOutline(workspacePath) {
6
+ const outlinePath = join(workspacePath, RIOTDOC_STRUCTURE.outlineFile);
7
+ return await readFile(outlinePath, "utf-8");
8
+ }
9
+ function buildOutlinePrompt(objectives, voice, documentType) {
10
+ return `Generate an outline for a ${documentType}.
11
+
12
+ ## Objectives
13
+
14
+ Primary Goal: ${objectives.primaryGoal}
15
+
16
+ Secondary Goals:
17
+ ${objectives.secondaryGoals.map((g) => `- ${g}`).join("\n")}
18
+
19
+ Key Takeaways:
20
+ ${objectives.keyTakeaways.map((t) => `- ${t}`).join("\n")}
21
+
22
+ ${objectives.emotionalArc ? `Emotional Arc: ${objectives.emotionalArc}` : ""}
23
+
24
+ ## Voice & Tone
25
+
26
+ Tone: ${voice.tone}
27
+ Point of View: ${voice.pointOfView}
28
+
29
+ ## Output Format
30
+
31
+ Create a markdown outline with:
32
+ 1. A compelling hook/introduction
33
+ 2. 3-5 main sections with bullet points
34
+ 3. A conclusion with call to action
35
+
36
+ Use ## for main sections, ### for subsections, and - for bullet points.
37
+ `;
38
+ }
39
+ async function loadDocument(workspacePath) {
40
+ try {
41
+ const configPath = join(workspacePath, RIOTDOC_STRUCTURE.configFile);
42
+ const content = await readFile(configPath, "utf-8");
43
+ const config = parse(content);
44
+ config.createdAt = new Date(config.createdAt);
45
+ config.updatedAt = new Date(config.updatedAt);
46
+ return {
47
+ config,
48
+ voice: { tone: "", pointOfView: "first", styleNotes: [], avoid: [] },
49
+ objectives: { primaryGoal: "", secondaryGoals: [], keyTakeaways: [] },
50
+ evidence: [],
51
+ drafts: [],
52
+ revisions: [],
53
+ workspacePath
54
+ };
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+ async function loadObjectives(workspacePath) {
60
+ const objectivesPath = join(workspacePath, RIOTDOC_STRUCTURE.objectivesFile);
61
+ try {
62
+ const content = await readFile(objectivesPath, "utf-8");
63
+ return parseObjectivesMarkdown(content);
64
+ } catch {
65
+ return {
66
+ primaryGoal: "",
67
+ secondaryGoals: [],
68
+ keyTakeaways: []
69
+ };
70
+ }
71
+ }
72
+ function parseObjectivesMarkdown(content) {
73
+ const objectives = {
74
+ primaryGoal: "",
75
+ secondaryGoals: [],
76
+ keyTakeaways: []
77
+ };
78
+ const goalMatch = content.match(/##\s*Primary\s+Goal\s*\n+([^\n#]+)/i);
79
+ if (goalMatch) {
80
+ objectives.primaryGoal = goalMatch[1].trim().replace(/^_|_$/g, "");
81
+ }
82
+ const lines = content.split("\n");
83
+ const secondaryLines = [];
84
+ let inSecondary = false;
85
+ for (const line of lines) {
86
+ if (/^##\s*Secondary\s+Goals$/i.test(line)) {
87
+ inSecondary = true;
88
+ continue;
89
+ }
90
+ if (inSecondary && /^##/.test(line)) {
91
+ break;
92
+ }
93
+ if (inSecondary) {
94
+ secondaryLines.push(line);
95
+ }
96
+ }
97
+ if (secondaryLines.length > 0) {
98
+ const sectionContent = secondaryLines.join("\n");
99
+ const goals = sectionContent.matchAll(/^[-*]\s+(.+)$/gm);
100
+ for (const goal of goals) {
101
+ const text = goal[1].trim().replace(/^_|_$/g, "");
102
+ if (text && !text.startsWith("Add")) {
103
+ objectives.secondaryGoals.push(text);
104
+ }
105
+ }
106
+ }
107
+ const takeawayLines = [];
108
+ let inTakeaways = false;
109
+ for (const line of lines) {
110
+ if (/^##\s*Key\s+Takeaways$/i.test(line)) {
111
+ inTakeaways = true;
112
+ continue;
113
+ }
114
+ if (inTakeaways && /^##/.test(line)) {
115
+ break;
116
+ }
117
+ if (inTakeaways) {
118
+ takeawayLines.push(line);
119
+ }
120
+ }
121
+ if (takeawayLines.length > 0) {
122
+ const sectionContent = takeawayLines.join("\n");
123
+ const takeaways = sectionContent.matchAll(/^\d+\.\s+(.+)$/gm);
124
+ for (const takeaway of takeaways) {
125
+ const text = takeaway[1].trim().replace(/^_|_$/g, "");
126
+ if (text && !text.startsWith("Define")) {
127
+ objectives.keyTakeaways.push(text);
128
+ }
129
+ }
130
+ }
131
+ const ctaMatch = content.match(/##\s*Call\s+to\s+Action\s*\n+([^\n#]+)/i);
132
+ if (ctaMatch) {
133
+ const cta = ctaMatch[1].trim().replace(/^_|_$/g, "");
134
+ if (cta && !cta.startsWith("What")) {
135
+ objectives.callToAction = cta;
136
+ }
137
+ }
138
+ const arcMatch = content.match(/##\s*Emotional\s+Arc\s*\n+([^\n#]+)/i);
139
+ if (arcMatch) {
140
+ const arc = arcMatch[1].trim().replace(/^_|_$/g, "");
141
+ if (arc && !arc.startsWith("Describe")) {
142
+ objectives.emotionalArc = arc;
143
+ }
144
+ }
145
+ return objectives;
146
+ }
147
+ export {
148
+ loadObjectives as a,
149
+ buildOutlinePrompt as b,
150
+ loadOutline as c,
151
+ loadDocument as l
152
+ };
153
+ //# sourceMappingURL=loader-Cvfo7vBn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-Cvfo7vBn.js","sources":["../src/outline/generator.ts","../src/workspace/loader.ts","../src/objectives/loader.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { RIOTDOC_STRUCTURE } from \"../constants.js\";\nimport type { DocumentObjectives, VoiceConfig } from \"../types.js\";\n\nexport interface OutlineSection {\n title: string;\n points: string[];\n subsections?: OutlineSection[];\n}\n\nexport interface Outline {\n title: string;\n hook: string;\n sections: OutlineSection[];\n conclusion: string;\n}\n\n/**\n * Load outline from workspace\n */\nexport async function loadOutline(workspacePath: string): Promise<string> {\n const outlinePath = join(workspacePath, RIOTDOC_STRUCTURE.outlineFile);\n return await readFile(outlinePath, \"utf-8\");\n}\n\n/**\n * Save outline to workspace\n */\nexport async function saveOutline(workspacePath: string, content: string): Promise<void> {\n const outlinePath = join(workspacePath, RIOTDOC_STRUCTURE.outlineFile);\n await writeFile(outlinePath, content, \"utf-8\");\n}\n\n/**\n * Build prompt for outline generation\n */\nexport function buildOutlinePrompt(\n objectives: DocumentObjectives,\n voice: VoiceConfig,\n documentType: string\n): string {\n return `Generate an outline for a ${documentType}.\n\n## Objectives\n\nPrimary Goal: ${objectives.primaryGoal}\n\nSecondary Goals:\n${objectives.secondaryGoals.map(g => `- ${g}`).join(\"\\n\")}\n\nKey Takeaways:\n${objectives.keyTakeaways.map(t => `- ${t}`).join(\"\\n\")}\n\n${objectives.emotionalArc ? `Emotional Arc: ${objectives.emotionalArc}` : \"\"}\n\n## Voice & Tone\n\nTone: ${voice.tone}\nPoint of View: ${voice.pointOfView}\n\n## Output Format\n\nCreate a markdown outline with:\n1. A compelling hook/introduction\n2. 3-5 main sections with bullet points\n3. A conclusion with call to action\n\nUse ## for main sections, ### for subsections, and - for bullet points.\n`;\n}\n\n/**\n * Parse outline markdown into structure\n */\nexport function parseOutline(content: string): Outline {\n const lines = content.split(\"\\n\");\n const outline: Outline = {\n title: \"\",\n hook: \"\",\n sections: [],\n conclusion: \"\",\n };\n \n let currentSection: OutlineSection | null = null;\n let inIntro = false;\n let inConclusion = false;\n \n for (const line of lines) {\n // Title\n if (line.startsWith(\"# \")) {\n outline.title = line.slice(2).trim();\n continue;\n }\n \n // Main section\n if (line.startsWith(\"## \")) {\n const title = line.slice(3).trim().toLowerCase();\n if (title.includes(\"intro\") || title.includes(\"hook\")) {\n inIntro = true;\n inConclusion = false;\n currentSection = null;\n } else if (title.includes(\"conclusion\")) {\n inIntro = false;\n inConclusion = true;\n currentSection = null;\n } else {\n inIntro = false;\n inConclusion = false;\n currentSection = { title: line.slice(3).trim(), points: [] };\n outline.sections.push(currentSection);\n }\n continue;\n }\n \n // Bullet point\n if (line.match(/^[-*]\\s+/)) {\n const point = line.replace(/^[-*]\\s+/, \"\").trim();\n if (inIntro) {\n outline.hook += (outline.hook ? \"\\n\" : \"\") + point;\n } else if (inConclusion) {\n outline.conclusion += (outline.conclusion ? \"\\n\" : \"\") + point;\n } else if (currentSection) {\n currentSection.points.push(point);\n }\n }\n }\n \n return outline;\n}\n\n/**\n * Format outline structure as markdown\n */\nexport function formatOutline(outline: Outline): string {\n const parts: string[] = [];\n \n parts.push(`# ${outline.title}\\n`);\n \n if (outline.hook) {\n parts.push(`## Introduction\\n`);\n parts.push(outline.hook.split(\"\\n\").map(p => `- ${p}`).join(\"\\n\"));\n parts.push(\"\");\n }\n \n for (const section of outline.sections) {\n parts.push(`## ${section.title}\\n`);\n parts.push(section.points.map(p => `- ${p}`).join(\"\\n\"));\n parts.push(\"\");\n }\n \n if (outline.conclusion) {\n parts.push(`## Conclusion\\n`);\n parts.push(outline.conclusion.split(\"\\n\").map(p => `- ${p}`).join(\"\\n\"));\n }\n \n return parts.join(\"\\n\");\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parse } from \"yaml\";\nimport { RIOTDOC_STRUCTURE } from \"../constants.js\";\nimport type { RiotDoc, DocumentConfig } from \"../types.js\";\n\n/**\n * Load document from workspace\n */\nexport async function loadDocument(workspacePath: string): Promise<RiotDoc | null> {\n try {\n const configPath = join(workspacePath, RIOTDOC_STRUCTURE.configFile);\n const content = await readFile(configPath, \"utf-8\");\n const config = parse(content) as DocumentConfig;\n \n // Convert date strings to Date objects\n config.createdAt = new Date(config.createdAt);\n config.updatedAt = new Date(config.updatedAt);\n \n return {\n config,\n voice: { tone: \"\", pointOfView: \"first\", styleNotes: [], avoid: [] },\n objectives: { primaryGoal: \"\", secondaryGoals: [], keyTakeaways: [] },\n evidence: [],\n drafts: [],\n revisions: [],\n workspacePath,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Check if path is a RiotDoc workspace\n */\nexport async function isRiotDocWorkspace(path: string): Promise<boolean> {\n try {\n const configPath = join(path, RIOTDOC_STRUCTURE.configFile);\n await stat(configPath);\n return true;\n } catch {\n return false;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { RIOTDOC_STRUCTURE } from \"../constants.js\";\nimport type { DocumentObjectives } from \"../types.js\";\n\n/**\n * Load objectives from workspace\n */\nexport async function loadObjectives(workspacePath: string): Promise<DocumentObjectives> {\n const objectivesPath = join(workspacePath, RIOTDOC_STRUCTURE.objectivesFile);\n \n try {\n const content = await readFile(objectivesPath, \"utf-8\");\n return parseObjectivesMarkdown(content);\n } catch {\n return {\n primaryGoal: \"\",\n secondaryGoals: [],\n keyTakeaways: [],\n };\n }\n}\n\n/**\n * Parse objectives markdown\n */\nfunction parseObjectivesMarkdown(content: string): DocumentObjectives {\n const objectives: DocumentObjectives = {\n primaryGoal: \"\",\n secondaryGoals: [],\n keyTakeaways: [],\n };\n \n // Extract primary goal\n const goalMatch = content.match(/##\\s*Primary\\s+Goal\\s*\\n+([^\\n#]+)/i);\n if (goalMatch) {\n objectives.primaryGoal = goalMatch[1].trim().replace(/^_|_$/g, \"\");\n }\n \n // Extract secondary goals\n // Use line-by-line parsing to avoid polynomial regex\n const lines = content.split('\\n');\n const secondaryLines: string[] = [];\n let inSecondary = false;\n \n for (const line of lines) {\n if (/^##\\s*Secondary\\s+Goals$/i.test(line)) {\n inSecondary = true;\n continue;\n }\n if (inSecondary && /^##/.test(line)) {\n break;\n }\n if (inSecondary) {\n secondaryLines.push(line);\n }\n }\n \n if (secondaryLines.length > 0) {\n const sectionContent = secondaryLines.join('\\n');\n const goals = sectionContent.matchAll(/^[-*]\\s+(.+)$/gm);\n for (const goal of goals) {\n const text = goal[1].trim().replace(/^_|_$/g, \"\");\n if (text && !text.startsWith(\"Add\")) {\n objectives.secondaryGoals.push(text);\n }\n }\n }\n \n // Extract key takeaways\n // Use line-by-line parsing to avoid polynomial regex\n const takeawayLines: string[] = [];\n let inTakeaways = false;\n \n for (const line of lines) {\n if (/^##\\s*Key\\s+Takeaways$/i.test(line)) {\n inTakeaways = true;\n continue;\n }\n if (inTakeaways && /^##/.test(line)) {\n break;\n }\n if (inTakeaways) {\n takeawayLines.push(line);\n }\n }\n \n if (takeawayLines.length > 0) {\n const sectionContent = takeawayLines.join('\\n');\n const takeaways = sectionContent.matchAll(/^\\d+\\.\\s+(.+)$/gm);\n for (const takeaway of takeaways) {\n const text = takeaway[1].trim().replace(/^_|_$/g, \"\");\n if (text && !text.startsWith(\"Define\")) {\n objectives.keyTakeaways.push(text);\n }\n }\n }\n \n // Extract call to action\n const ctaMatch = content.match(/##\\s*Call\\s+to\\s+Action\\s*\\n+([^\\n#]+)/i);\n if (ctaMatch) {\n const cta = ctaMatch[1].trim().replace(/^_|_$/g, \"\");\n if (cta && !cta.startsWith(\"What\")) {\n objectives.callToAction = cta;\n }\n }\n \n // Extract emotional arc\n const arcMatch = content.match(/##\\s*Emotional\\s+Arc\\s*\\n+([^\\n#]+)/i);\n if (arcMatch) {\n const arc = arcMatch[1].trim().replace(/^_|_$/g, \"\");\n if (arc && !arc.startsWith(\"Describe\")) {\n objectives.emotionalArc = arc;\n }\n }\n \n return objectives;\n}\n"],"names":[],"mappings":"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"}