vralphy 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +512 -0
  2. package/bin/vralphy.js +3 -0
  3. package/dist/commands/build.d.ts +9 -0
  4. package/dist/commands/build.d.ts.map +1 -0
  5. package/dist/commands/build.js +176 -0
  6. package/dist/commands/build.js.map +1 -0
  7. package/dist/commands/cleanup.d.ts +19 -0
  8. package/dist/commands/cleanup.d.ts.map +1 -0
  9. package/dist/commands/cleanup.js +159 -0
  10. package/dist/commands/cleanup.js.map +1 -0
  11. package/dist/commands/cleanup.test.d.ts +2 -0
  12. package/dist/commands/cleanup.test.d.ts.map +1 -0
  13. package/dist/commands/cleanup.test.js +389 -0
  14. package/dist/commands/cleanup.test.js.map +1 -0
  15. package/dist/commands/init.d.ts +13 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +120 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/plan.d.ts +9 -0
  20. package/dist/commands/plan.d.ts.map +1 -0
  21. package/dist/commands/plan.js +147 -0
  22. package/dist/commands/plan.js.map +1 -0
  23. package/dist/commands/spec.d.ts +9 -0
  24. package/dist/commands/spec.d.ts.map +1 -0
  25. package/dist/commands/spec.js +111 -0
  26. package/dist/commands/spec.js.map +1 -0
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +251 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/lib/agents.d.ts +32 -0
  32. package/dist/lib/agents.d.ts.map +1 -0
  33. package/dist/lib/agents.js +96 -0
  34. package/dist/lib/agents.js.map +1 -0
  35. package/dist/lib/config.d.ts +54 -0
  36. package/dist/lib/config.d.ts.map +1 -0
  37. package/dist/lib/config.js +199 -0
  38. package/dist/lib/config.js.map +1 -0
  39. package/dist/lib/config.test.d.ts +2 -0
  40. package/dist/lib/config.test.d.ts.map +1 -0
  41. package/dist/lib/config.test.js +57 -0
  42. package/dist/lib/config.test.js.map +1 -0
  43. package/dist/lib/context.d.ts +29 -0
  44. package/dist/lib/context.d.ts.map +1 -0
  45. package/dist/lib/context.js +175 -0
  46. package/dist/lib/context.js.map +1 -0
  47. package/dist/lib/engines/base.d.ts +75 -0
  48. package/dist/lib/engines/base.d.ts.map +1 -0
  49. package/dist/lib/engines/base.js +62 -0
  50. package/dist/lib/engines/base.js.map +1 -0
  51. package/dist/lib/engines/base.test.d.ts +2 -0
  52. package/dist/lib/engines/base.test.d.ts.map +1 -0
  53. package/dist/lib/engines/base.test.js +28 -0
  54. package/dist/lib/engines/base.test.js.map +1 -0
  55. package/dist/lib/engines/claude.d.ts +12 -0
  56. package/dist/lib/engines/claude.d.ts.map +1 -0
  57. package/dist/lib/engines/claude.js +156 -0
  58. package/dist/lib/engines/claude.js.map +1 -0
  59. package/dist/lib/engines/codex.d.ts +28 -0
  60. package/dist/lib/engines/codex.d.ts.map +1 -0
  61. package/dist/lib/engines/codex.js +177 -0
  62. package/dist/lib/engines/codex.js.map +1 -0
  63. package/dist/lib/engines/index.d.ts +19 -0
  64. package/dist/lib/engines/index.d.ts.map +1 -0
  65. package/dist/lib/engines/index.js +40 -0
  66. package/dist/lib/engines/index.js.map +1 -0
  67. package/dist/lib/engines/opencode.d.ts +14 -0
  68. package/dist/lib/engines/opencode.d.ts.map +1 -0
  69. package/dist/lib/engines/opencode.js +127 -0
  70. package/dist/lib/engines/opencode.js.map +1 -0
  71. package/dist/lib/events/index.d.ts +6 -0
  72. package/dist/lib/events/index.d.ts.map +1 -0
  73. package/dist/lib/events/index.js +5 -0
  74. package/dist/lib/events/index.js.map +1 -0
  75. package/dist/lib/events/types.d.ts +93 -0
  76. package/dist/lib/events/types.d.ts.map +1 -0
  77. package/dist/lib/events/types.js +7 -0
  78. package/dist/lib/events/types.js.map +1 -0
  79. package/dist/lib/events/writer.d.ts +68 -0
  80. package/dist/lib/events/writer.d.ts.map +1 -0
  81. package/dist/lib/events/writer.js +178 -0
  82. package/dist/lib/events/writer.js.map +1 -0
  83. package/dist/lib/events.d.ts +33 -0
  84. package/dist/lib/events.d.ts.map +1 -0
  85. package/dist/lib/events.js +81 -0
  86. package/dist/lib/events.js.map +1 -0
  87. package/dist/lib/events.test.d.ts +2 -0
  88. package/dist/lib/events.test.d.ts.map +1 -0
  89. package/dist/lib/events.test.js +123 -0
  90. package/dist/lib/events.test.js.map +1 -0
  91. package/dist/lib/file-injection.d.ts +32 -0
  92. package/dist/lib/file-injection.d.ts.map +1 -0
  93. package/dist/lib/file-injection.js +138 -0
  94. package/dist/lib/file-injection.js.map +1 -0
  95. package/dist/lib/file-injection.test.d.ts +2 -0
  96. package/dist/lib/file-injection.test.d.ts.map +1 -0
  97. package/dist/lib/file-injection.test.js +508 -0
  98. package/dist/lib/file-injection.test.js.map +1 -0
  99. package/dist/lib/init.d.ts +27 -0
  100. package/dist/lib/init.d.ts.map +1 -0
  101. package/dist/lib/init.js +363 -0
  102. package/dist/lib/init.js.map +1 -0
  103. package/dist/lib/init.test.d.ts +2 -0
  104. package/dist/lib/init.test.d.ts.map +1 -0
  105. package/dist/lib/init.test.js +315 -0
  106. package/dist/lib/init.test.js.map +1 -0
  107. package/dist/lib/plan.d.ts +11 -0
  108. package/dist/lib/plan.d.ts.map +1 -0
  109. package/dist/lib/plan.js +22 -0
  110. package/dist/lib/plan.js.map +1 -0
  111. package/dist/lib/plan.test.d.ts +2 -0
  112. package/dist/lib/plan.test.d.ts.map +1 -0
  113. package/dist/lib/plan.test.js +70 -0
  114. package/dist/lib/plan.test.js.map +1 -0
  115. package/dist/lib/prompts/codex.d.ts +18 -0
  116. package/dist/lib/prompts/codex.d.ts.map +1 -0
  117. package/dist/lib/prompts/codex.js +82 -0
  118. package/dist/lib/prompts/codex.js.map +1 -0
  119. package/dist/lib/prompts/opencode.d.ts +16 -0
  120. package/dist/lib/prompts/opencode.d.ts.map +1 -0
  121. package/dist/lib/prompts/opencode.js +71 -0
  122. package/dist/lib/prompts/opencode.js.map +1 -0
  123. package/dist/lib/prompts.d.ts +57 -0
  124. package/dist/lib/prompts.d.ts.map +1 -0
  125. package/dist/lib/prompts.js +255 -0
  126. package/dist/lib/prompts.js.map +1 -0
  127. package/dist/lib/prompts.test.d.ts +2 -0
  128. package/dist/lib/prompts.test.d.ts.map +1 -0
  129. package/dist/lib/prompts.test.js +128 -0
  130. package/dist/lib/prompts.test.js.map +1 -0
  131. package/dist/lib/skills.d.ts +36 -0
  132. package/dist/lib/skills.d.ts.map +1 -0
  133. package/dist/lib/skills.js +132 -0
  134. package/dist/lib/skills.js.map +1 -0
  135. package/dist/lib/slack.d.ts +43 -0
  136. package/dist/lib/slack.d.ts.map +1 -0
  137. package/dist/lib/slack.js +130 -0
  138. package/dist/lib/slack.js.map +1 -0
  139. package/dist/lib/slack.test.d.ts +2 -0
  140. package/dist/lib/slack.test.d.ts.map +1 -0
  141. package/dist/lib/slack.test.js +74 -0
  142. package/dist/lib/slack.test.js.map +1 -0
  143. package/dist/lib/templates/injections.d.ts +18 -0
  144. package/dist/lib/templates/injections.d.ts.map +1 -0
  145. package/dist/lib/templates/injections.js +32 -0
  146. package/dist/lib/templates/injections.js.map +1 -0
  147. package/dist/lib/templates/readme.d.ts +6 -0
  148. package/dist/lib/templates/readme.d.ts.map +1 -0
  149. package/dist/lib/templates/readme.js +168 -0
  150. package/dist/lib/templates/readme.js.map +1 -0
  151. package/docs/COMMANDS.md +664 -0
  152. package/docs/DESIGN.md +537 -0
  153. package/docs/EXAMPLES.md +812 -0
  154. package/docs/METHODOLOGY.md +390 -0
  155. package/docs/README.md +110 -0
  156. package/docs/WORKFLOWS.md +808 -0
  157. package/llms.txt +104 -0
  158. package/package.json +58 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * NDJSON Event Types for vralphy
