@shepai/cli 1.122.1 → 1.122.2-pr360.dfb75fe

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 (142) hide show
  1. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
  2. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +21 -4
  3. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts +7 -1
  4. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts.map +1 -1
  5. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.js +24 -2
  6. package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.d.ts.map +1 -1
  7. package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.js +10 -3
  8. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/claude-code.json +9 -4
  9. package/dist/src/presentation/cli/commands/install.command.js +8 -1
  10. package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts +2 -0
  11. package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts.map +1 -1
  12. package/dist/src/presentation/web/app/actions/check-agent-auth.js +8 -1
  13. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +1 -1
  14. package/dist/src/presentation/web/components/features/tools/tool-card.stories.js +1 -1
  15. package/dist/src/presentation/web/components/features/tools/tools-page-client.stories.js +1 -1
  16. package/dist/tsconfig.build.tsbuildinfo +1 -1
  17. package/package.json +1 -1
  18. package/web/.next/BUILD_ID +1 -1
  19. package/web/.next/build-manifest.json +2 -2
  20. package/web/.next/fallback-build-manifest.json +2 -2
  21. package/web/.next/prerender-manifest.json +3 -3
  22. package/web/.next/required-server-files.js +3 -3
  23. package/web/.next/required-server-files.json +3 -3
  24. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +22 -22
  25. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  26. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  27. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +28 -28
  28. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  29. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +28 -28
  31. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  32. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  33. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +20 -20
  34. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  35. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  36. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +22 -22
  37. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  38. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  39. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +28 -28
  40. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  41. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  42. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +28 -28
  43. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  44. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  45. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +20 -20
  46. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  47. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +20 -20
  49. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  50. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  51. package/web/.next/server/app/_global-error.html +2 -2
  52. package/web/.next/server/app/_global-error.rsc +1 -1
  53. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  54. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  55. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  56. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  57. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  58. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  59. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
  61. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  62. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  63. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  64. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  65. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  66. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  67. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  68. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  69. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  70. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  71. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  72. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js +1 -1
  73. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js.map +1 -1
  74. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js +1 -1
  75. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js.map +1 -1
  76. package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js +1 -1
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js.map +1 -1
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
  84. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
  85. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  86. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  87. package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +2 -2
  88. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js +1 -1
  89. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js.map +1 -1
  90. package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js +2 -2
  91. package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js.map +1 -1
  92. package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +2 -2
  93. package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js +1 -1
  94. package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js.map +1 -1
  95. package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js +1 -1
  96. package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js.map +1 -1
  97. package/web/.next/server/chunks/ssr/{_b294a667._.js → _004b791b._.js} +2 -2
  98. package/web/.next/server/chunks/ssr/{_b294a667._.js.map → _004b791b._.js.map} +1 -1
  99. package/web/.next/server/chunks/ssr/_0dc2cfd3._.js +1 -1
  100. package/web/.next/server/chunks/ssr/_0dc2cfd3._.js.map +1 -1
  101. package/web/.next/server/chunks/ssr/{_469c5451._.js → _0ee2702f._.js} +2 -2
  102. package/web/.next/server/chunks/ssr/{_469c5451._.js.map → _0ee2702f._.js.map} +1 -1
  103. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  104. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  105. package/web/.next/server/chunks/ssr/{_92d851b4._.js → _1c4cecde._.js} +2 -2
  106. package/web/.next/server/chunks/ssr/{_92d851b4._.js.map → _1c4cecde._.js.map} +1 -1
  107. package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
  108. package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  110. package/web/.next/server/chunks/ssr/_cc77a143._.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_5f039db1._.js +2 -2
  114. package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js +1 -1
  116. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  118. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  120. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  121. package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js +2 -2
  122. package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js.map +1 -1
  123. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  124. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  125. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  126. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  127. package/web/.next/server/pages/500.html +2 -2
  128. package/web/.next/server/server-reference-manifest.js +1 -1
  129. package/web/.next/server/server-reference-manifest.json +34 -34
  130. package/web/.next/static/chunks/{df85e52b1afb7340.js → 0dd2d4fcafd8772b.js} +1 -1
  131. package/web/.next/static/chunks/{e6a2fb8707e079ff.js → 1b5419c02d253fae.js} +1 -1
  132. package/web/.next/static/chunks/{37ac7fe1cd493293.js → 1e6bfbd7936bba25.js} +1 -1
  133. package/web/.next/static/chunks/{e9c3fbbeb418cbfa.js → 349c47b3b993ae54.js} +1 -1
  134. package/web/.next/static/chunks/{658fc2f5f65cf3b5.js → 37634985311cc4c6.js} +2 -2
  135. package/web/.next/static/chunks/{9df4681de92ebfc3.js → 6c4aa963056c0bc2.js} +1 -1
  136. package/web/.next/static/chunks/{941c13dcdb1978a4.js → 8e816c7f48f7653d.js} +2 -2
  137. package/web/.next/static/chunks/{50dd80c8aafa3b20.js → 9eb4f613f1e35899.js} +1 -1
  138. package/web/.next/static/chunks/{11e4439096f8d652.js → d05a044cbbedbd56.js} +1 -1
  139. package/web/.next/static/chunks/{78ab7b134f0649ac.js → eb165ab35b356164.js} +1 -1
  140. /package/web/.next/static/{hsK1x0unrjI_pUsvQhn6P → CMhbAJyvRj6ct2bZgc0Yp}/_buildManifest.js +0 -0
  141. /package/web/.next/static/{hsK1x0unrjI_pUsvQhn6P → CMhbAJyvRj6ct2bZgc0Yp}/_clientMiddlewareManifest.json +0 -0
  142. /package/web/.next/static/{hsK1x0unrjI_pUsvQhn6P → CMhbAJyvRj6ct2bZgc0Yp}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"feature-agent-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAOpG,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AASlF,OAAO,EAAE,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;CACjD;AA0HD;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,qBAAqB,GAAG,cAAc,EACtD,YAAY,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAwEnC"}
