@shepai/cli 1.37.0 → 1.37.1

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 (53) hide show
  1. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  2. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +1 -3
  3. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.d.ts.map +1 -1
  4. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js +2 -1
  5. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -1
  6. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +4 -1
  7. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
  8. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +2 -1
  9. package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
  10. package/dist/src/presentation/cli/commands/feat/show.command.js +21 -2
  11. package/dist/tsconfig.build.tsbuildinfo +1 -1
  12. package/package.json +1 -1
  13. package/web/.next/BUILD_ID +1 -1
  14. package/web/.next/build-manifest.json +2 -2
  15. package/web/.next/cache/.previewinfo +1 -1
  16. package/web/.next/cache/.rscinfo +1 -1
  17. package/web/.next/cache/config.json +3 -3
  18. package/web/.next/fallback-build-manifest.json +2 -2
  19. package/web/.next/prerender-manifest.json +3 -3
  20. package/web/.next/required-server-files.js +1 -1
  21. package/web/.next/required-server-files.json +1 -1
  22. package/web/.next/server/app/_global-error.html +2 -2
  23. package/web/.next/server/app/_global-error.rsc +1 -1
  24. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  25. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  26. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  27. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  28. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  29. package/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
  30. package/web/.next/server/pages/500.html +2 -2
  31. package/web/.next/server/server-reference-manifest.js +1 -1
  32. package/web/.next/server/server-reference-manifest.json +1 -1
  33. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  34. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  35. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  36. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  37. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  38. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  39. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  40. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  41. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  42. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  43. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  44. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
  45. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  46. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  47. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +1 -1
  48. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  49. package/web/.next/trace +1 -1
  50. package/web/.next/trace-build +1 -1
  51. /package/web/.next/static/{zoaB52IxAh-lSl8Qreb0t → UemLwbVtqCGOm4FHNOp05}/_buildManifest.js +0 -0
  52. /package/web/.next/static/{zoaB52IxAh-lSl8Qreb0t → UemLwbVtqCGOm4FHNOp05}/_clientMiddlewareManifest.json +0 -0
  53. /package/web/.next/static/{zoaB52IxAh-lSl8Qreb0t → UemLwbVtqCGOm4FHNOp05}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAyB1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA6C1D;AAgCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA6J/D"}
1
+ {"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAqB1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA6C1D;AAgCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA0J/D"}
@@ -19,7 +19,7 @@ import { AgentRunStatus } from '../../../../domain/generated/output.js';
19
19
  import { initializeSettings } from '../../../services/settings.service.js';
20
20
  import { InitializeSettingsUseCase } from '../../../../application/use-cases/settings/initialize-settings.use-case.js';
21
21
  import { setHeartbeatContext } from './heartbeat.js';
22
- import { setPhaseTimingContext, recordApprovalWaitStart, getLastTimingId, } from './phase-timing-context.js';
22
+ import { setPhaseTimingContext } from './phase-timing-context.js';
23
23
  import { setLifecycleContext } from './lifecycle-context.js';
24
24
  import { generatePrYaml } from './nodes/pr-yaml-generator.js';
