reviewflow 3.28.0 → 3.29.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 (123) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/dashboard/index.html +61 -0
  3. package/dist/dashboard/modules/emberChat.d.ts +77 -0
  4. package/dist/dashboard/modules/emberChat.d.ts.map +1 -0
  5. package/dist/dashboard/modules/emberChat.js +175 -0
  6. package/dist/dashboard/modules/emberChat.js.map +1 -0
  7. package/dist/dashboard/styles.css +85 -0
  8. package/dist/main/routes.d.ts.map +1 -1
  9. package/dist/main/routes.js +32 -0
  10. package/dist/main/routes.js.map +1 -1
  11. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.guard.d.ts +4 -0
  12. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.guard.d.ts.map +1 -0
  13. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.guard.js +4 -0
  14. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.guard.js.map +1 -0
  15. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.schema.d.ts +6 -0
  16. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.schema.d.ts.map +1 -0
  17. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.schema.js +5 -0
  18. package/dist/modules/ember-chat/entities/emberMessage/emberMessage.schema.js.map +1 -0
  19. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts +7 -0
  20. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts.map +1 -0
  21. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js +3 -0
  22. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js.map +1 -0
  23. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts +13 -0
  24. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts.map +1 -0
  25. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js +35 -0
  26. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js.map +1 -0
  27. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts +26 -0
  28. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts.map +1 -0
  29. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js +2 -0
  30. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js.map +1 -0
  31. package/dist/modules/ember-chat/entities/emberTool/emberTool.gateway.d.ts +11 -0
  32. package/dist/modules/ember-chat/entities/emberTool/emberTool.gateway.d.ts.map +1 -0
  33. package/dist/modules/ember-chat/entities/emberTool/emberTool.gateway.js +2 -0
  34. package/dist/modules/ember-chat/entities/emberTool/emberTool.gateway.js.map +1 -0
  35. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts +15 -0
  36. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts.map +1 -0
  37. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js +61 -0
  38. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js.map +1 -0
  39. package/dist/modules/ember-chat/interface-adapters/gateways/emberReadData.composite.gateway.d.ts +24 -0
  40. package/dist/modules/ember-chat/interface-adapters/gateways/emberReadData.composite.gateway.d.ts.map +1 -0
  41. package/dist/modules/ember-chat/interface-adapters/gateways/emberReadData.composite.gateway.js +19 -0
  42. package/dist/modules/ember-chat/interface-adapters/gateways/emberReadData.composite.gateway.js.map +1 -0
  43. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts +13 -0
  44. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts.map +1 -0
  45. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js +130 -0
  46. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js.map +1 -0
  47. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts +18 -0
  48. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts.map +1 -0
  49. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js +33 -0
  50. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js.map +1 -0
  51. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts +20 -0
  52. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts.map +1 -0
  53. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.js +28 -0
  54. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.js.map +1 -0
  55. package/dist/modules/ember-chat/services/emberSystemPrompt.d.ts +12 -0
  56. package/dist/modules/ember-chat/services/emberSystemPrompt.d.ts.map +1 -0
  57. package/dist/modules/ember-chat/services/emberSystemPrompt.js +29 -0
  58. package/dist/modules/ember-chat/services/emberSystemPrompt.js.map +1 -0
  59. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts +23 -0
  60. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts.map +1 -0
  61. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js +23 -0
  62. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js.map +1 -0
  63. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts +36 -0
  64. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts.map +1 -0
  65. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js +59 -0
  66. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js.map +1 -0
  67. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts +2 -0
  68. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts.map +1 -0
  69. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js +124 -0
  70. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js.map +1 -0
  71. package/dist/tests/factories/emberMessage.factory.d.ts +5 -0
  72. package/dist/tests/factories/emberMessage.factory.d.ts.map +1 -0
  73. package/dist/tests/factories/emberMessage.factory.js +9 -0
  74. package/dist/tests/factories/emberMessage.factory.js.map +1 -0
  75. package/dist/tests/stubs/emberReadData.stub.d.ts +20 -0
  76. package/dist/tests/stubs/emberReadData.stub.d.ts.map +1 -0
  77. package/dist/tests/stubs/emberReadData.stub.js +31 -0
  78. package/dist/tests/stubs/emberReadData.stub.js.map +1 -0
  79. package/dist/tests/stubs/emberSessionTransport.stub.d.ts +18 -0
  80. package/dist/tests/stubs/emberSessionTransport.stub.d.ts.map +1 -0
  81. package/dist/tests/stubs/emberSessionTransport.stub.js +75 -0
  82. package/dist/tests/stubs/emberSessionTransport.stub.js.map +1 -0
  83. package/dist/tests/units/dashboard/modules/emberChat.test.d.ts +2 -0
  84. package/dist/tests/units/dashboard/modules/emberChat.test.d.ts.map +1 -0
  85. package/dist/tests/units/dashboard/modules/emberChat.test.js +59 -0
  86. package/dist/tests/units/dashboard/modules/emberChat.test.js.map +1 -0
  87. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.d.ts +2 -0
  88. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.d.ts.map +1 -0
  89. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js +101 -0
  90. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js.map +1 -0
  91. package/dist/tests/units/modules/ember-chat/entities/emberMessage.guard.test.d.ts +2 -0
  92. package/dist/tests/units/modules/ember-chat/entities/emberMessage.guard.test.d.ts.map +1 -0
  93. package/dist/tests/units/modules/ember-chat/entities/emberMessage.guard.test.js +24 -0
  94. package/dist/tests/units/modules/ember-chat/entities/emberMessage.guard.test.js.map +1 -0
  95. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts +2 -0
  96. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts.map +1 -0
  97. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js +42 -0
  98. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js.map +1 -0
  99. package/dist/tests/units/modules/ember-chat/gateways/emberReadData.composite.gateway.test.d.ts +2 -0
  100. package/dist/tests/units/modules/ember-chat/gateways/emberReadData.composite.gateway.test.d.ts.map +1 -0
  101. package/dist/tests/units/modules/ember-chat/gateways/emberReadData.composite.gateway.test.js +75 -0
  102. package/dist/tests/units/modules/ember-chat/gateways/emberReadData.composite.gateway.test.js.map +1 -0
  103. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.d.ts +2 -0
  104. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.d.ts.map +1 -0
  105. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js +52 -0
  106. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js.map +1 -0
  107. package/dist/tests/units/modules/ember-chat/presenters/emberStatus.presenter.test.d.ts +2 -0
  108. package/dist/tests/units/modules/ember-chat/presenters/emberStatus.presenter.test.d.ts.map +1 -0
  109. package/dist/tests/units/modules/ember-chat/presenters/emberStatus.presenter.test.js +27 -0
  110. package/dist/tests/units/modules/ember-chat/presenters/emberStatus.presenter.test.js.map +1 -0
  111. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.d.ts +2 -0
  112. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.d.ts.map +1 -0
  113. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js +41 -0
  114. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js.map +1 -0
  115. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.d.ts +2 -0
  116. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.d.ts.map +1 -0
  117. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js +46 -0
  118. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js.map +1 -0
  119. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts +2 -0
  120. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts.map +1 -0
  121. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js +88 -0
  122. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js.map +1 -0
  123. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ export declare const emberSessionPhaseSchema: z.ZodEnum<{
3
+ idle: "idle";
4
+ live: "live";
5
+ }>;
6
+ export type EmberSessionPhase = z.infer<typeof emberSessionPhaseSchema>;
7
+ //# sourceMappingURL=emberSession.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSession.schema.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberSession/emberSession.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,uBAAuB;;;EAA2B,CAAC;AAEhE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { z } from 'zod';
2
+ export const emberSessionPhaseSchema = z.enum(['idle', 'live']);
3
+ //# sourceMappingURL=emberSession.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSession.schema.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberSession/emberSession.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { EmberSessionPhase } from '../../../../modules/ember-chat/entities/emberSession/emberSession.schema.js';
2
+ export declare class EmberSessionState {
3
+ private readonly props;
4
+ private constructor();
5
+ static idle(): EmberSessionState;
6
+ get phase(): EmberSessionPhase;
7
+ needsProcess(): boolean;
8
+ onQuestion(now: Date): EmberSessionState;
9
+ onAnswerDone(now: Date): EmberSessionState;
10
+ onIdleTick(now: Date, timeoutMs: number): EmberSessionState;
11
+ }
12
+ export declare function createIdleEmberSessionState(): EmberSessionState;
13
+ //# sourceMappingURL=emberSessionState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSessionState.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberSession/emberSessionState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mEAAmE,CAAC;AAO3G,qBAAa,iBAAiB;IACR,OAAO,CAAC,QAAQ,CAAC,KAAK;IAA1C,OAAO;IAEP,MAAM,CAAC,IAAI,IAAI,iBAAiB;IAIhC,IAAI,KAAK,IAAI,iBAAiB,CAE7B;IAED,YAAY,IAAI,OAAO;IAIvB,UAAU,CAAC,GAAG,EAAE,IAAI,GAAG,iBAAiB;IAIxC,YAAY,CAAC,GAAG,EAAE,IAAI,GAAG,iBAAiB;IAI1C,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB;CAU5D;AAED,wBAAgB,2BAA2B,IAAI,iBAAiB,CAE/D"}
@@ -0,0 +1,35 @@
1
+ export class EmberSessionState {
2
+ props;
3
+ constructor(props) {
4
+ this.props = props;
5
+ }
6
+ static idle() {
7
+ return new EmberSessionState({ phase: 'idle', lastActivityAt: null });
8
+ }
9
+ get phase() {
10
+ return this.props.phase;
11
+ }
12
+ needsProcess() {
13
+ return this.props.phase === 'idle';
14
+ }
15
+ onQuestion(now) {
16
+ return new EmberSessionState({ phase: 'live', lastActivityAt: now });
17
+ }
18
+ onAnswerDone(now) {
19
+ return new EmberSessionState({ phase: 'live', lastActivityAt: now });
20
+ }
21
+ onIdleTick(now, timeoutMs) {
22
+ if (this.props.phase === 'idle' || this.props.lastActivityAt === null) {
23
+ return this;
24
+ }
25
+ const inactiveMs = now.getTime() - this.props.lastActivityAt.getTime();
26
+ if (inactiveMs >= timeoutMs) {
27
+ return EmberSessionState.idle();
28
+ }
29
+ return this;
30
+ }
31
+ }
32
+ export function createIdleEmberSessionState() {
33
+ return EmberSessionState.idle();
34
+ }
35
+ //# sourceMappingURL=emberSessionState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSessionState.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberSession/emberSessionState.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,iBAAiB;IACS;IAArC,YAAqC,KAA6B;QAA7B,UAAK,GAAL,KAAK,CAAwB;IAAG,CAAC;IAEtE,MAAM,CAAC,IAAI;QACT,OAAO,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC1B,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC;IACrC,CAAC;IAED,UAAU,CAAC,GAAS;QAClB,OAAO,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,YAAY,CAAC,GAAS;QACpB,OAAO,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,UAAU,CAAC,GAAS,EAAE,SAAiB;QACrC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;QACvE,IAAI,UAAU,IAAI,SAAS,EAAE,CAAC;YAC5B,OAAO,iBAAiB,CAAC,IAAI,EAAE,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,iBAAiB,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,26 @@
1
+ export type EmberChunkHandler = (text: string) => void;
2
+ export type EmberDoneHandler = () => void;
3
+ export type EmberErrorHandler = (message: string) => void;
4
+ export interface EmberSessionHandle {
5
+ ask(question: string): void;
6
+ onChunk(handler: EmberChunkHandler): void;
7
+ onDone(handler: EmberDoneHandler): void;
8
+ onError(handler: EmberErrorHandler): void;
9
+ isAlive(): boolean;
10
+ kill(): void;
11
+ }
12
+ export interface EmberSessionSpawnOptions {
13
+ systemPrompt: string;
14
+ projectPath: string;
15
+ }
16
+ export type EmberSessionSpawnResult = {
17
+ status: 'spawned';
18
+ handle: EmberSessionHandle;
19
+ } | {
20
+ status: 'failed';
21
+ reason: string;
22
+ };
23
+ export interface EmberSessionTransportGateway {
24
+ spawn(options: EmberSessionSpawnOptions): EmberSessionSpawnResult;
25
+ }
26
+ //# sourceMappingURL=emberSessionTransport.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSessionTransport.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AACvD,MAAM,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC;AAC1C,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACxC,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,OAAO,IAAI,OAAO,CAAC;IACnB,IAAI,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,uBAAuB,GAC/B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GACjD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,4BAA4B;IAC3C,KAAK,CAAC,OAAO,EAAE,wBAAwB,GAAG,uBAAuB,CAAC;CACnE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=emberSessionTransport.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSessionTransport.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { ProjectStats } from '../../../../modules/statistics-insights/entities/stats/projectStats.js';
2
+ import type { PersistedInsightsData } from '../../../../modules/statistics-insights/entities/insight/persistedInsightsData.js';
3
+ import type { MrTrackingData } from '../../../../modules/tracking/entities/tracking/mrTrackingData.js';
4
+ import type { WorktreeEntry } from '../../../../modules/worktree-management/entities/worktree/worktree.schema.js';
5
+ export interface EmberReadDataGateway {
6
+ reviewScores(projectPath: string): Promise<ProjectStats | null>;
7
+ insights(projectPath: string): Promise<PersistedInsightsData | null>;
8
+ jobHistory(projectPath: string): Promise<MrTrackingData | null>;
9
+ worktrees(): Promise<WorktreeEntry[]>;
10
+ }
11
+ //# sourceMappingURL=emberTool.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberTool.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberTool/emberTool.gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AACjG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yEAAyE,CAAC;AACrH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oEAAoE,CAAC;AAExG,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACrE,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAChE,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CACvC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=emberTool.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberTool.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberTool/emberTool.gateway.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import type { FastifyPluginAsync } from 'fastify';
2
+ import type { Logger } from 'pino';
3
+ import type { EmberSessionRegistry } from '../../../../../modules/ember-chat/usecases/emberSession/emberSessionRegistry.js';
4
+ import type { EmberReadDataGateway } from '../../../../../modules/ember-chat/entities/emberTool/emberTool.gateway.js';
5
+ import type { EnvironmentGateway } from '../../../../../modules/claude-invocation/entities/billingState/environment.gateway.js';
6
+ export interface EmberChatRoutesOptions {
7
+ registry: EmberSessionRegistry;
8
+ environment: EnvironmentGateway;
9
+ readData: EmberReadDataGateway;
10
+ projectPath: string;
11
+ now: () => Date;
12
+ logger: Logger;
13
+ }
14
+ export declare const emberChatRoutes: FastifyPluginAsync<EmberChatRoutesOptions>;
15
+ //# sourceMappingURL=emberChat.routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberChat.routes.d.ts","sourceRoot":"","sources":["../../../../../../src/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACzG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0EAA0E,CAAC;AAInH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,eAAe,EAAE,kBAAkB,CAAC,sBAAsB,CAmEtE,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { emberMessageGuard } from '../../../../../modules/ember-chat/entities/emberMessage/emberMessage.guard.js';
2
+ import { askEmber } from '../../../../../modules/ember-chat/usecases/askEmber/askEmber.usecase.js';
3
+ const UNAVAILABLE_MESSAGE = '// EMBER INDISPONIBLE — réessayer';
4
+ export const emberChatRoutes = async (fastify, options) => {
5
+ const { registry, environment, readData, projectPath, now, logger } = options;
6
+ fastify.post('/api/ember/ask', async (request, reply) => {
7
+ const parsed = emberMessageGuard.safeParse(request.body);
8
+ if (!parsed.success) {
9
+ reply.code(400).send({ error: 'invalid-question' });
10
+ return;
11
+ }
12
+ const result = await askEmber(parsed.data, {
13
+ registry,
14
+ environment,
15
+ readData,
16
+ projectPath,
17
+ now,
18
+ });
19
+ reply.hijack();
20
+ reply.raw.writeHead(200, {
21
+ 'Content-Type': 'text/event-stream',
22
+ 'Cache-Control': 'no-cache',
23
+ Connection: 'keep-alive',
24
+ });
25
+ const writeEvent = (payload) => {
26
+ reply.raw.write(`data: ${JSON.stringify(payload)}\n\n`);
27
+ };
28
+ if (result.status !== 'streaming') {
29
+ logger.info({ status: result.status }, 'Ember unavailable for question');
30
+ writeEvent({ type: 'error', message: UNAVAILABLE_MESSAGE });
31
+ reply.raw.write('event: end\ndata: {}\n\n');
32
+ reply.raw.end();
33
+ return;
34
+ }
35
+ await new Promise((resolve) => {
36
+ let settled = false;
37
+ const finish = () => {
38
+ if (settled) {
39
+ return;
40
+ }
41
+ settled = true;
42
+ if (!reply.raw.writableEnded) {
43
+ reply.raw.write('event: end\ndata: {}\n\n');
44
+ reply.raw.end();
45
+ }
46
+ resolve();
47
+ };
48
+ result.subscribe({
49
+ onStatus: (state) => writeEvent({ type: 'status', state }),
50
+ onChunk: (text) => writeEvent({ type: 'chunk', text }),
51
+ onError: (message) => {
52
+ writeEvent({ type: 'error', message: UNAVAILABLE_MESSAGE, detail: message });
53
+ finish();
54
+ },
55
+ onDone: finish,
56
+ });
57
+ request.raw.on('close', finish);
58
+ });
59
+ });
60
+ };
61
+ //# sourceMappingURL=emberChat.routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberChat.routes.js","sourceRoot":"","sources":["../../../../../../src/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { EmberReadDataGateway } from '../../../../modules/ember-chat/entities/emberTool/emberTool.gateway.js';
2
+ import type { StatsGateway } from '../../../../modules/statistics-insights/entities/stats/stats.gateway.js';
3
+ import type { InsightsGateway } from '../../../../modules/statistics-insights/entities/insight/insights.gateway.js';
4
+ import type { ReviewRequestTrackingGateway } from '../../../../modules/tracking/entities/tracking/reviewRequestTracking.gateway.js';
5
+ import type { WorktreeGateway } from '../../../../modules/worktree-management/entities/worktree/worktree.gateway.js';
6
+ import type { ProjectStats } from '../../../../modules/statistics-insights/entities/stats/projectStats.js';
7
+ import type { PersistedInsightsData } from '../../../../modules/statistics-insights/entities/insight/persistedInsightsData.js';
8
+ import type { MrTrackingData } from '../../../../modules/tracking/entities/tracking/mrTrackingData.js';
9
+ import type { WorktreeEntry } from '../../../../modules/worktree-management/entities/worktree/worktree.schema.js';
10
+ export interface EmberReadDataCompositeGatewayDependencies {
11
+ statsGateway: StatsGateway;
12
+ insightsGateway: InsightsGateway;
13
+ trackingGateway: ReviewRequestTrackingGateway;
14
+ worktreeGateway: WorktreeGateway;
15
+ }
16
+ export declare class EmberReadDataCompositeGateway implements EmberReadDataGateway {
17
+ private readonly dependencies;
18
+ constructor(dependencies: EmberReadDataCompositeGatewayDependencies);
19
+ reviewScores(projectPath: string): Promise<ProjectStats | null>;
20
+ insights(projectPath: string): Promise<PersistedInsightsData | null>;
21
+ jobHistory(projectPath: string): Promise<MrTrackingData | null>;
22
+ worktrees(): Promise<WorktreeEntry[]>;
23
+ }
24
+ //# sourceMappingURL=emberReadData.composite.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberReadData.composite.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberReadData.composite.gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACzG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+DAA+D,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oEAAoE,CAAC;AAC1G,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uEAAuE,CAAC;AAC1H,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qEAAqE,CAAC;AAC3G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AACjG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yEAAyE,CAAC;AACrH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oEAAoE,CAAC;AAExG,MAAM,WAAW,yCAAyC;IACxD,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC;IACjC,eAAe,EAAE,4BAA4B,CAAC;IAC9C,eAAe,EAAE,eAAe,CAAC;CAClC;AAED,qBAAa,6BAA8B,YAAW,oBAAoB;IAC5D,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,yCAAyC;IAE9E,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAI/D,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAIpE,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAI/D,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAG5C"}
@@ -0,0 +1,19 @@
1
+ export class EmberReadDataCompositeGateway {
2
+ dependencies;
3
+ constructor(dependencies) {
4
+ this.dependencies = dependencies;
5
+ }
6
+ async reviewScores(projectPath) {
7
+ return this.dependencies.statsGateway.loadProjectStats(projectPath);
8
+ }
9
+ async insights(projectPath) {
10
+ return this.dependencies.insightsGateway.loadPersistedInsights(projectPath);
11
+ }
12
+ async jobHistory(projectPath) {
13
+ return this.dependencies.trackingGateway.loadTracking(projectPath);
14
+ }
15
+ async worktrees() {
16
+ return this.dependencies.worktreeGateway.list();
17
+ }
18
+ }
19
+ //# sourceMappingURL=emberReadData.composite.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberReadData.composite.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberReadData.composite.gateway.ts"],"names":[],"mappings":"AAiBA,MAAM,OAAO,6BAA6B;IACX;IAA7B,YAA6B,YAAuD;QAAvD,iBAAY,GAAZ,YAAY,CAA2C;IAAG,CAAC;IAExF,KAAK,CAAC,YAAY,CAAC,WAAmB;QACpC,OAAO,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,OAAO,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,WAAmB;QAClC,OAAO,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IAClD,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { EmberSessionSpawnOptions, EmberSessionSpawnResult, EmberSessionTransportGateway } from '../../../../modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js';
2
+ export interface EmberSessionTransportClaudeGatewayOptions {
3
+ claudePath: string;
4
+ mcpConfigJson: string;
5
+ allowedTools: string;
6
+ model: string;
7
+ }
8
+ export declare class EmberSessionTransportClaudeGateway implements EmberSessionTransportGateway {
9
+ private readonly options;
10
+ constructor(options: EmberSessionTransportClaudeGatewayOptions);
11
+ spawn(options: EmberSessionSpawnOptions): EmberSessionSpawnResult;
12
+ }
13
+ //# sourceMappingURL=emberSessionTransport.claude.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSessionTransport.claude.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAKV,wBAAwB,EACxB,uBAAuB,EACvB,4BAA4B,EAC7B,MAAM,6EAA6E,CAAC;AAkGrF,MAAM,WAAW,yCAAyC;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,kCAAmC,YAAW,4BAA4B;IACzE,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,yCAAyC;IAE/E,KAAK,CAAC,OAAO,EAAE,wBAAwB,GAAG,uBAAuB;CAgClE"}
@@ -0,0 +1,130 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { splitLines } from '../../../../modules/setup-wizard/interface-adapters/gateways/setupProcess.childProcess.gateway.js';
3
+ import { parseStreamJsonEvent, extractText, isTurnComplete, } from '../../../../modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js';
4
+ /**
5
+ * HUMBLE GLUE — NOT unit-tested. The conversational transport over the `claude`
6
+ * CLI is the one unverified mechanism in SPEC-189 (plan §12.1). Every layer above
7
+ * it (state machine, registry, usecase, presenter, routes, client) is unit-tested
8
+ * against the stub; this file is the swappable real implementation, validated by
9
+ * acceptance/manual only.
10
+ *
11
+ * Most plausible CLI shape: ONE long-lived child running claude in interactive
12
+ * streaming-JSON mode (`--input-format stream-json --output-format stream-json`),
13
+ * so consecutive questions are written on stdin as user messages and the answer
14
+ * is streamed back as assistant text deltas on stdout — keeping one resumable
15
+ * conversational thread per process. Grounding is injected into the appended
16
+ * system prompt (the review data is read through the typed EmberReadDataGateway
17
+ * in askEmber), so the session needs NO tools and gets none. No API key: relies
18
+ * on the operator's Claude login (subscription OAuth), like the bg dispatch path.
19
+ *
20
+ * MANUAL VERIFICATION REQUIRED: confirm the exact streaming-JSON event framing
21
+ * (assistant text delta vs. message_stop) and that interactive stream-json input
22
+ * keeps the thread alive across turns. Adjust extractText / isTurnComplete below
23
+ * once verified against a live `claude` build.
24
+ */
25
+ class ClaudeEmberSessionHandle {
26
+ child;
27
+ chunkHandler = null;
28
+ doneHandler = null;
29
+ errorHandler = null;
30
+ buffer = '';
31
+ alive = true;
32
+ constructor(child) {
33
+ this.child = child;
34
+ this.child.stdout.setEncoding('utf-8');
35
+ this.child.stdout.on('data', (chunk) => {
36
+ this.consume(chunk);
37
+ });
38
+ this.child.on('close', () => {
39
+ this.alive = false;
40
+ this.errorHandler?.('ember-session-closed');
41
+ });
42
+ this.child.on('error', () => {
43
+ this.alive = false;
44
+ this.errorHandler?.('ember-session-error');
45
+ });
46
+ }
47
+ ask(question) {
48
+ if (!this.child.stdin.writable) {
49
+ this.errorHandler?.('ember-session-not-writable');
50
+ return;
51
+ }
52
+ const userMessage = {
53
+ type: 'user',
54
+ message: { role: 'user', content: question },
55
+ };
56
+ this.child.stdin.write(`${JSON.stringify(userMessage)}\n`);
57
+ }
58
+ onChunk(handler) {
59
+ this.chunkHandler = handler;
60
+ }
61
+ onDone(handler) {
62
+ this.doneHandler = handler;
63
+ }
64
+ onError(handler) {
65
+ this.errorHandler = handler;
66
+ }
67
+ isAlive() {
68
+ return this.alive;
69
+ }
70
+ kill() {
71
+ this.alive = false;
72
+ this.child.kill();
73
+ }
74
+ consume(chunk) {
75
+ const { lines, rest } = splitLines(this.buffer, chunk);
76
+ this.buffer = rest;
77
+ for (const line of lines) {
78
+ const event = parseStreamJsonEvent(line);
79
+ if (event === null) {
80
+ continue;
81
+ }
82
+ const text = extractText(event);
83
+ if (text !== null) {
84
+ this.chunkHandler?.(text);
85
+ }
86
+ if (isTurnComplete(event)) {
87
+ this.doneHandler?.();
88
+ }
89
+ }
90
+ }
91
+ }
92
+ export class EmberSessionTransportClaudeGateway {
93
+ options;
94
+ constructor(options) {
95
+ this.options = options;
96
+ }
97
+ spawn(options) {
98
+ const args = [
99
+ '--input-format',
100
+ 'stream-json',
101
+ '--output-format',
102
+ 'stream-json',
103
+ '--verbose',
104
+ '--model',
105
+ this.options.model,
106
+ '--permission-mode',
107
+ 'default',
108
+ '--append-system-prompt',
109
+ options.systemPrompt,
110
+ '--mcp-config',
111
+ this.options.mcpConfigJson,
112
+ '--strict-mcp-config',
113
+ '--allowedTools',
114
+ this.options.allowedTools,
115
+ ];
116
+ try {
117
+ const child = spawn(this.options.claudePath, args, {
118
+ cwd: options.projectPath,
119
+ stdio: ['pipe', 'pipe', 'pipe'],
120
+ env: { ...process.env },
121
+ });
122
+ return { status: 'spawned', handle: new ClaudeEmberSessionHandle(child) };
123
+ }
124
+ catch (error) {
125
+ const reason = error instanceof Error ? error.message : 'spawn-failed';
126
+ return { status: 'failed', reason };
127
+ }
128
+ }
129
+ }
130
+ //# sourceMappingURL=emberSessionTransport.claude.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSessionTransport.claude.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface StreamJsonEvent {
2
+ type?: string;
3
+ subtype?: string;
4
+ text?: string;
5
+ delta?: {
6
+ text?: string;
7
+ };
8
+ message?: {
9
+ content?: Array<{
10
+ type?: string;
11
+ text?: string;
12
+ }>;
13
+ };
14
+ }
15
+ export declare function parseStreamJsonEvent(line: string): StreamJsonEvent | null;
16
+ export declare function extractText(event: StreamJsonEvent): string | null;
17
+ export declare function isTurnComplete(event: StreamJsonEvent): boolean;
18
+ //# sourceMappingURL=emberStreamJson.parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberStreamJson.parser.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CACjE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAUzE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAgBjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAE9D"}
@@ -0,0 +1,33 @@
1
+ export function parseStreamJsonEvent(line) {
2
+ try {
3
+ const parsed = JSON.parse(line);
4
+ if (parsed !== null && typeof parsed === 'object') {
5
+ return parsed;
6
+ }
7
+ return null;
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ export function extractText(event) {
14
+ if (typeof event.text === 'string') {
15
+ return event.text;
16
+ }
17
+ if (event.delta !== undefined && typeof event.delta.text === 'string') {
18
+ return event.delta.text;
19
+ }
20
+ const content = event.message?.content;
21
+ if (content !== undefined) {
22
+ const text = content
23
+ .filter((part) => part.type === 'text' && typeof part.text === 'string')
24
+ .map((part) => part.text ?? '')
25
+ .join('');
26
+ return text.length > 0 ? text : null;
27
+ }
28
+ return null;
29
+ }
30
+ export function isTurnComplete(event) {
31
+ return event.type === 'result' || event.type === 'message_stop';
32
+ }
33
+ //# sourceMappingURL=emberStreamJson.parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberStreamJson.parser.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAsB;IAChD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;IACvC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,OAAO;aACjB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;aACvE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;aAC9B,IAAI,CAAC,EAAE,CAAC,CAAC;QACZ,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAsB;IACnD,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC;AAClE,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { EmberStatus } from '../../../../modules/ember-chat/usecases/emberSession/emberSessionRegistry.js';
2
+ export type EmberAvatarState = 'idle' | 'working' | 'error';
3
+ export type EmberStatusEvent = {
4
+ kind: 'status';
5
+ status: EmberStatus;
6
+ } | {
7
+ kind: 'answer';
8
+ text: string;
9
+ } | {
10
+ kind: 'error';
11
+ };
12
+ export interface EmberStatusViewModel {
13
+ avatarState: EmberAvatarState;
14
+ liveRegionText: string;
15
+ unavailableMessage: string | null;
16
+ }
17
+ export declare class EmberStatusPresenter {
18
+ present(event: EmberStatusEvent): EmberStatusViewModel;
19
+ }
20
+ //# sourceMappingURL=emberStatus.presenter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberStatus.presenter.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oEAAoE,CAAC;AAEtG,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAID,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,oBAAoB;CA2BvD"}
@@ -0,0 +1,28 @@
1
+ const UNAVAILABLE_MESSAGE = '// EMBER INDISPONIBLE — réessayer';
2
+ export class EmberStatusPresenter {
3
+ present(event) {
4
+ if (event.kind === 'answer') {
5
+ return { avatarState: 'idle', liveRegionText: event.text, unavailableMessage: null };
6
+ }
7
+ if (event.kind === 'error' || event.status === 'error') {
8
+ return {
9
+ avatarState: 'error',
10
+ liveRegionText: 'Ember est indisponible.',
11
+ unavailableMessage: UNAVAILABLE_MESSAGE,
12
+ };
13
+ }
14
+ if (event.status === 'working') {
15
+ return {
16
+ avatarState: 'working',
17
+ liveRegionText: 'Ember prépare une réponse.',
18
+ unavailableMessage: null,
19
+ };
20
+ }
21
+ return {
22
+ avatarState: 'idle',
23
+ liveRegionText: 'Ember a terminé sa réponse.',
24
+ unavailableMessage: null,
25
+ };
26
+ }
27
+ }
28
+ //# sourceMappingURL=emberStatus.presenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberStatus.presenter.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.ts"],"names":[],"mappings":"AAeA,MAAM,mBAAmB,GAAG,mCAAmC,CAAC;AAEhE,MAAM,OAAO,oBAAoB;IAC/B,OAAO,CAAC,KAAuB;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;QACvF,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YACvD,OAAO;gBACL,WAAW,EAAE,OAAO;gBACpB,cAAc,EAAE,yBAAyB;gBACzC,kBAAkB,EAAE,mBAAmB;aACxC,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO;gBACL,WAAW,EAAE,SAAS;gBACtB,cAAc,EAAE,4BAA4B;gBAC5C,kBAAkB,EAAE,IAAI;aACzB,CAAC;QACJ,CAAC;QAED,OAAO;YACL,WAAW,EAAE,MAAM;YACnB,cAAc,EAAE,6BAA6B;YAC7C,kBAAkB,EAAE,IAAI;SACzB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import type { ProjectStats } from '../../../modules/statistics-insights/entities/stats/projectStats.js';
2
+ import type { PersistedInsightsData } from '../../../modules/statistics-insights/entities/insight/persistedInsightsData.js';
3
+ import type { MrTrackingData } from '../../../modules/tracking/entities/tracking/mrTrackingData.js';
4
+ import type { WorktreeEntry } from '../../../modules/worktree-management/entities/worktree/worktree.schema.js';
5
+ export interface EmberGrounding {
6
+ reviewScores: ProjectStats | null;
7
+ insights: PersistedInsightsData | null;
8
+ jobHistory: MrTrackingData | null;
9
+ worktrees: WorktreeEntry[];
10
+ }
11
+ export declare function buildEmberSystemPrompt(grounding: EmberGrounding): string;
12
+ //# sourceMappingURL=emberSystemPrompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSystemPrompt.d.ts","sourceRoot":"","sources":["../../../../src/modules/ember-chat/services/emberSystemPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AACjG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yEAAyE,CAAC;AACrH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oEAAoE,CAAC;AAExG,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACvC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CA2BxE"}
@@ -0,0 +1,29 @@
1
+ export function buildEmberSystemPrompt(grounding) {
2
+ return [
3
+ "Tu es Ember, l'assistant conversationnel du tableau de bord ReviewFlow.",
4
+ '',
5
+ 'TES SEULES SOURCES DE DONNÉES sont ces données de review du projet, fournies ci-dessous.',
6
+ "Tu n'as aucun autre accès : ni système de fichiers, ni outil, ni réseau.",
7
+ '',
8
+ 'reviewScores (scores et statistiques de review) :',
9
+ JSON.stringify(grounding.reviewScores),
10
+ '',
11
+ 'insights (insights développeur et équipe) :',
12
+ JSON.stringify(grounding.insights),
13
+ '',
14
+ 'jobHistory (historique des jobs de review) :',
15
+ JSON.stringify(grounding.jobHistory),
16
+ '',
17
+ 'worktrees (état des worktrees) :',
18
+ JSON.stringify(grounding.worktrees),
19
+ '',
20
+ 'GROUNDING : réponds uniquement à partir de ces données de review.',
21
+ "Si la question sort de ces données, dis que tu ne sais répondre qu'à propos des reviews",
22
+ "plutôt que d'inventer une réponse. N'invente jamais.",
23
+ '',
24
+ 'LECTURE SEULE : tu ne modifies, ne crées et ne supprimes rien. Si on te demande',
25
+ "d'écrire, de créer ou de modifier quelque chose (par exemple un quality gate),",
26
+ "explique que cela arrivera en Phase B et n'effectue aucune écriture.",
27
+ ].join('\n');
28
+ }
29
+ //# sourceMappingURL=emberSystemPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberSystemPrompt.js","sourceRoot":"","sources":["../../../../src/modules/ember-chat/services/emberSystemPrompt.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,sBAAsB,CAAC,SAAyB;IAC9D,OAAO;QACL,yEAAyE;QACzE,EAAE;QACF,0FAA0F;QAC1F,0EAA0E;QAC1E,EAAE;QACF,mDAAmD;QACnD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC;QACtC,EAAE;QACF,6CAA6C;QAC7C,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC;QAClC,EAAE;QACF,8CAA8C;QAC9C,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU,CAAC;QACpC,EAAE;QACF,kCAAkC;QAClC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC;QACnC,EAAE;QACF,mEAAmE;QACnE,yFAAyF;QACzF,sDAAsD;QACtD,EAAE;QACF,iFAAiF;QACjF,gFAAgF;QAChF,sEAAsE;KACvE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}