1
+ {"version":3,"file":"feature-agent-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAOpG,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAclF,OAAO,EAAE,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;CACjD;AAwID;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,qBAAqB,GAAG,cAAc,EACtD,YAAY,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAgFnC"}
@@ -11,7 +11,7 @@ import { createRepairNode } from './nodes/repair.node.js';
11
11
  import { validateSpecAnalyze, validateSpecRequirements } from './nodes/schemas/spec.schema.js';
12
12
  import { validateResearch } from './nodes/schemas/research.schema.js';
13
13
  import { validatePlan, validateTasks } from './nodes/schemas/plan.schema.js';
14
- import { readSpecFile, safeYamlLoad, createNodeLogger } from './nodes/node-helpers.js';
14
+ import { readSpecFile, safeYamlLoad, createNodeLogger, getCompletedPhases, } from './nodes/node-helpers.js';
15
15
  // Re-export state types for consumers
16
16
  export { FeatureAgentAnnotation } from './state.js';
17
17
  /**
@@ -54,6 +54,18 @@ function createPlanTasksValidator() {
54
54
  const log = createNodeLogger('validate:plan+tasks');
55
55
  return async (state) => {
56
56
  log.activate();
57
+ // Skip validation when the successor phase (implement) is already completed.
58
+ // This proves validation already passed and the pipeline progressed beyond it.
59
+ // Same logic as createValidateNode's successorPhase guard.
60
+ if (getCompletedPhases(state.specDir).includes('implement')) {
61
+ log.info("Successor phase 'implement' already completed, skipping validation");
62
+ return {
63
+ lastValidationTarget: 'plan.yaml+tasks.yaml',
64
+ lastValidationErrors: [],
65
+ validationRetries: 0,
66
+ messages: ["[validate:plan+tasks] SKIP (successor 'implement' already completed)"],
67
+ };
68
+ }
57
69
  log.info('Validating plan.yaml and tasks.yaml');
58
70
  const allErrors = [];
59
71
  // Validate plan.yaml
@@ -145,9 +157,14 @@ export function createFeatureAgentGraph(depsOrExecutor, checkpointer) {
145
157
  .addNode('plan', createPlanNode(executor))
146
158
  .addNode('implement', createImplementNode(executor))
147
159
  // --- Validate nodes ---
148
- .addNode('validate_spec_analyze', createValidateNode('spec.yaml', validateSpecAnalyze))
149
- .addNode('validate_spec_requirements', createValidateNode('spec.yaml', validateSpecRequirements))
150
- .addNode('validate_research', createValidateNode('research.yaml', validateResearch))
160
+ // Each validate node receives its SUCCESSOR phase name (the phase that runs
161
+ // after validation passes). On resume, validation is skipped only when the
162
+ // successor is already completed — proving this validation already passed.
163
+ // Using the successor (not the producer) avoids skipping validation when the
164
+ // producer ran successfully but validation itself failed.
165
+ .addNode('validate_spec_analyze', createValidateNode('spec.yaml', validateSpecAnalyze, 'requirements'))
166
+ .addNode('validate_spec_requirements', createValidateNode('spec.yaml', validateSpecRequirements, 'research'))
167
+ .addNode('validate_research', createValidateNode('research.yaml', validateResearch, 'plan'))
151
168
  .addNode('validate_plan_tasks', createPlanTasksValidator())
152
169
  // --- Repair nodes ---
153
170
  .addNode('repair_spec_analyze', createRepairNode('spec.yaml', executor))
@@ -6,7 +6,13 @@ type SchemaValidator = (data: unknown) => ValidationResult;
6
6
  *
7
7
  * On success: resets validationRetries to 0, clears errors.
8
8
  * On failure: increments validationRetries, sets errors for repair node.
9
+ *
10
+ * @param successorPhase - The phase that runs AFTER this validation passes.
11
+ * If provided, skip validation when the successor is already completed — this
12
+ * proves the validation already passed in a prior run and the pipeline progressed
13
+ * beyond it. Checking the successor (not the producer) avoids skipping validation
14
+ * when the producer ran but validation itself failed.
9
15
  */