25
25
  /**
@@ -193,8 +193,6 @@ export async function runWorker(args) {
193
193
  // Check if graph was interrupted (human-in-the-loop approval needed)
194
194
  const interruptPayload = result.__interrupt__;
195
195
  if (interruptPayload && interruptPayload.length > 0) {
196
- // Record approval wait start on the last phase timing
197
- await recordApprovalWaitStart(getLastTimingId());
198
196
  const now = new Date();
199
197
  await runRepository.updateStatus(args.runId, AgentRunStatus.waitingApproval, {
200
198
  updatedAt: now,
@@ -1 +1 @@
1
- {"version":3,"file":"implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAiErD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,IAG5C,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CA+K7E"}
1
+ {"version":3,"file":"implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAqErD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,IAG5C,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAgL7E"}
@@ -12,7 +12,7 @@ import { join } from 'node:path';
12
12
  import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
13
13
  import { createNodeLogger, readSpecFile, buildExecutorOptions, shouldInterrupt, safeYamlLoad, retryExecute, getCompletedPhases, markPhaseComplete, } from './node-helpers.js';
14
14
  import { reportNodeStart } from '../heartbeat.js';
15
- import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
15
+ import { recordPhaseStart, recordPhaseEnd, recordApprovalWaitStart, } from '../phase-timing-context.js';
16
16
  import { updateNodeLifecycle } from '../lifecycle-context.js';
17
17
  import { buildImplementPhasePrompt, } from './prompts/implement.prompt.js';
18
18
  /**
@@ -145,6 +145,7 @@ export function createImplementNode(executor) {
145
145
  await recordPhaseEnd(implementTimingId, Date.now() - startTime);
146
146
  if (shouldInterrupt('implement', state.approvalGates)) {
147
147
  log.info('Interrupting for human approval');
148
+ await recordApprovalWaitStart(implementTimingId);
148
149
  interrupt({
149
150
  node: 'implement',
150
151
  message: `Implementation complete: ${totalTasks} tasks across ${totalPhases} phases. Approve to finish.`,
@@ -1 +1 @@
1
- {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAC;AACrG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAOlH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,aAAa,CAAC;IAC5B,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAChF,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;CACpE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAqJ7E"}
1
+ {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAC;AACrG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAWlH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,aAAa,CAAC;IAC5B,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAChF,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;CACpE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAwJ7E"}
@@ -13,7 +13,7 @@ import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
13
13
  import { SdlcLifecycle, PrStatus } from '../../../../../domain/generated/output.js';
14
14
  import { createNodeLogger, shouldInterrupt } from './node-helpers.js';
15
15
  import { reportNodeStart } from '../heartbeat.js';
16
- import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
16
+ import { recordPhaseStart, recordPhaseEnd, recordApprovalWaitStart, } from '../phase-timing-context.js';
17
17
  import { updateNodeLifecycle } from '../lifecycle-context.js';
18
18
  /**
19
19
  * Factory that creates the merge node function.
@@ -82,6 +82,9 @@ export function createMergeNode(deps) {
82
82
  // --- Step 4: Merge approval gate ---
83
83
  if (shouldInterrupt('merge', state.approvalGates)) {
84
84
  log.info('Interrupting for merge approval');
85
+ // Close timing before interrupt so the pre-approval work has a duration
86
+ await recordPhaseEnd(mergeTimingId, Date.now() - startTime);
87
+ await recordApprovalWaitStart(mergeTimingId);
85
88
  const diffSummary = await gitPrService.getPrDiffSummary(cwd, baseBranch);
86
89
  interrupt({
87
90
  node: 'merge',
@@ -1 +1 @@
1
- {"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM;kBAE/B,MAAM,GAAG,IAAI;mBAIZ,MAAM,GAAG,IAAI;EAK/B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,qBAAqB,CAMpF;AAeD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAS3F;AAMD,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,mBAAmB,GAAG,eAAe,GAAG,SAAS,CAAC;AAMhG;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAKjE;AAED,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,EAC9B,SAAS,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAW5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAwB1F;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GACjE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAgFnE"}
1
+ {"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AASrD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM;kBAE/B,MAAM,GAAG,IAAI;mBAIZ,MAAM,GAAG,IAAI;EAK/B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,qBAAqB,CAMpF;AAeD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAS3F;AAMD,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,mBAAmB,GAAG,eAAe,GAAG,SAAS,CAAC;AAMhG;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAKjE;AAED,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,EAC9B,SAAS,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAW5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAwB1F;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GACjE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAiFnE"}
@@ -9,7 +9,7 @@ import { readFileSync, writeFileSync } from 'node:fs';
9
9
  import { join } from 'node:path';
10
10
  import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
11
11
  import { reportNodeStart } from '../heartbeat.js';
12
- import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
12
+ import { recordPhaseStart, recordPhaseEnd, recordApprovalWaitStart, } from '../phase-timing-context.js';
13
13
  import { updateNodeLifecycle } from '../lifecycle-context.js';
14
14
  /**
15
15
  * Create a scoped logger that prefixes messages with the node name.
@@ -245,6 +245,7 @@ export function executeNode(nodeName, executor, buildPrompt) {
245
245
  // Human-in-the-loop: interrupt after node execution for review
246
246
  if (shouldInterrupt(nodeName, state.approvalGates)) {
247
247
  log.info('Interrupting for human approval');
248
+ await recordApprovalWaitStart(timingId);
248
249
  interrupt({
249
250
  node: nodeName,
250
251
  result: result.result.slice(0, 500),
@@ -1 +1 @@
1
- {"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmFpC,wBAAgB,iBAAiB,IAAI,OAAO,CAiO3C"}
1
+ {"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmFpC,wBAAgB,iBAAiB,IAAI,OAAO,CAwP3C"}
@@ -131,7 +131,9 @@ export function createShowCommand() {
131
131
  if (t.completedAt && t.durationMs != null) {
132
132
  const ms = Number(t.durationMs);
133
133
  const secs = (ms / 1000).toFixed(1);
134
- const barLen = maxDurationMs > 0 ? Math.max(1, Math.round((ms / maxDurationMs) * MAX_BAR)) : 1;
134
+ const barLen = maxDurationMs > 0
135
+ ? Math.min(MAX_BAR, Math.max(1, Math.round((ms / maxDurationMs) * MAX_BAR)))
136
+ : 1;
135
137
  const bar = `${colors.success('\u2588'.repeat(barLen))}${colors.muted('\u2591'.repeat(MAX_BAR - barLen))}`;
136
138
  lines.push(`${label} ${bar} ${secs}s`);
137
139
  }
@@ -151,13 +153,30 @@ export function createShowCommand() {
151
153
  }
152
154
  // Show approval wait time under gated phases
153
155
  if (t.approvalWaitMs != null && Number(t.approvalWaitMs) > 0) {
156
+ // Completed approval wait - show final duration
154
157
  const waitMs = Number(t.approvalWaitMs);
155
158
  const waitSecs = (waitMs / 1000).toFixed(1);
156
159
  const waitLabel = ' \u21b3 approval'.padEnd(16);
157
- const waitBarLen = maxDurationMs > 0 ? Math.max(1, Math.round((waitMs / maxDurationMs) * MAX_BAR)) : 1;
160
+ const waitBarLen = maxDurationMs > 0
161
+ ? Math.min(MAX_BAR, Math.max(1, Math.round((waitMs / maxDurationMs) * MAX_BAR)))
162
+ : 1;
158
163
  const waitBar = `${colors.warning('\u2588'.repeat(waitBarLen))}${colors.muted('\u2591'.repeat(MAX_BAR - waitBarLen))}`;
159
164
  lines.push(`${waitLabel} ${waitBar} ${waitSecs}s`);
160
165
  }
166
+ else if (isLast && isWaiting && t.waitingApprovalAt) {
167
+ // Live approval wait - show elapsed time
168
+ const waitStart = t.waitingApprovalAt instanceof Date
169
+ ? t.waitingApprovalAt.getTime()
170
+ : Number(t.waitingApprovalAt);
171
+ const waitElapsedMs = Math.max(0, Date.now() - waitStart);
172
+ const waitSecs = (waitElapsedMs / 1000).toFixed(1);
173
+ const waitLabel = ' \u21b3 approval'.padEnd(16);
174
+ const waitBarLen = maxDurationMs > 0
175
+ ? Math.min(MAX_BAR, Math.max(1, Math.round((waitElapsedMs / maxDurationMs) * MAX_BAR)))
176
+ : 1;
177
+ const waitBar = `${colors.warning('\u2588'.repeat(waitBarLen))}${colors.muted('\u2591'.repeat(MAX_BAR - waitBarLen))}`;
178
+ lines.push(`${waitLabel} ${waitBar} ${waitSecs}s (waiting)`);
179
+ }
161
180
  }
162
181
  // Summary totals
163
182
  const totalExecMs = timings.reduce((sum, t) => sum + (t.durationMs != null ? Number(t.durationMs) : 0), 0);