@shepai/cli 1.81.0 → 1.82.0-pr253.7a6575f

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 (147) hide show
  1. package/apis/json-schema/Feature.yaml +5 -0
  2. package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.js +3 -0
  4. package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts +6 -0
  5. package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts.map +1 -1
  6. package/dist/src/presentation/web/app/actions/get-feature-phase-timings.js +26 -1
  7. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
  8. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +8 -1
  9. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts +3 -2
  10. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts.map +1 -1
  11. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.js +29 -6
  12. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.d.ts +2 -0
  13. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.d.ts.map +1 -1
  14. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.js +72 -0
  15. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map +1 -1
  16. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js +2 -2
  17. package/dist/tsconfig.build.tsbuildinfo +1 -1
  18. package/package.json +1 -1
  19. package/web/.next/BUILD_ID +1 -1
  20. package/web/.next/build-manifest.json +2 -2
  21. package/web/.next/fallback-build-manifest.json +2 -2
  22. package/web/.next/prerender-manifest.json +3 -3
  23. package/web/.next/required-server-files.js +1 -1
  24. package/web/.next/required-server-files.json +1 -1
  25. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +18 -18
  26. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  27. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  28. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +21 -21
  29. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  31. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  32. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  33. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  34. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  35. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +18 -18
  36. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  37. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  38. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +21 -21
  39. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
  40. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  41. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  42. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  43. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  44. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  45. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  46. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  47. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/_global-error.html +2 -2
  49. package/web/.next/server/app/_global-error.rsc +1 -1
  50. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  51. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  52. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  53. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  54. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  55. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  56. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/api/dialog/pick-files/route.js +1 -1
  58. package/web/.next/server/app/api/dialog/pick-files/route.js.nft.json +1 -1
  59. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  60. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  61. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  63. package/web/.next/server/app/skills/page.js +3 -2
  64. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  65. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  67. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  68. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  69. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  70. package/web/.next/server/chunks/{[root-of-the-server]__a6bf88cc._.js → [root-of-the-server]__332c8d91._.js} +2 -2
  71. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  72. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  73. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  74. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +1 -1
  75. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  76. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js.map +1 -1
  77. package/web/.next/server/chunks/ssr/90b01_js-yaml_dist_js-yaml_mjs_c897fb57._.js +3 -0
  78. package/web/.next/server/chunks/ssr/90b01_js-yaml_dist_js-yaml_mjs_c897fb57._.js.map +1 -0
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__17143953._.js +3 -0
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__17143953._.js.map +1 -0
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  84. package/web/.next/server/chunks/ssr/[root-of-the-server]__4be9a9bb._.js +1 -1
  85. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  86. package/web/.next/server/chunks/ssr/[root-of-the-server]__9de266fa._.js +3 -0
  87. package/web/.next/server/chunks/ssr/[root-of-the-server]__9de266fa._.js.map +1 -0
  88. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  89. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  90. package/web/.next/server/chunks/ssr/[root-of-the-server]__b3a4cef4._.js +1 -1
  91. package/web/.next/server/chunks/ssr/[root-of-the-server]__b3a4cef4._.js.map +1 -1
  92. package/web/.next/server/chunks/ssr/[root-of-the-server]__f0d8d054._.js +2 -2
  93. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  94. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  95. package/web/.next/server/chunks/ssr/_1e3cf73b._.js +1 -1
  96. package/web/.next/server/chunks/ssr/_1e3cf73b._.js.map +1 -1
  97. package/web/.next/server/chunks/ssr/{_a9bd20e7._.js → _366a5dce._.js} +2 -2
  98. package/web/.next/server/chunks/ssr/{_a9bd20e7._.js.map → _366a5dce._.js.map} +1 -1
  99. package/web/.next/server/chunks/ssr/_3a4c94e3._.js +1 -1
  100. package/web/.next/server/chunks/ssr/_3a4c94e3._.js.map +1 -1
  101. package/web/.next/server/chunks/ssr/_63868199._.js +1 -1
  102. package/web/.next/server/chunks/ssr/_63868199._.js.map +1 -1
  103. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  104. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  105. package/web/.next/server/chunks/ssr/{_443a73b8._.js → _c0449b16._.js} +2 -2
  106. package/web/.next/server/chunks/ssr/{_443a73b8._.js.map → _c0449b16._.js.map} +1 -1
  107. package/web/.next/server/chunks/ssr/_c3a8bcb1._.js +1 -1
  108. package/web/.next/server/chunks/ssr/_c3a8bcb1._.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/{_acad3a0a._.js → _ffe55fc9._.js} +2 -2
  110. package/web/.next/server/chunks/ssr/{_acad3a0a._.js.map → _ffe55fc9._.js.map} +1 -1
  111. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  112. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +1 -1
  114. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  116. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  118. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/src_presentation_web_c4348b8a._.js +2 -2
  120. package/web/.next/server/chunks/ssr/src_presentation_web_c4348b8a._.js.map +1 -1
  121. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  122. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  123. package/web/.next/server/chunks/ssr/src_presentation_web_e4510d10._.js +2 -2
  124. package/web/.next/server/chunks/ssr/src_presentation_web_e4510d10._.js.map +1 -1
  125. package/web/.next/server/pages/500.html +2 -2
  126. package/web/.next/server/server-reference-manifest.js +1 -1
  127. package/web/.next/server/server-reference-manifest.json +28 -28
  128. package/web/.next/static/chunks/{0bdbe1cc9455ff91.js → 002230749b700f8b.js} +1 -1
  129. package/web/.next/static/chunks/{aa29aeb2773241a1.js → 14b82aa592cf8ce7.js} +1 -1
  130. package/web/.next/static/chunks/{1145c07ed418ff5f.js → 17612276444e823b.js} +1 -1
  131. package/web/.next/static/chunks/{735d7a295a2358aa.js → 6b68b235f44e3bf7.js} +1 -1
  132. package/web/.next/static/chunks/{0c048048cb2cfbaa.js → 7d4c368fa1e584b5.js} +1 -1
  133. package/web/.next/static/chunks/{f9c2c44f843344ea.js → 8120afda3430873f.js} +1 -1
  134. package/web/.next/static/chunks/{0c6a84d6dc47ee76.js → 9aa0f8c1f7b74fef.js} +1 -1
  135. package/web/.next/static/chunks/{71939cdc18fa4e10.js → 9ad1c13c6185cf89.js} +1 -1
  136. package/web/.next/static/chunks/{c89e416ccf4e2f4a.js → a8c6942315c6bb2d.js} +1 -1
  137. package/web/.next/static/chunks/ae01d2be1d0bad47.css +2 -0
  138. package/web/.next/static/chunks/{58d2d89b83b2f777.js → fea2340010754ea0.js} +1 -1
  139. package/web/.next/server/chunks/ssr/src_presentation_web_7efa14ca._.js +0 -3
  140. package/web/.next/server/chunks/ssr/src_presentation_web_7efa14ca._.js.map +0 -1
  141. package/web/.next/server/chunks/ssr/src_presentation_web_b59d79db._.js +0 -3
  142. package/web/.next/server/chunks/ssr/src_presentation_web_b59d79db._.js.map +0 -1
  143. package/web/.next/static/chunks/96bab6d3820504f3.css +0 -2
  144. /package/web/.next/server/chunks/{[root-of-the-server]__a6bf88cc._.js.map → [root-of-the-server]__332c8d91._.js.map} +0 -0
  145. /package/web/.next/static/{Bq92HGWK4ybMJvAQ3w10T → NsKGjPPyxd2c90DNz4oNY}/_buildManifest.js +0 -0
  146. /package/web/.next/static/{Bq92HGWK4ybMJvAQ3w10T → NsKGjPPyxd2c90DNz4oNY}/_clientMiddlewareManifest.json +0 -0
  147. /package/web/.next/static/{Bq92HGWK4ybMJvAQ3w10T → NsKGjPPyxd2c90DNz4oNY}/_ssgManifest.js +0 -0