10
- export declare function createValidateNode(filename: string, schema: SchemaValidator): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
16
+ export declare function createValidateNode(filename: string, schema: SchemaValidator, successorPhase?: string): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
11
17
  export {};
12
18
  //# sourceMappingURL=validate.node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,gBAAgB,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,GACtB,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAuDnE"}
1
+ {"version":3,"file":"validate.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAQhE,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,gBAAgB,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAyEnE"}
@@ -1,14 +1,36 @@
1
- import { readSpecFile, safeYamlLoad, createNodeLogger } from './node-helpers.js';
1
+ import { readSpecFile, safeYamlLoad, createNodeLogger, getCompletedPhases, } from './node-helpers.js';
2
2
  /**
3
3
  * Factory that creates a validate node for a specific YAML file.
4
4
  *
5
5
  * On success: resets validationRetries to 0, clears errors.
6
6
  * On failure: increments validationRetries, sets errors for repair node.
7
+ *
8
+ * @param successorPhase - The phase that runs AFTER this validation passes.
9
+ * If provided, skip validation when the successor is already completed — this
10
+ * proves the validation already passed in a prior run and the pipeline progressed
11
+ * beyond it. Checking the successor (not the producer) avoids skipping validation
12
+ * when the producer ran but validation itself failed.
7
13
  */
