@shepai/cli 1.52.1 → 1.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apis/json-schema/CiFixRecord.yaml +24 -0
- package/apis/json-schema/Feature.yaml +3 -0
- package/apis/json-schema/PullRequest.yaml +10 -0
- package/apis/json-schema/SdlcLifecycle.yaml +1 -0
- package/apis/json-schema/WorkflowConfig.yaml +15 -0
- package/dist/packages/core/src/application/ports/output/repositories/feature-repository.interface.d.ts +8 -0
- package/dist/packages/core/src/application/ports/output/repositories/feature-repository.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +12 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.d.ts +30 -0
- package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.js +74 -0
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +60 -16
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +2 -0
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.js +11 -4
- package/dist/packages/core/src/application/use-cases/features/update/update-feature-lifecycle.use-case.d.ts +28 -0
- package/dist/packages/core/src/application/use-cases/features/update/update-feature-lifecycle.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/features/update/update-feature-lifecycle.use-case.js +53 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +47 -1
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/domain/generated/output.js +1 -0
- package/dist/packages/core/src/domain/lifecycle-gates.d.ts +16 -0
- package/dist/packages/core/src/domain/lifecycle-gates.d.ts.map +1 -0
- package/dist/packages/core/src/domain/lifecycle-gates.js +19 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +12 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +3 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +8 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +28 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +12 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +52 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +7 -2
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/lifecycle-context.d.ts +27 -5
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/lifecycle-context.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/lifecycle-context.js +19 -16
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-helpers.d.ts +24 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-helpers.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-helpers.js +47 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts +43 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.js +118 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/{merge.node.d.ts → merge/merge.node.d.ts} +10 -4
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/{merge.node.js → merge/merge.node.js} +44 -17
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts +12 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +38 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts +4 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.js +13 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +29 -1
- package/dist/src/presentation/cli/commands/feat/ls.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/ls.command.js +39 -3
- package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/new.command.js +18 -0
- package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/show.command.js +20 -0
- package/dist/src/presentation/web/app/actions/create-feature.d.ts +1 -0
- package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/create-feature.js +2 -1
- package/dist/src/presentation/web/app/page.d.ts.map +1 -1
- package/dist/src/presentation/web/app/page.js +34 -6
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +11 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +52 -5
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +4 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +13 -4
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +2 -0
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +26 -8
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.d.ts +7 -0
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.js +20 -0
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.stories.d.ts +6 -0
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.stories.js +58 -0
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +5 -1
- package/dist/src/presentation/web/next.config.d.ts.map +1 -1
- package/dist/src/presentation/web/next.config.js +11 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/.tsbuildinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +5 -2
- package/web/.next/required-server-files.json +5 -2
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/page/server-reference-manifest.json +14 -14
- package/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_1fafa9db._.js +1 -1
- package/web/.next/server/chunks/ssr/_1fafa9db._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +15 -15
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +5 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +14 -14
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_1fafa9db._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +15 -15
- package/web/.next/standalone/src/presentation/web/app/actions/create-feature.ts +4 -1
- package/web/.next/standalone/src/presentation/web/app/page.tsx +36 -6
- package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +199 -2
- package/web/.next/standalone/src/presentation/web/components/common/feature-node/derive-feature-state.ts +5 -0
- package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +20 -1
- package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +43 -12
- package/web/.next/standalone/src/presentation/web/components/features/features-canvas/dependency-edge.stories.tsx +81 -0
- package/web/.next/standalone/src/presentation/web/components/features/features-canvas/dependency-edge.tsx +29 -0
- package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +9 -0
- package/web/.next/standalone/src/presentation/web/next.config.ts +11 -2
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/48309f9ad2a84b15.css +2 -0
- package/web/.next/static/chunks/5123ae1490fd2606.js +10 -0
- package/web/.next/static/chunks/{31e5030eed01a941.js → 68fb91b6eca14536.js} +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/next.config.mjs +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge-output-parser.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +0 -1
- package/web/.next/static/chunks/59b8bd47023e0249.css +0 -2
- package/web/.next/static/chunks/de88642301974a9c.js +0 -10
- /package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/{merge-output-parser.d.ts → merge/merge-output-parser.d.ts} +0 -0
- /package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/{merge-output-parser.js → merge/merge-output-parser.js} +0 -0
- /package/web/.next/static/{bBUbYZdszzvMJTi9A76CZ → OXSWdTgy-1XJBN9IJtQPz}/_buildManifest.js +0 -0
- /package/web/.next/static/{bBUbYZdszzvMJTi9A76CZ → OXSWdTgy-1XJBN9IJtQPz}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{bBUbYZdszzvMJTi9A76CZ → OXSWdTgy-1XJBN9IJtQPz}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
$schema: https://json-schema.org/draft/2020-12/schema
|
|
2
|
+
$id: CiFixRecord.yaml
|
|
3
|
+
type: object
|
|
4
|
+
properties:
|
|
5
|
+
attempt:
|
|
6
|
+
type: integer
|
|
7
|
+
minimum: -2147483648
|
|
8
|
+
maximum: 2147483647
|
|
9
|
+
description: 1-based attempt number
|
|
10
|
+
startedAt:
|
|
11
|
+
type: string
|
|
12
|
+
description: ISO timestamp when this attempt started
|
|
13
|
+
failureSummary:
|
|
14
|
+
type: string
|
|
15
|
+
description: First 500 chars of failure logs for this attempt
|
|
16
|
+
outcome:
|
|
17
|
+
type: string
|
|
18
|
+
description: "Outcome of this attempt: fixed, failed, or timeout"
|
|
19
|
+
required:
|
|
20
|
+
- attempt
|
|
21
|
+
- startedAt
|
|
22
|
+
- failureSummary
|
|
23
|
+
- outcome
|
|
24
|
+
description: Record of one CI fix attempt in the watch/fix loop
|
|
@@ -19,6 +19,16 @@ properties:
|
|
|
19
19
|
ciStatus:
|
|
20
20
|
$ref: CiStatus.yaml
|
|
21
21
|
description: CI pipeline status
|
|
22
|
+
ciFixAttempts:
|
|
23
|
+
type: integer
|
|
24
|
+
minimum: -2147483648
|
|
25
|
+
maximum: 2147483647
|
|
26
|
+
description: Number of CI fix attempts made
|
|
27
|
+
ciFixHistory:
|
|
28
|
+
type: array
|
|
29
|
+
items:
|
|
30
|
+
$ref: CiFixRecord.yaml
|
|
31
|
+
description: History of CI fix attempts
|
|
22
32
|
required:
|
|
23
33
|
- url
|
|
24
34
|
- number
|
|
@@ -9,6 +9,21 @@ properties:
|
|
|
9
9
|
approvalGateDefaults:
|
|
10
10
|
$ref: ApprovalGateDefaults.yaml
|
|
11
11
|
description: Default approval gate preferences for new features
|
|
12
|
+
ciMaxFixAttempts:
|
|
13
|
+
type: integer
|
|
14
|
+
minimum: -2147483648
|
|
15
|
+
maximum: 2147483647
|
|
16
|
+
description: "Maximum number of CI fix/push/watch iterations before giving up (default: 3)"
|
|
17
|
+
ciWatchTimeoutMs:
|
|
18
|
+
type: integer
|
|
19
|
+
minimum: -2147483648
|
|
20
|
+
maximum: 2147483647
|
|
21
|
+
description: "Timeout in milliseconds for watching a CI run (default: 600000 = 10 minutes)"
|
|
22
|
+
ciLogMaxChars:
|
|
23
|
+
type: integer
|
|
24
|
+
minimum: -2147483648
|
|
25
|
+
maximum: 2147483647
|
|
26
|
+
description: "Maximum characters of CI failure logs to pass to the executor (default: 50000)"
|
|
12
27
|
required:
|
|
13
28
|
- openPrOnImplementationComplete
|
|
14
29
|
- approvalGateDefaults
|
|
@@ -66,6 +66,14 @@ export interface IFeatureRepository {
|
|
|
66
66
|
* @param feature - The feature with updated fields
|
|
67
67
|
*/
|
|
68
68
|
update(feature: Feature): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Returns all direct (non-recursive) children of the given parent feature ID.
|
|
71
|
+
* Children are ordered by creation time ascending.
|
|
72
|
+
*
|
|
73
|
+
* @param parentId - The parent feature ID
|
|
74
|
+
* @returns Array of direct child features
|
|
75
|
+
*/
|
|
76
|
+
findByParentId(parentId: string): Promise<Feature[]>;
|
|
69
77
|
/**
|
|
70
78
|
* Delete a feature by ID.
|
|
71
79
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-repository.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/repositories/feature-repository.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAE9C;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAExD;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAE1E;;;;;OAKG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEvD;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;;;OAIG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC"}
|
|
1
|
+
{"version":3,"file":"feature-repository.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/repositories/feature-repository.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAE9C;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAExD;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAE1E;;;;;OAKG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEvD;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;;;;;OAMG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAErD;;;;OAIG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC"}
|
package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts
CHANGED
|
@@ -189,5 +189,17 @@ export interface IGitPrService {
|
|
|
189
189
|
* @returns True if featureBranch is an ancestor of baseBranch
|
|
190
190
|
*/
|
|
191
191
|
verifyMerge(cwd: string, featureBranch: string, baseBranch: string): Promise<boolean>;
|
|
192
|
+
/**
|
|
193
|
+
* Retrieve failure logs for a CI run via `gh run view --log-failed`.
|
|
194
|
+
* Output is truncated to the first `logMaxChars` characters (head truncation).
|
|
195
|
+
* A notice is appended when truncation occurs.
|
|
196
|
+
*
|
|
197
|
+
* @param runId - GitHub Actions run ID (numeric string)
|
|
198
|
+
* @param branch - Branch name (informational, used in truncation notice)
|
|
199
|
+
* @param logMaxChars - Maximum characters to return (default 50_000)
|
|
200
|
+
* @returns Truncated failure log output
|
|
201
|
+
* @throws GitPrError with GH_NOT_FOUND or GIT_ERROR code on failure
|
|
202
|
+
*/
|
|
203
|
+
getFailureLogs(runId: string, branch: string, logMaxChars?: number): Promise<string>;
|
|
192
204
|
}
|
|
193
205
|
//# sourceMappingURL=git-pr-service.interface.d.ts.map
|
package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-pr-service.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/services/git-pr-service.interface.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"git-pr-service.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/services/git-pr-service.interface.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CheckAndUnblockFeaturesUseCase
|
|
3
|
+
*
|
|
4
|
+
* Evaluates whether blocked direct children of a parent feature are now
|
|
5
|
+
* eligible to start, and if so transitions them to Started and spawns their
|
|
6
|
+
* agents.
|
|
7
|
+
*
|
|
8
|
+
* Business Rules:
|
|
9
|
+
* - Only direct children of parentFeatureId are evaluated (no recursive traversal).
|
|
10
|
+
* Grandchildren stay Blocked until their own direct parent progresses.
|
|
11
|
+
* - Gate: parent lifecycle must be in POST_IMPLEMENTATION (Implementation, Review, Maintain).
|
|
12
|
+
* - Idempotent: already-Started children are not touched; calling execute() twice is safe.
|
|
13
|
+
* - spawn() is skipped for children missing agentRunId or specPath (defensive guard).
|
|
14
|
+
*
|
|
15
|
+
* Called from: UpdateFeatureLifecycleUseCase after every lifecycle transition.
|
|
16
|
+
*/
|
|
17
|
+
import type { IFeatureRepository } from '../../ports/output/repositories/feature-repository.interface.js';
|
|
18
|
+
import type { IFeatureAgentProcessService } from '../../ports/output/agents/feature-agent-process.interface.js';
|
|
19
|
+
export declare class CheckAndUnblockFeaturesUseCase {
|
|
20
|
+
private readonly featureRepo;
|
|
21
|
+
private readonly agentProcess;
|
|
22
|
+
constructor(featureRepo: IFeatureRepository, agentProcess: IFeatureAgentProcessService);
|
|
23
|
+
/**
|
|
24
|
+
* Check and unblock direct children of the given parent feature.
|
|
25
|
+
*
|
|
26
|
+
* @param parentFeatureId - ID of the feature whose children should be evaluated.
|
|
27
|
+
*/
|
|
28
|
+
execute(parentFeatureId: string): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=check-and-unblock-features.use-case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-and-unblock-features.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAGhH,qBACa,8BAA8B;IAET,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE1D,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAFkB,WAAW,EAAE,kBAAkB,EAE7D,YAAY,EAAE,2BAA2B;IAG5D;;;;OAIG;IACG,OAAO,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAiCtD"}
|
package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CheckAndUnblockFeaturesUseCase
|
|
3
|
+
*
|
|
4
|
+
* Evaluates whether blocked direct children of a parent feature are now
|
|
5
|
+
* eligible to start, and if so transitions them to Started and spawns their
|
|
6
|
+
* agents.
|
|
7
|
+
*
|
|
8
|
+
* Business Rules:
|
|
9
|
+
* - Only direct children of parentFeatureId are evaluated (no recursive traversal).
|
|
10
|
+
* Grandchildren stay Blocked until their own direct parent progresses.
|
|
11
|
+
* - Gate: parent lifecycle must be in POST_IMPLEMENTATION (Implementation, Review, Maintain).
|
|
12
|
+
* - Idempotent: already-Started children are not touched; calling execute() twice is safe.
|
|
13
|
+
* - spawn() is skipped for children missing agentRunId or specPath (defensive guard).
|
|
14
|
+
*
|
|
15
|
+
* Called from: UpdateFeatureLifecycleUseCase after every lifecycle transition.
|
|
16
|
+
*/
|
|
17
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
18
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
20
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
21
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
22
|
+
};
|
|
23
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
24
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
25
|
+
};
|
|
26
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
27
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
28
|
+
};
|
|
29
|
+
import { injectable, inject } from 'tsyringe';
|
|
30
|
+
import { SdlcLifecycle } from '../../../domain/generated/output.js';
|
|
31
|
+
import { POST_IMPLEMENTATION } from '../../../domain/lifecycle-gates.js';
|
|
32
|
+
let CheckAndUnblockFeaturesUseCase = class CheckAndUnblockFeaturesUseCase {
|
|
33
|
+
featureRepo;
|
|
34
|
+
agentProcess;
|
|
35
|
+
constructor(featureRepo, agentProcess) {
|
|
36
|
+
this.featureRepo = featureRepo;
|
|
37
|
+
this.agentProcess = agentProcess;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check and unblock direct children of the given parent feature.
|
|
41
|
+
*
|
|
42
|
+
* @param parentFeatureId - ID of the feature whose children should be evaluated.
|
|
43
|
+
*/
|
|
44
|
+
async execute(parentFeatureId) {
|
|
45
|
+
// Load parent and verify gate
|
|
46
|
+
const parent = await this.featureRepo.findById(parentFeatureId);
|
|
47
|
+
if (!parent || !POST_IMPLEMENTATION.has(parent.lifecycle)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// Load direct children
|
|
51
|
+
const children = await this.featureRepo.findByParentId(parentFeatureId);
|
|
52
|
+
// Unblock each blocked child
|
|
53
|
+
for (const child of children) {
|
|
54
|
+
if (child.lifecycle !== SdlcLifecycle.Blocked) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// Transition to Started
|
|
58
|
+
child.lifecycle = SdlcLifecycle.Started;
|
|
59
|
+
child.updatedAt = new Date();
|
|
60
|
+
await this.featureRepo.update(child);
|
|
61
|
+
// Spawn agent using fields set at feature creation time
|
|
62
|
+
if (child.agentRunId && child.specPath) {
|
|
63
|
+
this.agentProcess.spawn(child.id, child.agentRunId, child.repositoryPath, child.specPath, child.worktreePath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
CheckAndUnblockFeaturesUseCase = __decorate([
|
|
69
|
+
injectable(),
|
|
70
|
+
__param(0, inject('IFeatureRepository')),
|
|
71
|
+
__param(1, inject('IFeatureAgentProcessService')),
|
|
72
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
73
|
+
], CheckAndUnblockFeaturesUseCase);
|
|
74
|
+
export { CheckAndUnblockFeaturesUseCase };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/use-cases/features/create/create-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oEAAoE,CAAC;AAC7G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAC;AACrG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iEAAiE,CAAC;AACnH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gEAAgE,CAAC;AAC1G,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8DAA8D,CAAC;AAC5G,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uEAAuE,CAAC;AACnH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4DAA4D,CAAC;
|
|
1
|
+
{"version":3,"file":"create-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/use-cases/features/create/create-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oEAAoE,CAAC;AAC7G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAC;AACrG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iEAAiE,CAAC;AACnH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gEAAgE,CAAC;AAC1G,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8DAA8D,CAAC;AAC5G,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uEAAuE,CAAC;AACnH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4DAA4D,CAAC;AAGhG,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E,qBACa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAE7B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAE7B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAhBZ,WAAW,EAAE,kBAAkB,EAE/B,eAAe,EAAE,gBAAgB,EAEjC,YAAY,EAAE,2BAA2B,EAEzC,aAAa,EAAE,mBAAmB,EAElC,eAAe,EAAE,uBAAuB,EAExC,iBAAiB,EAAE,iBAAiB,EAEpC,YAAY,EAAE,YAAY,EAE1B,cAAc,EAAE,qBAAqB,EAErC,YAAY,EAAE,aAAa;IAGxC,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAyJvE"}
|
package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js
CHANGED
|
@@ -31,6 +31,7 @@ import { injectable, inject } from 'tsyringe';
|
|
|
31
31
|
import { randomUUID } from 'node:crypto';
|
|
32
32
|
import { SdlcLifecycle, AgentRunStatus } from '../../../../domain/generated/output.js';
|
|
33
33
|
import { getSettings } from '../../../../infrastructure/services/settings.service.js';
|
|
34
|
+
import { POST_IMPLEMENTATION } from '../../../../domain/lifecycle-gates.js';
|
|
34
35
|
import { MetadataGenerator } from './metadata-generator.js';
|
|
35
36
|
import { SlugResolver } from './slug-resolver.js';
|
|
36
37
|
let CreateFeatureUseCase = class CreateFeatureUseCase {
|
|
@@ -55,28 +56,67 @@ let CreateFeatureUseCase = class CreateFeatureUseCase {
|
|
|
55
56
|
this.gitPrService = gitPrService;
|
|
56
57
|
}
|
|
57
58
|
async execute(input) {
|
|
59
|
+
// Resolve parent feature and determine child initial lifecycle (FR-8, FR-9, FR-12, FR-19)
|
|
60
|
+
let initialLifecycle = SdlcLifecycle.Requirements;
|
|
61
|
+
let shouldSpawn = true;
|
|
62
|
+
// When creating a child feature, always use the parent's repositoryPath (the
|
|
63
|
+
// original repo root), not the caller's cwd which may be a worktree (FR-10).
|
|
64
|
+
let effectiveRepoPath = input.repositoryPath;
|
|
65
|
+
if (input.parentId) {
|
|
66
|
+
const parent = await this.featureRepo.findById(input.parentId);
|
|
67
|
+
if (!parent) {
|
|
68
|
+
throw new Error(`Parent feature not found: ${input.parentId}`);
|
|
69
|
+
}
|
|
70
|
+
// Use the parent's repositoryPath so the child worktree branches from the
|
|
71
|
+
// original repo, not from inside another worktree.
|
|
72
|
+
effectiveRepoPath = parent.repositoryPath;
|
|
73
|
+
// Cycle detection — O(depth) upward walk through ancestor chain (FR-19)
|
|
74
|
+
const visited = new Set([input.parentId]);
|
|
75
|
+
let cursor = parent.parentId;
|
|
76
|
+
while (cursor) {
|
|
77
|
+
if (visited.has(cursor)) {
|
|
78
|
+
throw new Error(`Cycle detected in feature dependency chain at feature: ${cursor}`);
|
|
79
|
+
}
|
|
80
|
+
visited.add(cursor);
|
|
81
|
+
const ancestor = await this.featureRepo.findById(cursor);
|
|
82
|
+
cursor = ancestor?.parentId ?? undefined;
|
|
83
|
+
}
|
|
84
|
+
// Two-gate lifecycle logic (FR-9):
|
|
85
|
+
// parent.lifecycle === Blocked → cascade block (FR-12)
|
|
86
|
+
// parent.lifecycle not in POST_IMPLEMENTATION → early gate not met → Blocked
|
|
87
|
+
// parent.lifecycle in POST_IMPLEMENTATION → gate satisfied → Started
|
|
88
|
+
if (parent.lifecycle === SdlcLifecycle.Blocked ||
|
|
89
|
+
!POST_IMPLEMENTATION.has(parent.lifecycle)) {
|
|
90
|
+
initialLifecycle = SdlcLifecycle.Blocked;
|
|
91
|
+
shouldSpawn = false;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
initialLifecycle = SdlcLifecycle.Started;
|
|
95
|
+
shouldSpawn = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
58
98
|
// Ensure the target directory is a git repository (auto-init if needed)
|
|
59
99
|
// Must run before slug resolution which needs git commands
|
|
60
|
-
await this.worktreeService.ensureGitRepository(
|
|
100
|
+
await this.worktreeService.ensureGitRepository(effectiveRepoPath);
|
|
61
101
|
const metadata = await this.metadataGenerator.generateMetadata(input.userInput);
|
|
62
102
|
const originalSlug = metadata.slug;
|
|
63
103
|
// Find a unique slug — the branch may exist from a previous (deleted) feature
|
|
64
|
-
const { slug, branch, warning } = await this.slugResolver.resolveUniqueSlug(originalSlug,
|
|
104
|
+
const { slug, branch, warning } = await this.slugResolver.resolveUniqueSlug(originalSlug, effectiveRepoPath);
|
|
65
105
|
// Determine next feature number for this repo
|
|
66
106
|
const existingFeatures = await this.featureRepo.list({
|
|
67
|
-
repositoryPath:
|
|
107
|
+
repositoryPath: effectiveRepoPath,
|
|
68
108
|
});
|
|
69
109
|
const featureNumber = existingFeatures.length + 1;
|
|
70
110
|
const now = new Date();
|
|
71
111
|
const runId = randomUUID();
|
|
72
112
|
// Create git worktree branching from the repo's default branch
|
|
73
|
-
const defaultBranch = await this.gitPrService.getDefaultBranch(
|
|
74
|
-
const worktreePath = this.worktreeService.getWorktreePath(
|
|
75
|
-
await this.worktreeService.create(
|
|
113
|
+
const defaultBranch = await this.gitPrService.getDefaultBranch(effectiveRepoPath);
|
|
114
|
+
const worktreePath = this.worktreeService.getWorktreePath(effectiveRepoPath, branch);
|
|
115
|
+
await this.worktreeService.create(effectiveRepoPath, branch, worktreePath, defaultBranch);
|
|
76
116
|
// Initialize spec directory — full user input goes into spec.yaml as-is
|
|
77
117
|
const { specDir } = await this.specInitializer.initialize(worktreePath, slug, featureNumber, input.userInput);
|
|
78
118
|
// Resolve or create repository entity for this path
|
|
79
|
-
const normalizedPath =
|
|
119
|
+
const normalizedPath = effectiveRepoPath.replace(/\/+$/, '') || effectiveRepoPath;
|
|
80
120
|
let repository = await this.repositoryRepo.findByPath(normalizedPath);
|
|
81
121
|
if (!repository) {
|
|
82
122
|
const repoName = normalizedPath.split('/').pop() ?? normalizedPath;
|
|
@@ -95,9 +135,9 @@ let CreateFeatureUseCase = class CreateFeatureUseCase {
|
|
|
95
135
|
slug,
|
|
96
136
|
description: metadata.description,
|
|
97
137
|
userQuery: input.userInput,
|
|
98
|
-
repositoryPath:
|
|
138
|
+
repositoryPath: effectiveRepoPath,
|
|
99
139
|
branch,
|
|
100
|
-
lifecycle:
|
|
140
|
+
lifecycle: initialLifecycle,
|
|
101
141
|
messages: [],
|
|
102
142
|
relatedArtifacts: [],
|
|
103
143
|
push: input.push ?? false,
|
|
@@ -110,6 +150,7 @@ let CreateFeatureUseCase = class CreateFeatureUseCase {
|
|
|
110
150
|
agentRunId: runId,
|
|
111
151
|
specPath: specDir,
|
|
112
152
|
repositoryId: repository.id,
|
|
153
|
+
...(input.parentId ? { parentId: input.parentId } : {}),
|
|
113
154
|
createdAt: now,
|
|
114
155
|
updatedAt: now,
|
|
115
156
|
};
|
|
@@ -124,18 +165,21 @@ let CreateFeatureUseCase = class CreateFeatureUseCase {
|
|
|
124
165
|
prompt: input.userInput,
|
|
125
166
|
threadId: randomUUID(),
|
|
126
167
|
featureId: feature.id,
|
|
127
|
-
repositoryPath:
|
|
168
|
+
repositoryPath: effectiveRepoPath,
|
|
128
169
|
...(input.approvalGates ? { approvalGates: input.approvalGates } : {}),
|
|
129
170
|
createdAt: now.toISOString(),
|
|
130
171
|
updatedAt: now.toISOString(),
|
|
131
172
|
};
|
|
132
173
|
await this.runRepository.create(agentRun);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
174
|
+
// Only spawn the agent immediately if the child is not blocked (FR-9, FR-16)
|
|
175
|
+
if (shouldSpawn) {
|
|
176
|
+
this.agentProcess.spawn(feature.id, runId, effectiveRepoPath, specDir, worktreePath, {
|
|
177
|
+
...(input.approvalGates ? { approvalGates: input.approvalGates } : {}),
|
|
178
|
+
threadId: agentRun.threadId,
|
|
179
|
+
push: input.push ?? false,
|
|
180
|
+
openPr: input.openPr ?? false,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
139
183
|
return { feature, warning };
|
|
140
184
|
}
|
|
141
185
|
};
|
|
@@ -5,6 +5,8 @@ export interface CreateFeatureInput {
|
|
|
5
5
|
approvalGates?: ApprovalGates;
|
|
6
6
|
push?: boolean;
|
|
7
7
|
openPr?: boolean;
|
|
8
|
+
/** Optional ID of the parent feature. When set, child may be created in Blocked state. */
|
|
9
|
+
parentId?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface CreateFeatureResult {
|
|
10
12
|
feature: Feature;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/use-cases/features/create/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AAErF,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/use-cases/features/create/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AAErF,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/features/delete-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAClG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAEvG,qBACa,oBAAoB;IAEC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAE5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IACA,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAJR,WAAW,EAAE,kBAAkB,EACjC,eAAe,EAAE,gBAAgB,EAE7D,cAAc,EAAE,2BAA2B,EACZ,OAAO,EAAE,mBAAmB;IAGxE,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"delete-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/features/delete-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAClG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAEvG,qBACa,oBAAoB;IAEC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAE5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IACA,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAJR,WAAW,EAAE,kBAAkB,EACjC,eAAe,EAAE,gBAAgB,EAE7D,cAAc,EAAE,2BAA2B,EACZ,OAAO,EAAE,mBAAmB;IAGxE,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAqDnD"}
|
|
@@ -24,7 +24,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
24
24
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
25
25
|
};
|
|
26
26
|
import { injectable, inject } from 'tsyringe';
|
|
27
|
-
import { AgentRunStatus } from '../../../domain/generated/output.js';
|
|
27
|
+
import { AgentRunStatus, SdlcLifecycle } from '../../../domain/generated/output.js';
|
|
28
28
|
let DeleteFeatureUseCase = class DeleteFeatureUseCase {
|
|
29
29
|
featureRepo;
|
|
30
30
|
worktreeService;
|
|
@@ -43,7 +43,14 @@ let DeleteFeatureUseCase = class DeleteFeatureUseCase {
|
|
|
43
43
|
if (!feature) {
|
|
44
44
|
throw new Error(`Feature not found: "${featureId}"`);
|
|
45
45
|
}
|
|
46
|
-
// 2.
|
|
46
|
+
// 2. Guard: reject deletion if blocked children exist (FR-29)
|
|
47
|
+
const blockedChildren = (await this.featureRepo.findByParentId(feature.id)).filter((child) => child.lifecycle === SdlcLifecycle.Blocked);
|
|
48
|
+
if (blockedChildren.length > 0) {
|
|
49
|
+
const list = blockedChildren.map((c) => `${c.id} (${c.name})`).join(', ');
|
|
50
|
+
throw new Error(`Cannot delete feature "${feature.name}" because it has blocked children: ${list}. ` +
|
|
51
|
+
`Remove or re-parent the blocked children before deleting this feature.`);
|
|
52
|
+
}
|
|
53
|
+
// 3. Cancel running/pending agent run if present
|
|
47
54
|
if (feature.agentRunId) {
|
|
48
55
|
const run = await this.runRepo.findById(feature.agentRunId);
|
|
49
56
|
if (run && (run.status === AgentRunStatus.running || run.status === AgentRunStatus.pending)) {
|
|
@@ -59,7 +66,7 @@ let DeleteFeatureUseCase = class DeleteFeatureUseCase {
|
|
|
59
66
|
await this.runRepo.updateStatus(run.id, AgentRunStatus.cancelled);
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
|
-
//
|
|
69
|
+
// 4. Remove worktree (ignore errors if already removed)
|
|
63
70
|
const worktreePath = this.worktreeService.getWorktreePath(feature.repositoryPath, feature.branch);
|
|
64
71
|
try {
|
|
65
72
|
await this.worktreeService.remove(worktreePath);
|
|
@@ -67,7 +74,7 @@ let DeleteFeatureUseCase = class DeleteFeatureUseCase {
|
|
|
67
74
|
catch {
|
|
68
75
|
// Worktree might already be removed - that's fine
|
|
69
76
|
}
|
|
70
|
-
//
|
|
77
|
+
// 5. Delete feature record
|
|
71
78
|
await this.featureRepo.delete(feature.id);
|
|
72
79
|
return feature;
|
|
73
80
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UpdateFeatureLifecycleUseCase
|
|
3
|
+
*
|
|
4
|
+
* Centralises all feature lifecycle transitions. Every call to this use case:
|
|
5
|
+
* 1. Persists the new lifecycle value via the feature repository.
|
|
6
|
+
* 2. Immediately calls CheckAndUnblockFeaturesUseCase to evaluate whether
|
|
7
|
+
* any blocked children can now be unblocked.
|
|
8
|
+
*
|
|
9
|
+
* This is the single hook point that ensures auto-unblocking fires on every
|
|
10
|
+
* lifecycle transition made by the feature agent, satisfying FR-17.
|
|
11
|
+
*
|
|
12
|
+
* No-op when the feature is not found (swallowed gracefully so agent nodes
|
|
13
|
+
* do not crash on a missing feature record).
|
|
14
|
+
*/
|
|
15
|
+
import type { SdlcLifecycle } from '../../../../domain/generated/output.js';
|
|
16
|
+
import type { IFeatureRepository } from '../../../ports/output/repositories/feature-repository.interface.js';
|
|
17
|
+
import { CheckAndUnblockFeaturesUseCase } from '../check-and-unblock-features.use-case.js';
|
|
18
|
+
export interface UpdateFeatureLifecycleInput {
|
|
19
|
+
featureId: string;
|
|
20
|
+
lifecycle: SdlcLifecycle;
|
|
21
|
+
}
|
|
22
|
+
export declare class UpdateFeatureLifecycleUseCase {
|
|
23
|
+
private readonly featureRepo;
|
|
24
|
+
private readonly checkAndUnblock;
|
|
25
|
+
constructor(featureRepo: IFeatureRepository, checkAndUnblock: CheckAndUnblockFeaturesUseCase);
|
|
26
|
+
execute(input: UpdateFeatureLifecycleInput): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=update-feature-lifecycle.use-case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-feature-lifecycle.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/use-cases/features/update/update-feature-lifecycle.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oEAAoE,CAAC;AAC7G,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAE3F,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,qBACa,6BAA6B;IAER,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE1D,OAAO,CAAC,QAAQ,CAAC,eAAe;gBAFe,WAAW,EAAE,kBAAkB,EAE7D,eAAe,EAAE,8BAA8B;IAG5D,OAAO,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC;CAYjE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UpdateFeatureLifecycleUseCase
|
|
3
|
+
*
|
|
4
|
+
* Centralises all feature lifecycle transitions. Every call to this use case:
|
|
5
|
+
* 1. Persists the new lifecycle value via the feature repository.
|
|
6
|
+
* 2. Immediately calls CheckAndUnblockFeaturesUseCase to evaluate whether
|
|
7
|
+
* any blocked children can now be unblocked.
|
|
8
|
+
*
|
|
9
|
+
* This is the single hook point that ensures auto-unblocking fires on every
|
|
10
|
+
* lifecycle transition made by the feature agent, satisfying FR-17.
|
|
11
|
+
*
|
|
12
|
+
* No-op when the feature is not found (swallowed gracefully so agent nodes
|
|
13
|
+
* do not crash on a missing feature record).
|
|
14
|
+
*/
|
|
15
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
16
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
17
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
18
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
19
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
20
|
+
};
|
|
21
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
22
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
23
|
+
};
|
|
24
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
25
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
26
|
+
};
|
|
27
|
+
import { injectable, inject } from 'tsyringe';
|
|
28
|
+
import { CheckAndUnblockFeaturesUseCase } from '../check-and-unblock-features.use-case.js';
|
|
29
|
+
let UpdateFeatureLifecycleUseCase = class UpdateFeatureLifecycleUseCase {
|
|
30
|
+
featureRepo;
|
|
31
|
+
checkAndUnblock;
|
|
32
|
+
constructor(featureRepo, checkAndUnblock) {
|
|
33
|
+
this.featureRepo = featureRepo;
|
|
34
|
+
this.checkAndUnblock = checkAndUnblock;
|
|
35
|
+
}
|
|
36
|
+
async execute(input) {
|
|
37
|
+
const feature = await this.featureRepo.findById(input.featureId);
|
|
38
|
+
if (!feature) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
feature.lifecycle = input.lifecycle;
|
|
42
|
+
feature.updatedAt = new Date();
|
|
43
|
+
await this.featureRepo.update(feature);
|
|
44
|
+
await this.checkAndUnblock.execute(input.featureId);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
UpdateFeatureLifecycleUseCase = __decorate([
|
|
48
|
+
injectable(),
|
|
49
|
+
__param(0, inject('IFeatureRepository')),
|
|
50
|
+
__param(1, inject(CheckAndUnblockFeaturesUseCase)),
|
|
51
|
+
__metadata("design:paramtypes", [Object, CheckAndUnblockFeaturesUseCase])
|
|
52
|
+
], UpdateFeatureLifecycleUseCase);
|
|
53
|
+
export { UpdateFeatureLifecycleUseCase };
|
|
@@ -332,6 +332,18 @@ export type WorkflowConfig = {
|
|
|
332
332
|
* Default approval gate preferences for new features
|
|
333
333
|
*/
|
|
334
334
|
approvalGateDefaults: ApprovalGateDefaults;
|
|
335
|
+
/**
|
|
336
|
+
* Maximum number of CI fix/push/watch iterations before giving up (default: 3)
|
|
337
|
+
*/
|
|
338
|
+
ciMaxFixAttempts?: number;
|
|
339
|
+
/**
|
|
340
|
+
* Timeout in milliseconds for watching a CI run (default: 600000 = 10 minutes)
|
|
341
|
+
*/
|
|
342
|
+
ciWatchTimeoutMs?: number;
|
|
343
|
+
/**
|
|
344
|
+
* Maximum characters of CI failure logs to pass to the executor (default: 50000)
|
|
345
|
+
*/
|
|
346
|
+
ciLogMaxChars?: number;
|
|
335
347
|
};
|
|
336
348
|
export declare enum AgentType {
|
|
337
349
|
ClaudeCode = "claude-code",
|
|
@@ -594,7 +606,8 @@ export declare enum SdlcLifecycle {
|
|
|
594
606
|
Planning = "Planning",
|
|
595
607
|
Implementation = "Implementation",
|
|
596
608
|
Review = "Review",
|
|
597
|
-
Maintain = "Maintain"
|
|
609
|
+
Maintain = "Maintain",
|
|
610
|
+
Blocked = "Blocked"
|
|
598
611
|
}
|
|
599
612
|
/**
|
|
600
613
|
* Configuration for human-in-the-loop approval gates
|
|
@@ -623,6 +636,27 @@ export declare enum CiStatus {
|
|
|
623
636
|
Success = "Success",
|
|
624
637
|
Failure = "Failure"
|
|
625
638
|
}
|
|
639
|
+
/**
|
|
640
|
+
* Record of one CI fix attempt in the watch/fix loop
|
|
641
|
+
*/
|
|
642
|
+
export type CiFixRecord = {
|
|
643
|
+
/**
|
|
644
|
+
* 1-based attempt number
|
|
645
|
+
*/
|
|
646
|
+
attempt: number;
|
|
647
|
+
/**
|
|
648
|
+
* ISO timestamp when this attempt started
|
|
649
|
+
*/
|
|
650
|
+
startedAt: string;
|
|
651
|
+
/**
|
|
652
|
+
* First 500 chars of failure logs for this attempt
|
|
653
|
+
*/
|
|
654
|
+
failureSummary: string;
|
|
655
|
+
/**
|
|
656
|
+
* Outcome of this attempt: fixed, failed, or timeout
|
|
657
|
+
*/
|
|
658
|
+
outcome: string;
|
|
659
|
+
};
|
|
626
660
|
/**
|
|
627
661
|
* Pull request tracking data for a feature
|
|
628
662
|
*/
|
|
@@ -647,6 +681,14 @@ export type PullRequest = {
|
|
|
647
681
|
* CI pipeline status
|
|
648
682
|
*/
|
|
649
683
|
ciStatus?: CiStatus;
|
|
684
|
+
/**
|
|
685
|
+
* Number of CI fix attempts made
|
|
686
|
+
*/
|
|
687
|
+
ciFixAttempts?: number;
|
|
688
|
+
/**
|
|
689
|
+
* History of CI fix attempts
|
|
690
|
+
*/
|
|
691
|
+
ciFixHistory?: CiFixRecord[];
|
|
650
692
|
};
|
|
651
693
|
/**
|
|
652
694
|
* Central entity tracking a piece of work through the SDLC lifecycle (Aggregate Root)
|
|
@@ -724,6 +766,10 @@ export type Feature = BaseEntity & {
|
|
|
724
766
|
* Pull request data (null until PR created)
|
|
725
767
|
*/
|
|
726
768
|
pr?: PullRequest;
|
|
769
|
+
/**
|
|
770
|
+
* Parent feature ID for dependency tracking (optional)
|
|
771
|
+
*/
|
|
772
|
+
parentId?: UUID;
|
|
727
773
|
};
|
|
728
774
|
/**
|
|
729
775
|
* Option for resolving an open question
|