@@ -45,6 +45,10 @@ properties:
45
45
  repositoryId:
46
46
  $ref: UUID.yaml
47
47
  description: ID of the Repository entity this feature belongs to
48
+ fast:
49
+ type: boolean
50
+ default: false
51
+ description: When true, SDLC phases were skipped and the feature was implemented directly from the prompt
48
52
  push:
49
53
  type: boolean
50
54
  default: false
@@ -75,6 +79,7 @@ required:
75
79
  - lifecycle
76
80
  - messages
77
81
  - relatedArtifacts
82
+ - fast
78
83
  - push
79
84
  - openPr
80
85
  - approvalGates
@@ -1 +1 @@
1
- {"version":3,"file":"reject-agent-run.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/agents/reject-agent-run.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AACvG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gEAAgE,CAAC;AAC7G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAS1G,qBACa,qBAAqB;IAG9B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAEnC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;gBANrB,kBAAkB,EAAE,mBAAmB,EAEvC,cAAc,EAAE,2BAA2B,EAE3C,iBAAiB,EAAE,kBAAkB,EAErC,qBAAqB,EAAE,sBAAsB;IAG1D,OAAO,CACX,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QACT,QAAQ,EAAE,OAAO,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,CAAC;CAgHH"}
1
+ {"version":3,"file":"reject-agent-run.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/agents/reject-agent-run.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AACvG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gEAAgE,CAAC;AAC7G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAU1G,qBACa,qBAAqB;IAG9B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAEnC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;gBANrB,kBAAkB,EAAE,mBAAmB,EAEvC,cAAc,EAAE,2BAA2B,EAE3C,iBAAiB,EAAE,kBAAkB,EAErC,qBAAqB,EAAE,sBAAsB;IAG1D,OAAO,CACX,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QACT,QAAQ,EAAE,OAAO,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,CAAC;CAmHH"}
@@ -23,6 +23,7 @@ import { readFileSync } from 'node:fs';
23
23
  import { join } from 'node:path';