3
+ *
4
+ * These events can be consumed via: tail -f .vralphy/events.ndjson | jq .
5
+ */
6
+ import { EngineName } from '../engines/index.js';
7
+ /**
8
+ * Common fields for all events
9
+ */
10
+ export interface BaseEvent {
11
+ timestamp: string;
12
+ sessionId: string;
13
+ engine: EngineName;
14
+ }
15
+ /**
16
+ * Iteration lifecycle start event
17
+ */
18
+ export interface IterationStartEvent extends BaseEvent {
19
+ type: 'iteration_start';
20
+ iteration: number;
21
+ command: 'build' | 'plan' | 'spec';
22
+ }
23
+ /**
24
+ * Iteration lifecycle end event
25
+ */
26
+ export interface IterationEndEvent extends BaseEvent {
27
+ type: 'iteration_end';
28
+ iteration: number;
29
+ durationMs: number;
30
+ success: boolean;
31
+ error?: string;
32
+ }
33
+ /**
34
+ * Tool usage event (Claude only - has structured data)
35
+ */
36
+ export interface ToolEvent extends BaseEvent {
37
+ type: 'tool';
38
+ tool: string;
39
+ params: Record<string, unknown>;
40
+ }
41
+ /**
42
+ * File operation event (derived from tool events)
43
+ */
44
+ export interface FileEvent extends BaseEvent {
45
+ type: 'file';
46
+ operation: 'read' | 'write' | 'edit' | 'delete';
47
+ path: string;
48
+ }
49
+ /**
50
+ * State change event (e.g., IMPLEMENTATION_PLAN.md updates)
51
+ */
52
+ export interface StateChangeEvent extends BaseEvent {
53
+ type: 'state_change';
54
+ kind: 'task_status' | 'plan_update' | 'spec_update';
55
+ file: string;
56
+ description?: string;
57
+ }
58
+ /**
59
+ * Error event
60
+ */
61
+ export interface ErrorEvent extends BaseEvent {
62
+ type: 'error';
63
+ message: string;
64
+ code?: string;
65
+ iteration?: number;
66
+ }
67
+ /**
68
+ * Session start event
69
+ */
70
+ export interface SessionStartEvent extends BaseEvent {
71
+ type: 'session_start';
72
+ command: 'build' | 'plan' | 'spec';
73
+ planningModel: string;
74
+ executorModel: string;
75
+ }
76
+ /**
77
+ * Session end event
78
+ */
79
+ export interface SessionEndEvent extends BaseEvent {
80
+ type: 'session_end';
81
+ totalIterations: number;
82
+ totalDurationMs: number;
83
+ success: boolean;
84
+ }
85
+ /**
86
+ * Union type of all events
87
+ */
88
+ export type VralphyEvent = IterationStartEvent | IterationEndEvent | ToolEvent | FileEvent | StateChangeEvent | ErrorEvent | SessionStartEvent | SessionEndEvent;
89
+ /**
90
+ * Event types for filtering
91
+ */
92
+ export type EventType = VralphyEvent['type'];
93
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/events/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,SAAS;IACpD,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,aAAa,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,IAAI,EAAE,aAAa,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB,mBAAmB,GACnB,iBAAiB,GACjB,SAAS,GACT,SAAS,GACT,gBAAgB,GAChB,UAAU,GACV,iBAAiB,GACjB,eAAe,CAAC;AAEpB;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * NDJSON Event Types for vralphy
3
+ *
4
+ * These events can be consumed via: tail -f .vralphy/events.ndjson | jq .
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/events/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * EventWriter - Non-blocking NDJSON event writer
3
+ *
4
+ * Appends events to .vralphy/events.ndjson for external consumption.
5
+ * Writes are fire-and-forget to never block or fail the main execution.
6
+ */
7
+ import { EngineName } from '../engines/index.js';
8
+ export declare class EventWriter {
9
+ private readonly engine;
10
+ private readonly sessionId;
11
+ private readonly eventsPath;
12
+ private readonly enabled;
13
+ private initialized;
14
+ constructor(engine: EngineName, enabled?: boolean);
15
+ /**
16
+ * Get the session ID for this writer
17
+ */
18
+ getSessionId(): string;
19
+ /**
20
+ * Ensure the events directory exists
21
+ */
22
+ private ensureDir;
23
+ /**
24
+ * Write an event to the NDJSON file (fire-and-forget)
25
+ */
26
+ private write;
27
+ /**
28
+ * Record session start
29
+ */
30
+ sessionStart(command: 'build' | 'plan' | 'spec', planningModel: string, executorModel: string): Promise<void>;
31
+ /**
32
+ * Record session end
33
+ */
34
+ sessionEnd(totalIterations: number, totalDurationMs: number, success: boolean): Promise<void>;
35
+ /**
36
+ * Record iteration start
37
+ */
38
+ iterationStart(iteration: number, command: 'build' | 'plan' | 'spec'): Promise<void>;
39
+ /**
40
+ * Record iteration end
41
+ */
42
+ iterationEnd(iteration: number, durationMs: number, success: boolean, error?: string): Promise<void>;
43
+ /**
44
+ * Record tool usage
45
+ */
46
+ tool(tool: string, params: Record<string, unknown>): Promise<void>;
47
+ /**
48
+ * Record file operation
49
+ */
50
+ file(operation: 'read' | 'write' | 'edit' | 'delete', path: string): Promise<void>;
51
+ /**
52
+ * Record state change
53
+ */
54
+ stateChange(kind: 'task_status' | 'plan_update' | 'spec_update', file: string, description?: string): Promise<void>;
55
+ /**
56
+ * Record error
57
+ */
58
+ error(message: string, code?: string, iteration?: number): Promise<void>;
59
+ /**
60
+ * Detect file operation from tool name
61
+ */
62
+ static getFileOperation(toolName: string): 'read' | 'write' | 'edit' | 'delete' | null;
63
+ /**
64
+ * Check if a file path indicates an IMPLEMENTATION_PLAN.md change
65
+ */
66
+ static isImplementationPlan(filePath: string | unknown): boolean;
67
+ }
68
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../../src/lib/events/writer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAgBjD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,WAAW,CAAkB;gBAEzB,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,OAAc;IAOvD;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;YACW,SAAS;IAavB;;OAEG;YACW,KAAK;IAoBnB;;OAEG;IACG,YAAY,CAChB,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAClC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACG,UAAU,CAAC,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IASnG;;OAEG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1F;;OAEG;IACG,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxE;;OAEG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxF;;OAEG;IACG,WAAW,CACf,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,aAAa,EACnD,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9E;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI;IAatF;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO;CAIjE"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * EventWriter - Non-blocking NDJSON event writer
3
+ *
4
+ * Appends events to .vralphy/events.ndjson for external consumption.
5
+ * Writes are fire-and-forget to never block or fail the main execution.
6
+ */
7
+ import { appendFile, mkdir } from 'fs/promises';
8
+ import { existsSync } from 'fs';
9
+ import { join } from 'path';
10
+ import { randomUUID } from 'crypto';
11
+ const EVENTS_DIR = '.vralphy';
12
+ const EVENTS_FILE = 'events.ndjson';
13
+ export class EventWriter {
14
+ engine;
15
+ sessionId;
16
+ eventsPath;
17
+ enabled;
18
+ initialized = false;
19
+ constructor(engine, enabled = true) {
20
+ this.engine = engine;
21
+ this.sessionId = randomUUID();
22
+ this.eventsPath = join(EVENTS_DIR, EVENTS_FILE);
23
+ this.enabled = enabled;
24
+ }
25
+ /**
26
+ * Get the session ID for this writer
27
+ */
28
+ getSessionId() {
29
+ return this.sessionId;
30
+ }
31
+ /**
32
+ * Ensure the events directory exists
33
+ */
34
+ async ensureDir() {
35
+ if (this.initialized)
36
+ return;
37
+ try {
38
+ if (!existsSync(EVENTS_DIR)) {
39
+ await mkdir(EVENTS_DIR, { recursive: true });
40
+ }
41
+ this.initialized = true;
42
+ }
43
+ catch {
44
+ // Silently fail - non-blocking
45
+ }
46
+ }
47
+ /**
48
+ * Write an event to the NDJSON file (fire-and-forget)
49
+ */
50
+ async write(event) {
51
+ if (!this.enabled)
52
+ return;
53
+ try {
54
+ await this.ensureDir();
55
+ const fullEvent = {
56
+ ...event,
57
+ timestamp: new Date().toISOString(),
58
+ sessionId: this.sessionId,
59
+ engine: this.engine,
60
+ };
61
+ const line = JSON.stringify(fullEvent) + '\n';
62
+ await appendFile(this.eventsPath, line);
63
+ }
64
+ catch {
65
+ // Silently fail - non-blocking, never interrupts execution
66
+ }
67
+ }
68
+ /**
69
+ * Record session start
70
+ */
71
+ async sessionStart(command, planningModel, executorModel) {
72
+ await this.write({
73
+ type: 'session_start',
74
+ command,
75
+ planningModel,
76
+ executorModel,
77
+ });
78
+ }
79
+ /**
80
+ * Record session end
81
+ */
82
+ async sessionEnd(totalIterations, totalDurationMs, success) {
83
+ await this.write({
84
+ type: 'session_end',
85
+ totalIterations,
86
+ totalDurationMs,
87
+ success,
88
+ });
89
+ }
90
+ /**
91
+ * Record iteration start
92
+ */
93
+ async iterationStart(iteration, command) {
94
+ await this.write({
95
+ type: 'iteration_start',
96
+ iteration,
97
+ command,
98
+ });
99
+ }
100
+ /**
101
+ * Record iteration end
102
+ */
103
+ async iterationEnd(iteration, durationMs, success, error) {
104
+ await this.write({
105
+ type: 'iteration_end',
106
+ iteration,
107
+ durationMs,
108
+ success,
109
+ ...(error && { error }),
110
+ });
111
+ }
112
+ /**
113
+ * Record tool usage
114
+ */
115
+ async tool(tool, params) {
116
+ await this.write({
117
+ type: 'tool',
118
+ tool,
119
+ params,
120
+ });
121
+ }
122
+ /**
123
+ * Record file operation
124
+ */
125
+ async file(operation, path) {
126
+ await this.write({
127
+ type: 'file',
128
+ operation,
129
+ path,
130
+ });
131
+ }
132
+ /**
133
+ * Record state change
134
+ */
135
+ async stateChange(kind, file, description) {
136
+ await this.write({
137
+ type: 'state_change',
138
+ kind,
139
+ file,
140
+ ...(description && { description }),
141
+ });
142
+ }
143
+ /**
144
+ * Record error
145
+ */
146
+ async error(message, code, iteration) {
147
+ await this.write({
148
+ type: 'error',
149
+ message,
150
+ ...(code && { code }),
151
+ ...(iteration !== undefined && { iteration }),
152
+ });
153
+ }
154
+ /**
155
+ * Detect file operation from tool name
156
+ */
157
+ static getFileOperation(toolName) {
158
+ switch (toolName) {
159
+ case 'Read':
160
+ return 'read';
161
+ case 'Write':
162
+ return 'write';
163
+ case 'Edit':
164
+ return 'edit';
165
+ default:
166
+ return null;
167
+ }
168
+ }
169
+ /**
170
+ * Check if a file path indicates an IMPLEMENTATION_PLAN.md change
171
+ */
172
+ static isImplementationPlan(filePath) {
173
+ if (typeof filePath !== 'string')
174
+ return false;
175
+ return filePath.includes('IMPLEMENTATION_PLAN.md');
176
+ }
177
+ }
178
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/lib/events/writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export type EventType = 'session.start' | 'session.end' | 'iteration.start' | 'iteration.end' | 'iteration.error' | 'plan.completed';
2
+ export interface VralphyEvent {
3
+ type: EventType;
4
+ timestamp: string;
5
+ sessionId: string;
6
+ project: string;
7
+ [key: string]: unknown;
8
+ }
9
+ interface EventLoggerConfig {
10
+ maxFileSizeBytes: number;
11
+ maxRotatedFiles: number;
12
+ }
13
+ export declare function generateSessionId(): string;
14
+ export declare class EventLogger {
15
+ private logPath;
16
+ private sessionId;
17
+ private project;
18
+ private config;
19
+ private initialized;
20
+ constructor(options: {
21
+ logDir?: string;
22
+ sessionId: string;
23
+ project: string;
24
+ config?: Partial<EventLoggerConfig>;
25
+ });
26
+ log(event: Omit<VralphyEvent, 'timestamp' | 'sessionId' | 'project'>): void;
27
+ private ensureInitialized;
28
+ private maybeRotate;
29
+ }
30
+ export declare function initEventLogger(sessionId: string, project: string): void;
31
+ export declare function logEvent(event: Omit<VralphyEvent, 'timestamp' | 'sessionId' | 'project'>): void;
32
+ export {};
33
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/lib/events.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,aAAa,GACb,iBAAiB,GACjB,eAAe,GACf,iBAAiB,GACjB,gBAAgB,CAAC;AAErB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,iBAAiB;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAOD,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;KACrC;IAOD,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC,GAAG,IAAI;IAkB3E,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,WAAW;CAoBpB;AAKD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAExE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC,GAAG,IAAI,CAE/F"}
@@ -0,0 +1,81 @@
1
+ import { appendFileSync, existsSync, mkdirSync, statSync, renameSync, unlinkSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ const DEFAULT_CONFIG = {
4
+ maxFileSizeBytes: 5 * 1024 * 1024, // 5MB
5
+ maxRotatedFiles: 1,
6
+ };
7
+ export function generateSessionId() {
8
+ const timestamp = Date.now().toString(36);
9
+ const random = Math.random().toString(36).substring(2, 8);
10
+ return `${timestamp}-${random}`;
11
+ }
12
+ export class EventLogger {
13
+ logPath;
14
+ sessionId;
15
+ project;
16
+ config;
17
+ initialized = false;
18
+ constructor(options) {
19
+ this.logPath = join(options.logDir ?? '.vralphy/logs', 'events.jsonl');
20
+ this.sessionId = options.sessionId;
21
+ this.project = options.project;
22
+ this.config = { ...DEFAULT_CONFIG, ...options.config };
23
+ }
24
+ log(event) {
25
+ try {
26
+ this.ensureInitialized();
27
+ this.maybeRotate();
28
+ const fullEvent = {
29
+ timestamp: new Date().toISOString(),
30
+ sessionId: this.sessionId,
31
+ project: this.project,
32
+ ...event,
33
+ };
34
+ appendFileSync(this.logPath, JSON.stringify(fullEvent) + '\n');
35
+ }
36
+ catch {
37
+ // Silent failure - logging should never break the CLI
38
+ }
39
+ }
40
+ ensureInitialized() {
41
+ if (this.initialized)
42
+ return;
43
+ const dir = dirname(this.logPath);
44
+ if (!existsSync(dir)) {
45
+ mkdirSync(dir, { recursive: true });
46
+ }
47
+ this.initialized = true;
48
+ }
49
+ maybeRotate() {
50
+ try {
51
+ if (!existsSync(this.logPath))
52
+ return;
53
+ const stats = statSync(this.logPath);
54
+ if (stats.size < this.config.maxFileSizeBytes)
55
+ return;
56
+ // Delete oldest, shift others
57
+ for (let i = this.config.maxRotatedFiles; i >= 1; i--) {
58
+ const path = `${this.logPath}.${i}`;
59
+ if (i === this.config.maxRotatedFiles && existsSync(path)) {
60
+ unlinkSync(path);
61
+ }
62
+ else if (existsSync(path)) {
63
+ renameSync(path, `${this.logPath}.${i + 1}`);
64
+ }
65
+ }
66
+ renameSync(this.logPath, `${this.logPath}.1`);
67
+ }
68
+ catch {
69
+ // Ignore rotation errors
70
+ }
71
+ }
72
+ }
73
+ // Global logger instance
74
+ let logger = null;
75
+ export function initEventLogger(sessionId, project) {
76
+ logger = new EventLogger({ sessionId, project });
77
+ }
78
+ export function logEvent(event) {
79
+ logger?.log(event);
80
+ }
81
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/lib/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=events.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.test.d.ts","sourceRoot":"","sources":["../../src/lib/events.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,123 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdirSync, rmSync, readFileSync, writeFileSync, existsSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { generateSessionId, EventLogger } from './events.js';
5
+ const TEST_DIR = '.vralphy-test-events';
6
+ const LOG_PATH = join(TEST_DIR, 'events.jsonl');
7
+ describe('generateSessionId', () => {
8
+ it('returns unique IDs', () => {
9
+ const ids = new Set();
10
+ for (let i = 0; i < 100; i++) {
11
+ ids.add(generateSessionId());
12
+ }
13
+ expect(ids.size).toBe(100);
14
+ });
15
+ it('returns string with timestamp and random parts', () => {
16
+ const id = generateSessionId();
17
+ expect(id).toMatch(/^[a-z0-9]+-[a-z0-9]+$/);
18
+ });
19
+ });
20
+ describe('EventLogger', () => {
21
+ beforeEach(() => {
22
+ rmSync(TEST_DIR, { recursive: true, force: true });
23
+ });
24
+ afterEach(() => {
25
+ rmSync(TEST_DIR, { recursive: true, force: true });
26
+ });
27
+ it('creates directory and file on first log', () => {
28
+ const logger = new EventLogger({
29
+ logDir: TEST_DIR,
30
+ sessionId: 'test-session',
31
+ project: 'test-project',
32
+ });
33
+ logger.log({ type: 'session.start' });
34
+ expect(existsSync(LOG_PATH)).toBe(true);
35
+ });
36
+ it('logs valid JSON lines', () => {
37
+ const logger = new EventLogger({
38
+ logDir: TEST_DIR,
39
+ sessionId: 'test-session',
40
+ project: 'test-project',
41
+ });
42
+ logger.log({ type: 'session.start', command: 'build' });
43
+ logger.log({ type: 'iteration.end', iteration: 1 });
44
+ const content = readFileSync(LOG_PATH, 'utf-8');
45
+ const lines = content.trim().split('\n');
46
+ expect(lines.length).toBe(2);
47
+ const event1 = JSON.parse(lines[0]);
48
+ expect(event1.type).toBe('session.start');
49
+ expect(event1.sessionId).toBe('test-session');
50
+ expect(event1.project).toBe('test-project');
51
+ expect(event1.command).toBe('build');
52
+ expect(event1.timestamp).toBeDefined();
53
+ const event2 = JSON.parse(lines[1]);
54
+ expect(event2.type).toBe('iteration.end');
55
+ expect(event2.iteration).toBe(1);
56
+ });
57
+ it('includes all event properties', () => {
58
+ const logger = new EventLogger({
59
+ logDir: TEST_DIR,
60
+ sessionId: 'sess-123',
61
+ project: 'my-project',
62
+ });
63
+ logger.log({
64
+ type: 'session.start',
65
+ engine: 'claude',
66
+ maxIterations: 5,
67
+ nested: { key: 'value' },
68
+ });
69
+ const content = readFileSync(LOG_PATH, 'utf-8');
70
+ const event = JSON.parse(content.trim());
71
+ expect(event.type).toBe('session.start');
72
+ expect(event.sessionId).toBe('sess-123');
73
+ expect(event.project).toBe('my-project');
74
+ expect(event.engine).toBe('claude');
75
+ expect(event.maxIterations).toBe(5);
76
+ expect(event.nested).toEqual({ key: 'value' });
77
+ });
78
+ it('rotates at threshold', () => {
79
+ mkdirSync(TEST_DIR, { recursive: true });
80
+ // Create a file slightly under the threshold
81
+ const threshold = 1024; // 1KB for testing
82
+ const content = 'x'.repeat(threshold);
83
+ writeFileSync(LOG_PATH, content);
84
+ const logger = new EventLogger({
85
+ logDir: TEST_DIR,
86
+ sessionId: 'test',
87
+ project: 'test',
88
+ config: { maxFileSizeBytes: threshold, maxRotatedFiles: 1 },
89
+ });
90
+ logger.log({ type: 'session.start' });
91
+ expect(existsSync(`${LOG_PATH}.1`)).toBe(true);
92
+ expect(readFileSync(`${LOG_PATH}.1`, 'utf-8')).toBe(content);
93
+ const newContent = readFileSync(LOG_PATH, 'utf-8');
94
+ expect(newContent).toContain('session.start');
95
+ });
96
+ it('deletes oldest rotation when max reached', () => {
97
+ mkdirSync(TEST_DIR, { recursive: true });
98
+ const threshold = 100;
99
+ // Pre-create rotation files
100
+ writeFileSync(LOG_PATH, 'x'.repeat(threshold + 1));
101
+ writeFileSync(`${LOG_PATH}.1`, 'old-backup');
102
+ const logger = new EventLogger({
103
+ logDir: TEST_DIR,
104
+ sessionId: 'test',
105
+ project: 'test',
106
+ config: { maxFileSizeBytes: threshold, maxRotatedFiles: 1 },
107
+ });
108
+ logger.log({ type: 'session.start' });
109
+ // Old .1 should be gone, current should become .1
110
+ expect(readFileSync(`${LOG_PATH}.1`, 'utf-8')).toBe('x'.repeat(threshold + 1));
111
+ expect(existsSync(`${LOG_PATH}.2`)).toBe(false);
112
+ });
113
+ it('silently handles errors', () => {
114
+ const logger = new EventLogger({
115
+ logDir: '/nonexistent/path/that/should/fail',
116
+ sessionId: 'test',
117
+ project: 'test',
118
+ });
119
+ // Should not throw
120
+ expect(() => logger.log({ type: 'session.start' })).not.toThrow();
121
+ });
122
+ });
123
+ //# sourceMappingURL=events.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.test.js","sourceRoot":"","sources":["../../src/lib/events.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Utilities for marker-based content injection and removal in files
3
+ */
4
+ export interface InjectionMarkers {
5
+ start: string;
6
+ end: string;
7
+ }
8
+ export interface InjectionResult {
9
+ success: boolean;
10
+ action: 'injected' | 'replaced' | 'removed' | 'skipped' | 'error';
11
+ message?: string;
12
+ }
13
+ /**
14
+ * Check if content already has injection markers
15
+ */
16
+ export declare function hasMarkers(content: string, markers: InjectionMarkers): boolean;
17
+ /**
18
+ * Check if content has incomplete markers (only start or end)
19
+ */
20
+ export declare function hasIncompleteMarkers(content: string, markers: InjectionMarkers): boolean;
21
+ /**
22
+ * Inject content into a file between markers
23
+ * If markers exist, replaces content between them
24
+ * If markers don't exist, appends to end of file
25
+ */
26
+ export declare function injectContent(filePath: string, content: string, markers: InjectionMarkers): Promise<InjectionResult>;
27
+ /**
28
+ * Remove injected content from a file
29
+ * Removes everything between and including the markers
30
+ */
31
+ export declare function removeInjectedContent(filePath: string, markers: InjectionMarkers): Promise<InjectionResult>;
32
+ //# sourceMappingURL=file-injection.d.ts.map