8
- export function createValidateNode(filename, schema) {
14
+ export function createValidateNode(filename, schema, successorPhase) {
9
15
  const log = createNodeLogger(`validate:${filename}`);
10
16
  return async (state) => {
11
17
  log.activate();
18
+ // Skip validation when the successor phase is already completed.
19
+ // This means: the validation already passed in a prior run AND the next phase
20
+ // ran successfully. On resume, LangGraph replays nodes from the last checkpoint.
21
+ // The producer node skips (via getCompletedPhases), but if we only checked the
22
+ // producer we'd also skip validation when it previously FAILED (since
23
+ // markPhaseComplete runs before validation). Checking the successor is safe:
24
+ // if the successor completed, this validation must have passed to get there.
25
+ if (successorPhase && getCompletedPhases(state.specDir).includes(successorPhase)) {
26
+ log.info(`Successor phase '${successorPhase}' already completed, skipping validation`);
27
+ return {
28
+ lastValidationTarget: filename,
29
+ lastValidationErrors: [],
30
+ validationRetries: 0,
31
+ messages: [`[validate:${filename}] SKIP (successor '${successorPhase}' already completed)`],
32
+ };
33
+ }
12
34
  log.info(`Validating ${filename}`);
13
35
  const content = readSpecFile(state.specDir, filename);
14
36
  if (!content) {
@@ -1 +1 @@
1
- {"version":3,"file":"tool-installer.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/tool-installer/tool-installer.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sEAAsE,CAAC;AAClH,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EAEnB,MAAM,qCAAqC,CAAC;AA2B7C,qBACa,wBAAyB,YAAW,qBAAqB;IACpE;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAoC1E;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAqB9D;;;OAGG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,sBAAsB,CAAC;IAgFlC;;OAEG;IACH,OAAO,CAAC,6BAA6B;CA4BtC"}
1
+ {"version":3,"file":"tool-installer.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/tool-installer/tool-installer.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sEAAsE,CAAC;AAClH,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EAEnB,MAAM,qCAAqC,CAAC;AA2B7C,qBACa,wBAAyB,YAAW,qBAAqB;IACpE;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAoC1E;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAqB9D;;;OAGG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,sBAAsB,CAAC;IAwFlC;;OAEG;IACH,OAAO,CAAC,6BAA6B;CA4BtC"}
@@ -107,9 +107,14 @@ let ToolInstallerServiceImpl = class ToolInstallerServiceImpl {
107
107
  }
108
108
  return new Promise((resolve) => {
109
109
  let output = '';
110
+ // Inherit stdin when running in an interactive terminal so that commands
111
+ // requiring sudo can prompt the user for a password. In non-interactive
112
+ // contexts (web UI, CI) stdin is piped and closed immediately to prevent
113
+ // the process from hanging waiting for input.
114
+ const isInteractive = process.stdin.isTTY === true;
110
115
  const child = spawn(installCommand.command, [], {
111
116
  shell: true,
112
- stdio: ['pipe', 'pipe', 'pipe'],
117
+ stdio: [isInteractive ? 'inherit' : 'pipe', 'pipe', 'pipe'],
113
118
  env: {
114
119
  ...process.env,
115
120
  DEBIAN_FRONTEND: 'noninteractive',
@@ -117,8 +122,10 @@ let ToolInstallerServiceImpl = class ToolInstallerServiceImpl {
117
122
  GPG_TTY: '',
118
123
  },
119
124
  });
120
- // Close stdin immediately to prevent interactive prompts
121
- child.stdin?.end();
125
+ // Close stdin in non-interactive mode to prevent prompts from hanging
126
+ if (!isInteractive) {
127
+ child.stdin?.end();
128
+ }
122
129
  // Stream output from stdout and stderr
123
130
  const pipeOutput = (stream) => {
124
131
  if (!stream)
@@ -12,13 +12,17 @@
12
12
  "commands": {
13
13
  "linux": "curl -fsSL https://claude.ai/install.sh | bash",
14
14
  "darwin": "curl -fsSL https://claude.ai/install.sh | bash",
15
- "win32": "npm install -g @anthropic-ai/claude-code"
15
+ "win32": "powershell -Command \"iwr -useb https://claude.ai/install.ps1 | iex\""
16
16
  },
17
17
  "timeout": 300000,
18
- "documentationUrl": "https://code.claude.com/docs/en/overview",
18
+ "documentationUrl": "https://docs.anthropic.com/en/docs/claude-code/overview",
19
19
  "verifyCommand": "claude --version",
20
20
  "autoInstall": true,
21
- "openDirectory": "cd {dir} && exec claude",
21
+ "openDirectory": {
22
+ "linux": "cd {dir} && exec claude",
23
+ "darwin": "cd {dir} && exec claude",
24
+ "win32": "cd /d {dir} && claude"
25
+ },
22
26
  "spawnOptions": {
23
27
  "shell": true,
24
28
  "stdio": "inherit",
@@ -26,6 +30,7 @@
26
30
  },
27
31
  "terminalCommand": {
28
32
  "linux": "x-terminal-emulator -e bash -c 'cd {dir} && exec claude'",
29
- "darwin": "open -a Terminal.app bash -c 'cd {dir} && exec claude'"
33
+ "darwin": "osascript -e 'tell application \"Terminal\" to do script \"cd {dir} && exec claude\"'",
34
+ "win32": "start cmd /k \"cd /d {dir} && claude\""
30
35
  }
31
36
  }
@@ -117,7 +117,14 @@ function printInstallInstructions(metadata) {
117
117
  // Print open directory command if available
118
118
  if (metadata.openDirectory) {
119
119
  console.log(fmt.heading('Open Directory'));
120
- console.log(`${colors.muted('$')} ${metadata.openDirectory}`);
120
+ if (typeof metadata.openDirectory === 'string') {
121
+ console.log(`${colors.muted('$')} ${metadata.openDirectory}`);
122
+ }
123
+ else {
124
+ for (const [platform, cmd] of Object.entries(metadata.openDirectory)) {
125
+ console.log(`${colors.muted(`[${platform}]`)} ${cmd}`);
126
+ }
127
+ }
121
128
  console.log();
122
129
  }
123
130
  // Print documentation link
@@ -10,6 +10,8 @@ export interface AgentAuthStatus {
10
10
  binaryName: string | null;
11
11
  /** Instructions to authenticate if not authenticated */
12
12
  authCommand: string | null;
13
+ /** Platform-resolved install command (e.g. "npm install -g @google/gemini-cli") */
14
+ installCommand: string | null;
13
15
  }
14
16
  /**
15
17
  * Check agent tool installation + auth status.
@@ -1 +1 @@
1
- {"version":3,"file":"check-agent-auth.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/check-agent-auth.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wDAAwD;IACxD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA4FD;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAiF/D"}
1
+ {"version":3,"file":"check-agent-auth.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/check-agent-auth.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wDAAwD;IACxD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,mFAAmF;IACnF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AA4FD;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAwF/D"}
@@ -20,7 +20,7 @@ const AGENT_TOOL_MAP = {
20
20
  };
21
21
  const AGENT_BINARY_MAP = {
22
22
  'claude-code': 'claude',
23
- cursor: 'agent',
23
+ cursor: 'cursor-agent',
24
24
  'gemini-cli': 'gemini',
25
25
  };
26
26
  /**
@@ -113,6 +113,7 @@ export async function checkAgentAuth() {
113
113
  label: 'Unknown',
114
114
  binaryName: null,
115
115
  authCommand: null,
116
+ installCommand: null,
116
117
  };
117
118
  }
118
119
  const label = AGENT_LABELS[agentType] ?? agentType;
@@ -127,15 +128,18 @@ export async function checkAgentAuth() {
127
128
  label,
128
129
  binaryName: null,
129
130
  authCommand: null,
131
+ installCommand: null,
130
132
  };
131
133
  }
132
134
  // Check if tool is installed
133
135
  let installed = false;
136
+ let installCommand = null;
134
137
  try {
135
138
  const useCase = resolve('ListToolsUseCase');
136
139
  const tools = await useCase.execute();
137
140
  const tool = tools.find((t) => t.id === toolId);
138
141
  installed = tool?.status.status === 'available';
142
+ installCommand = tool?.installCommand ?? null;
139
143
  }
140
144
  catch {
141
145
  installed = false;
@@ -148,6 +152,7 @@ export async function checkAgentAuth() {
148
152
  label,
149
153
  binaryName,
150
154
  authCommand: binaryName ? `Install ${label} first` : null,
155
+ installCommand,
151
156
  };
152
157
  }
153
158
  // Tier 1: instant file/env check
@@ -160,6 +165,7 @@ export async function checkAgentAuth() {
160
165
  label,
161
166
  binaryName,
162
167
  authCommand: binaryName,
168
+ installCommand,
163
169
  };
164
170
  }
165
171
  // Tier 2: subprocess verify (best effort, ~200ms)
@@ -174,5 +180,6 @@ export async function checkAgentAuth() {
174
180
  label,
175
181
  binaryName,
176
182
  authCommand: authenticated ? null : binaryName,
183
+ installCommand,
177
184
  };
178
185
  }
@@ -70,7 +70,7 @@ function AgentAuthBanner({ status, onRetry, }) {
70
70
  }
71
71
  // Not installed
72
72
  if (!status.installed) {
73
- return (_jsxs("div", { className: "flex w-full flex-col gap-2 rounded-md bg-amber-500/10 px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-3 w-3 text-amber-600 dark:text-amber-400" }), _jsxs("span", { className: "text-[10px] font-medium text-amber-700 dark:text-amber-300", children: [status.label, " not installed"] })] }), status.binaryName ? (_jsxs("div", { className: "rounded bg-zinc-900 px-2 py-1 font-mono text-[10px] text-zinc-300", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), "npm install -g ", status.binaryName] })) : null, _jsx("button", { type: "button", onClick: onRetry, className: "self-start text-[10px] font-medium text-amber-700 underline underline-offset-2 hover:text-amber-900 dark:text-amber-300 dark:hover:text-amber-100", children: "Re-check" })] }));
73
+ return (_jsxs("div", { className: "flex w-full flex-col gap-2 rounded-md bg-amber-500/10 px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-3 w-3 text-amber-600 dark:text-amber-400" }), _jsxs("span", { className: "text-[10px] font-medium text-amber-700 dark:text-amber-300", children: [status.label, " not installed"] })] }), status.installCommand ? (_jsxs("div", { className: "rounded bg-zinc-900 px-2 py-1 font-mono text-[10px] text-zinc-300", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), status.installCommand] })) : null, _jsx("button", { type: "button", onClick: onRetry, className: "self-start text-[10px] font-medium text-amber-700 underline underline-offset-2 hover:text-amber-900 dark:text-amber-300 dark:hover:text-amber-100", children: "Re-check" })] }));
74
74
  }
75
75
  // Installed but not authenticated
76
76
  return (_jsxs("div", { className: "flex w-full flex-col gap-2 rounded-md bg-amber-500/10 px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-3 w-3 text-amber-600 dark:text-amber-400" }), _jsxs("span", { className: "text-[10px] font-medium text-amber-700 dark:text-amber-300", children: [status.label, " needs authentication"] })] }), status.authCommand ? (_jsxs("div", { className: "rounded bg-zinc-900 px-2 py-1 font-mono text-[10px] text-zinc-300", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), status.authCommand] })) : null, _jsxs("div", { className: "flex items-center gap-2", children: [status.binaryName ? (_jsxs("button", { type: "button", "data-testid": "auth-banner-open-terminal", onClick: async () => {
@@ -28,7 +28,7 @@ const installedNoLaunchTool = {
28
28
  required: false,
29
29
  openDirectory: undefined,
30
30
  documentationUrl: 'https://claude.ai',
31
- installCommand: 'npm install -g @anthropic-ai/claude-code',
31
+ installCommand: 'curl -fsSL https://claude.ai/install.sh | bash',
32
32
  status: { status: 'available', toolName: 'claude-code' },
33
33
  author: 'Anthropic',
34
34
  website: 'https://claude.ai/code',
@@ -45,7 +45,7 @@ const mockTools = [
45
45
  required: false,
46
46
  openDirectory: undefined,
47
47
  documentationUrl: 'https://claude.ai/code',
48
- installCommand: 'npm install -g @anthropic-ai/claude-code',
48
+ installCommand: 'curl -fsSL https://claude.ai/install.sh | bash',
49
49
  status: { status: 'available', toolName: 'claude-code' },
50
50
  author: 'Anthropic',
51
51
  website: 'https://claude.ai/code',