24
24
  import { AgentRunStatus } from '../../../domain/generated/output.js';
25
25
  import { writeSpecFileAtomic } from '../../../infrastructure/services/agents/feature-agent/nodes/node-helpers.js';
26
+ import { recordLifecycleEvent } from '../../../infrastructure/services/agents/feature-agent/phase-timing-context.js';
26
27
  import { computeWorktreePath } from '../../../infrastructure/services/ide-launchers/compute-worktree-path.js';
27
28
  let RejectAgentRunUseCase = class RejectAgentRunUseCase {
28
29
  agentRunRepository;
@@ -101,6 +102,8 @@ let RejectAgentRunUseCase = class RejectAgentRunUseCase {
101
102
  catch {
102
103
  // Non-fatal
103
104
  }
105
+ // Record rejected lifecycle event
106
+ await recordLifecycleEvent('run:rejected', id, this.phaseTimingRepository);
104
107
  // Spawn worker with rejection payload
105
108
  const rejectionPayload = {
106
109
  rejected: true,
@@ -7,8 +7,14 @@ export interface PhaseTimingData {
7
7
  waitingApprovalAt?: string;
8
8
  approvalWaitMs?: number;
9
9
  }
10
+ export interface RejectionFeedbackData {
11
+ iteration: number;
12
+ message: string;
13
+ phase?: string;
14
+ }
10
15
  type GetPhaseTimingsResult = {
11
16
  timings: PhaseTimingData[];
17
+ rejectionFeedback: RejectionFeedbackData[];
12
18
  } | {
13
19
  error: string;
14
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"get-feature-phase-timings.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-feature-phase-timings.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,KAAK,qBAAqB,GAAG;IAAE,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwB9F"}
1
+ {"version":3,"file":"get-feature-phase-timings.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-feature-phase-timings.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,qBAAqB,GACtB;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,iBAAiB,EAAE,qBAAqB,EAAE,CAAA;CAAE,GAC1E;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA2B9F"}
@@ -16,10 +16,35 @@ export async function getFeaturePhaseTimings(featureId) {
16
16
  waitingApprovalAt: t.waitingApprovalAt,
17
17
  approvalWaitMs: t.approvalWaitMs != null ? Number(t.approvalWaitMs) : undefined,
18
18
  }));
19
- return { timings };
19
+ // Read rejection feedback from spec.yaml
20
+ const rejectionFeedback = await readRejectionFeedback(featureId);
21
+ return { timings, rejectionFeedback };
20
22
  }
21
23
  catch (error) {
22
24
  const message = error instanceof Error ? error.message : 'Failed to load phase timings';
23
25
  return { error: message };
24
26
  }
25
27
  }
28
+ async function readRejectionFeedback(featureId) {
29
+ try {
30
+ const featureRepo = resolve('IFeatureRepository');
31
+ const feature = await featureRepo.findById(featureId);
32
+ if (!feature?.specPath)
33
+ return [];
34
+ const { readFileSync } = await import('node:fs');
35
+ const { join } = await import('node:path');
36
+ const yaml = (await import('js-yaml')).default;
37
+ const specContent = readFileSync(join(feature.specPath, 'spec.yaml'), 'utf-8');
38
+ const spec = yaml.load(specContent);
39
+ if (!Array.isArray(spec?.rejectionFeedback))
40
+ return [];
41
+ return spec.rejectionFeedback.map((entry) => ({
42
+ iteration: Number(entry.iteration ?? 1),
43
+ message: String(entry.message ?? ''),
44
+ phase: entry.phase ? String(entry.phase) : undefined,
45
+ }));
46
+ }
47
+ catch {
48
+ return [];
49
+ }
50
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAC/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAI5E,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,EAAE,OAAO,CAAC;IACd,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,YAAY,GACb,EAAE,wBAAwB,2CAiY1B"}
1
+ {"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAC/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAI5E,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,EAAE,OAAO,CAAC;IACd,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,YAAY,GACb,EAAE,wBAAwB,2CAgZ1B"}
@@ -121,8 +121,15 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
121
121
  const handleRemoveFile = useCallback((path) => {
122
122
  setAttachments((prev) => prev.filter((f) => f.path !== path));
123
123
  }, []);
124
+ const formRef = useRef(null);
125
+ const handleKeyDown = useCallback((e) => {
126
+ if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
127
+ e.preventDefault();
128
+ formRef.current?.requestSubmit();
129
+ }
130
+ }, []);
124
131
  const hasFeatures = features && features.length > 0;
125
- return (_jsx(BaseDrawer, { open: open, onClose: attemptClose, size: "md", modal: false, dismissOnOutsideClick: true, "data-testid": "feature-create-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), isSubmitting ? (_jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })) : null] }), footer: _jsxs("div", { className: "flex flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: attemptClose, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !description.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] }), children: _jsx("div", { className: "overflow-y-auto p-4", children: _jsx(TooltipProvider, { delayDuration: 400, children: _jsxs("form", { id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIBE YOUR FEATURE" }), _jsxs("div", { className: "border-input focus-within:ring-ring/50 focus-within:border-ring overflow-hidden rounded-md border shadow-xs transition-[color,box-shadow] focus-within:ring-[3px]", children: [_jsx(Textarea, { id: "feature-description", placeholder: "e.g. Add GitHub OAuth login with callback handling and token refresh...", value: description, onChange: (e) => setDescription(e.target.value), rows: 7, required: true, disabled: isSubmitting, className: "field-sizing-fixed min-h-42! resize-none rounded-none border-0 shadow-none focus-visible:ring-0" }), _jsxs("div", { className: "border-input flex items-center gap-3 border-t px-3 py-1.5", children: [_jsx(AgentModelPicker, { initialAgentType: overrideAgent ?? currentAgentType ?? 'claude-code', initialModel: overrideModel ?? currentModel ?? 'claude-sonnet-4-6', mode: "override", onAgentModelChange: (agent, model) => {
132
+ return (_jsx(BaseDrawer, { open: open, onClose: attemptClose, size: "md", modal: false, dismissOnOutsideClick: true, "data-testid": "feature-create-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), isSubmitting ? (_jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })) : null] }), footer: _jsxs("div", { className: "flex flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: attemptClose, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !description.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] }), children: _jsx("div", { className: "overflow-y-auto p-4", children: _jsx(TooltipProvider, { delayDuration: 400, children: _jsxs("form", { ref: formRef, id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIBE YOUR FEATURE" }), _jsxs("div", { className: "border-input focus-within:ring-ring/50 focus-within:border-ring overflow-hidden rounded-md border shadow-xs transition-[color,box-shadow] focus-within:ring-[3px]", children: [_jsx(Textarea, { id: "feature-description", placeholder: "e.g. Add GitHub OAuth login with callback handling and token refresh...", value: description, onChange: (e) => setDescription(e.target.value), onKeyDown: handleKeyDown, rows: 7, required: true, disabled: isSubmitting, className: "field-sizing-fixed min-h-42! resize-none rounded-none border-0 shadow-none focus-visible:ring-0" }), _jsxs("div", { className: "border-input flex items-center gap-3 border-t px-3 py-1.5", children: [_jsx(AgentModelPicker, { initialAgentType: overrideAgent ?? currentAgentType ?? 'claude-code', initialModel: overrideModel ?? currentModel ?? 'claude-sonnet-4-6', mode: "override", onAgentModelChange: (agent, model) => {
126
133
  setOverrideAgent(agent);
127
134
  setOverrideModel(model);
128
135
  }, disabled: isSubmitting, className: "w-55" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "ml-auto flex cursor-pointer items-center gap-2", children: [_jsx(Switch, { id: "fast-mode", checked: fast, onCheckedChange: setFast, disabled: isSubmitting }), _jsxs(Label, { htmlFor: "fast-mode", className: "flex cursor-pointer items-center gap-1 text-sm font-medium", children: [_jsx(Zap, { className: "h-3.5 w-3.5" }), "Fast Mode"] })] }) }), _jsx(TooltipContent, { side: "bottom", children: "Skip SDLC phases and implement directly from your prompt." })] })] })] })] }), hasFeatures && initialParentId !== undefined ? (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "parent-feature", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "PARENT FEATURE" }), _jsx(ParentFeatureCombobox, { features: features, value: parentId, onChange: setParentId, disabled: isSubmitting })] })) : null, _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "border-input flex items-center gap-4 rounded-md border px-3 py-2.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "text-muted-foreground w-16 shrink-0 cursor-default text-xs font-semibold tracking-wider", children: "APPROVE" }) }), _jsx(TooltipContent, { side: "bottom", children: "Auto-approve phase transitions without manual review." })] }), _jsx("div", { className: "flex flex-1 items-center gap-4", children: AUTO_APPROVE_OPTIONS.map((opt) => (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex cursor-pointer items-center gap-1.5", children: [_jsx(Switch, { id: `approve-${opt.id}`, size: "sm", checked: approvalGates[opt.id] ?? false, onCheckedChange: (v) => setApprovalGates((prev) => ({ ...prev, [opt.id]: v })), disabled: isSubmitting ||
@@ -1,8 +1,9 @@
1
- import type { PhaseTimingData } from '../../../app/actions/get-feature-phase-timings.js';
1
+ import type { PhaseTimingData, RejectionFeedbackData } from '../../../app/actions/get-feature-phase-timings.js';
2
2
  export interface ActivityTabProps {
3
3
  timings: PhaseTimingData[] | null;
4
4
  loading: boolean;
5
5
  error: string | null;
6
+ rejectionFeedback?: RejectionFeedbackData[];
6
7
  }
7
- export declare function ActivityTab({ timings, loading, error }: ActivityTabProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function ActivityTab({ timings, loading, error, rejectionFeedback }: ActivityTabProps): import("react/jsx-runtime").JSX.Element;
8
9
  //# sourceMappingURL=activity-tab.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"activity-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE/E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AA+CD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,gBAAgB,2CA0DxE"}
1
+ {"version":3,"file":"activity-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACtB,MAAM,yCAAyC,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iBAAiB,CAAC,EAAE,qBAAqB,EAAE,CAAC;CAC7C;AAsED,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,2CA8D3F"}
@@ -16,6 +16,7 @@ const LIFECYCLE_EVENTS = {
16
16
  'run:failed': { label: 'failed', colorClass: 'text-red-600' },
17
17
  'run:stopped': { label: 'stopped', colorClass: 'text-amber-600' },
18
18
  'run:crashed': { label: 'crashed', colorClass: 'text-red-600' },
19
+ 'run:rejected': { label: 'rejected', colorClass: 'text-orange-600' },
19
20
  };
20
21
  function isLifecycleEvent(phase) {
21
22
  return phase.startsWith('run:');
@@ -36,7 +37,25 @@ function groupTimingsByRun(timings) {
36
37
  }
37
38
  return groups;
38
39
  }
39
- export function ActivityTab({ timings, loading, error }) {
40
+ /**
41
+ * Map each run:rejected timing entry to its rejection feedback message.
42
+ * Matches by sequential order: 1st rejected event → 1st feedback entry, etc.
43
+ */
44
+ function buildRejectionMessageMap(timings, feedback) {
45
+ const map = new Map();
46
+ if (!feedback?.length)
47
+ return map;
48
+ let rejectionIdx = 0;
49
+ for (const t of timings) {
50
+ if (t.phase === 'run:rejected' && rejectionIdx < feedback.length) {
51
+ const key = `${t.agentRunId}-${t.phase}-${t.startedAt}`;
52
+ map.set(key, feedback[rejectionIdx].message);
53
+ rejectionIdx++;
54
+ }
55
+ }
56
+ return map;
57
+ }
58
+ export function ActivityTab({ timings, loading, error, rejectionFeedback }) {
40
59
  if (loading) {
41
60
  return (_jsx("div", { "data-testid": "activity-tab-loading", className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
42
61
  }
@@ -48,25 +67,29 @@ export function ActivityTab({ timings, loading, error }) {
48
67
  }
49
68
  const nodeTimings = timings.filter((t) => !isLifecycleEvent(t.phase));
50
69
  const maxDurationMs = Math.max(...nodeTimings.map((t) => t.durationMs ?? 0), ...nodeTimings.map((t) => t.approvalWaitMs ?? 0), 0);
70
+ // Build a map from rejection index to feedback message
71
+ const rejectionMessages = buildRejectionMessageMap(timings, rejectionFeedback);
51
72
  const groups = groupTimingsByRun(timings);
52
73
  const multiRun = groups.length > 1;
53
74
  const totalExecMs = nodeTimings.reduce((sum, t) => sum + (t.durationMs ?? 0), 0);
54
75
  const totalWaitMs = nodeTimings.reduce((sum, t) => sum + (t.approvalWaitMs ?? 0), 0);
55
- return (_jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx("div", { "data-testid": "activity-timings", className: "flex flex-col gap-3", children: groups.map((group, groupIdx) => (_jsx(RunGroup, { group: group, groupIdx: groupIdx, multiRun: multiRun, maxDurationMs: maxDurationMs }, group.runId))) }), totalExecMs > 0 ? (_jsx(SummaryTotals, { totalExecMs: totalExecMs, totalWaitMs: totalWaitMs })) : null] }));
76
+ return (_jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx("div", { "data-testid": "activity-timings", className: "flex flex-col gap-3", children: groups.map((group, groupIdx) => (_jsx(RunGroup, { group: group, groupIdx: groupIdx, multiRun: multiRun, maxDurationMs: maxDurationMs, rejectionMessages: rejectionMessages }, group.runId))) }), totalExecMs > 0 ? (_jsx(SummaryTotals, { totalExecMs: totalExecMs, totalWaitMs: totalWaitMs })) : null] }));
56
77
  }
57
- function RunGroup({ group, groupIdx, multiRun, maxDurationMs, }) {
78
+ function RunGroup({ group, groupIdx, multiRun, maxDurationMs, rejectionMessages, }) {
58
79
  return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [multiRun ? (_jsxs("div", { className: "text-muted-foreground text-xs font-medium", children: ["Run #", groupIdx + 1] })) : null, group.timings.map((t) => {
59
80
  if (isLifecycleEvent(t.phase)) {
60
- return _jsx(LifecycleEventRow, { timing: t }, `${t.agentRunId}-${t.phase}-${t.startedAt}`);
81
+ const key = `${t.agentRunId}-${t.phase}-${t.startedAt}`;
82
+ const message = t.phase === 'run:rejected' ? rejectionMessages.get(key) : undefined;
83
+ return _jsx(LifecycleEventRow, { timing: t, message: message }, key);
61
84
  }
62
85
  return (_jsx(NodeTimingRow, { timing: t, maxDurationMs: maxDurationMs }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
63
86
  })] }));
64
87
  }
65
- function LifecycleEventRow({ timing }) {
88
+ function LifecycleEventRow({ timing, message }) {
66
89
  const event = LIFECYCLE_EVENTS[timing.phase];
67
90
  if (!event)
68
91
  return null;
69
- return (_jsx("div", { className: `text-xs ${event.colorClass}`, children: _jsx("span", { children: event.label }) }));
92
+ return (_jsxs("div", { className: `text-xs ${event.colorClass}`, children: [_jsx("span", { children: event.label }), message ? (_jsxs("span", { "data-testid": "rejection-feedback-text", className: "text-muted-foreground ml-2 font-normal italic", children: ["\u2014 ", message] })) : null] }));
70
93
  }
71
94
  function NodeTimingRow({ timing, maxDurationMs, }) {
72
95
  const label = timing.phase.includes(':')
@@ -15,6 +15,8 @@ export declare const Loading: Story;
15
15
  export declare const Empty: Story;
16
16
  /** Error state — inline error message. */
17
17
  export declare const Error: Story;
18
+ /** Rejection — shows rejected lifecycle event with user feedback text. */
19
+ export declare const WithRejection: Story;
18
20
  /** Approval wait indicators — phases with approval wait sub-rows. */
19
21
  export declare const WithApprovalWaits: Story;
20
22
  //# sourceMappingURL=activity-tab.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"activity-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AAmK1C,2EAA2E;AAC3E,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,EAAE,KAgC/B,CAAC"}
1
+ {"version":3,"file":"activity-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AAmK1C,2EAA2E;AAC3E,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,aAAa,EAAE,KAsE3B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,EAAE,KAgC/B,CAAC"}
@@ -216,6 +216,78 @@ export const Error = {
216
216
  error: 'Failed to load phase timings. Please try again.',
217
217
  },
218
218
  };
219
+ /** Rejection — shows rejected lifecycle event with user feedback text. */
220
+ export const WithRejection = {
221
+ args: {
222
+ timings: [
223
+ {
224
+ agentRunId: 'run-1',
225
+ phase: 'run:started',
226
+ startedAt: '2025-01-15T10:00:00Z',
227
+ durationMs: 0,
228
+ },
229
+ {
230
+ agentRunId: 'run-1',
231
+ phase: 'analyze',
232
+ startedAt: '2025-01-15T10:00:01Z',
233
+ completedAt: '2025-01-15T10:00:15Z',
234
+ durationMs: 14000,
235
+ },
236
+ {
237
+ agentRunId: 'run-1',
238
+ phase: 'requirements',
239
+ startedAt: '2025-01-15T10:00:15Z',
240
+ completedAt: '2025-01-15T10:01:45Z',
241
+ durationMs: 90000,
242
+ waitingApprovalAt: '2025-01-15T10:01:00Z',
243
+ approvalWaitMs: 30000,
244
+ },
245
+ {
246
+ agentRunId: 'run-1',
247
+ phase: 'run:rejected',
248
+ startedAt: '2025-01-15T10:01:45Z',
249
+ durationMs: 0,
250
+ },
251
+ {
252
+ agentRunId: 'run-1',
253
+ phase: 'run:resumed',
254
+ startedAt: '2025-01-15T10:02:00Z',
255
+ durationMs: 0,
256
+ },
257
+ {
258
+ agentRunId: 'run-1',
259
+ phase: 'requirements:2',
260
+ startedAt: '2025-01-15T10:02:01Z',
261
+ completedAt: '2025-01-15T10:03:30Z',
262
+ durationMs: 89000,
263
+ waitingApprovalAt: '2025-01-15T10:03:00Z',
264
+ approvalWaitMs: 15000,
265
+ },
266
+ {
267
+ agentRunId: 'run-1',
268
+ phase: 'research',
269
+ startedAt: '2025-01-15T10:03:30Z',
270
+ completedAt: '2025-01-15T10:05:00Z',
271
+ durationMs: 90000,
272
+ },
273
+ {
274
+ agentRunId: 'run-1',
275
+ phase: 'run:completed',
276
+ startedAt: '2025-01-15T10:05:00Z',
277
+ durationMs: 0,
278
+ },
279
+ ],
280
+ rejectionFeedback: [
281
+ {
282
+ iteration: 1,
283
+ message: 'The requirements are missing error handling for edge cases',
284
+ phase: 'requirements',
285
+ },
286
+ ],
287
+ loading: false,
288
+ error: null,
289
+ },
290
+ };
219
291
  /** Approval wait indicators — phases with approval wait sub-rows. */
220
292
  export const WithApprovalWaits = {
221
293
  args: {
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAaxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AAiD3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAG3B,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAmBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,GAClB,EAAE,sBAAsB,2CA2MxB"}
1
+ {"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAaxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AAiD3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAG3B,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,GAClB,EAAE,sBAAsB,2CA4MxB"}
@@ -51,7 +51,7 @@ async function fetchActivity(featureId) {
51
51
  const result = await getFeaturePhaseTimings(featureId);
52
52
  if ('error' in result)
53
53
  throw new Error(result.error);
54
- return result.timings;
54
+ return { timings: result.timings, rejectionFeedback: result.rejectionFeedback };
55
55
  }
56
56
  async function fetchPlan(featureId) {
57
57
  const result = await getFeaturePlan(featureId);
@@ -115,7 +115,7 @@ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, prdData,
115
115
  fetchTab(tab);
116
116
  }
117
117
  }, [fetchTab]);
118
- return (_jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: _jsxs(Tabs, { value: activeTab, onValueChange: handleTabChange, className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "shrink-0 overflow-x-auto px-4 pt-4", children: _jsx(TabsList, { className: "flex w-full", children: visibleTabDefs.map((tab) => (_jsx(TabsTrigger, { value: tab.key, className: "flex-1", children: tab.label }, tab.key))) }) }), _jsx(TabsContent, { value: "overview", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(OverviewTab, { data: featureNode }) }), _jsx(TabsContent, { value: "activity", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(ActivityTab, { timings: tabs.activity.data, loading: tabs.activity.loading, error: tabs.activity.error }) }), _jsx(TabsContent, { value: "log", className: "mt-0 flex-1 overflow-hidden", children: _jsx(LogTab, { content: featureLogs.content, isConnected: featureLogs.isConnected, error: featureLogs.error }) }), _jsx(TabsContent, { value: "plan", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(PlanTab, { plan: tabs.plan.data, loading: tabs.plan.loading, error: tabs.plan.error }) }), visibleTabs.includes('prd-review') ? (_jsx(TabsContent, { value: "prd-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: prdData ? (_jsx(PrdQuestionnaire, { data: prdData, selections: prdSelections ?? {}, onSelect: onPrdSelect ?? (() => undefined), onApprove: onPrdApprove ?? (() => undefined), onReject: onPrdReject, isProcessing: isPrdLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('tech-decisions') ? (_jsx(TabsContent, { value: "tech-decisions", className: "mt-0 flex min-h-0 flex-1 flex-col", children: techData ? (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(TechDecisionsContent, { data: techData }) }), _jsx(DrawerActionBarForTech, { onApprove: onTechApprove ?? (() => undefined), onReject: onTechReject, isProcessing: isTechLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })] })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('product-decisions') ? (_jsx(TabsContent, { value: "product-decisions", className: "mt-0 flex-1 overflow-y-auto", children: productData === null ? (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) : productData ? (_jsx(ProductDecisionsSummary, { data: productData })) : (_jsx("p", { className: "text-muted-foreground p-4 text-center text-sm", children: "No product decisions available." })) })) : null, visibleTabs.includes('merge-review') ? (_jsx(TabsContent, { value: "merge-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: mergeData ? (_jsx(MergeReview, { data: mergeData, onApprove: onMergeApprove ?? (() => undefined), onReject: onMergeReject, isProcessing: isMergeLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null] }) }));
118
+ return (_jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: _jsxs(Tabs, { value: activeTab, onValueChange: handleTabChange, className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "shrink-0 overflow-x-auto px-4 pt-4", children: _jsx(TabsList, { className: "flex w-full", children: visibleTabDefs.map((tab) => (_jsx(TabsTrigger, { value: tab.key, className: "flex-1", children: tab.label }, tab.key))) }) }), _jsx(TabsContent, { value: "overview", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(OverviewTab, { data: featureNode }) }), _jsx(TabsContent, { value: "activity", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(ActivityTab, { timings: tabs.activity.data?.timings ?? null, loading: tabs.activity.loading, error: tabs.activity.error, rejectionFeedback: tabs.activity.data?.rejectionFeedback }) }), _jsx(TabsContent, { value: "log", className: "mt-0 flex-1 overflow-hidden", children: _jsx(LogTab, { content: featureLogs.content, isConnected: featureLogs.isConnected, error: featureLogs.error }) }), _jsx(TabsContent, { value: "plan", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(PlanTab, { plan: tabs.plan.data, loading: tabs.plan.loading, error: tabs.plan.error }) }), visibleTabs.includes('prd-review') ? (_jsx(TabsContent, { value: "prd-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: prdData ? (_jsx(PrdQuestionnaire, { data: prdData, selections: prdSelections ?? {}, onSelect: onPrdSelect ?? (() => undefined), onApprove: onPrdApprove ?? (() => undefined), onReject: onPrdReject, isProcessing: isPrdLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('tech-decisions') ? (_jsx(TabsContent, { value: "tech-decisions", className: "mt-0 flex min-h-0 flex-1 flex-col", children: techData ? (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(TechDecisionsContent, { data: techData }) }), _jsx(DrawerActionBarForTech, { onApprove: onTechApprove ?? (() => undefined), onReject: onTechReject, isProcessing: isTechLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })] })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('product-decisions') ? (_jsx(TabsContent, { value: "product-decisions", className: "mt-0 flex-1 overflow-y-auto", children: productData === null ? (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) : productData ? (_jsx(ProductDecisionsSummary, { data: productData })) : (_jsx("p", { className: "text-muted-foreground p-4 text-center text-sm", children: "No product decisions available." })) })) : null, visibleTabs.includes('merge-review') ? (_jsx(TabsContent, { value: "merge-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: mergeData ? (_jsx(MergeReview, { data: mergeData, onApprove: onMergeApprove ?? (() => undefined), onReject: onMergeReject, isProcessing: isMergeLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null] }) }));
119
119
  }
120
120
  // ── Private helper ──────────────────────────────────────────────────────
121
121
  function DrawerActionBarForTech({ onApprove, onReject, isProcessing, isRejecting, chatInput, onChatInputChange, }) {