The Feature is the central aggregate root in Shep, representing a piece of work progressing through the SDLC lifecycle.
From packages/core/src/domain/generated/output.ts (TypeSpec-generated):
export type Feature = BaseEntity & {
name: string;
userQuery: string;
slug: string;
description: string;
repositoryPath: string;
branch: string;
lifecycle: SdlcLifecycle;
messages: Message[];
plan?: Plan;
relatedArtifacts: Artifact[];
agentRunId?: string;
specPath?: string;
repositoryId?: UUID;
fast: boolean;
push: boolean;
openPr: boolean;
approvalGates: ApprovalGates;
worktreePath?: string;
pr?: PullRequest;
parentId?: UUID;
attachments?: Attachment[];
};
| Property | Type | Description |
|---|---|---|
id |
UUID |
Unique identifier (UUID v4) |
repositoryPath |
string |
Absolute path to repository |
repositoryId |
UUID? |
ID of the Repository entity |
slug |
string |
URL-friendly identifier (unique/repo) |
createdAt |
any |
Creation timestamp |
updatedAt |
any |
Last update timestamp |
| Property | Type | Description |
|---|---|---|
name |
string |
Human-readable feature name |
userQuery |
string |
Original user query/request (preserved verbatim) |
description |
string |
Detailed feature description |
branch |
string |
Git branch for the feature |
lifecycle |
SdlcLifecycle |
Current lifecycle phase |
fast |
boolean |
Whether SDLC phases were skipped (fast mode) |
push |
boolean |
Push branch to remote after implementation |
openPr |
boolean |
Create PR after implementation |
agentRunId |
string? |
Agent execution run ID (optional) |
specPath |
string? |
Absolute path to feature spec directory (optional) |
worktreePath |
string? |
Absolute path to git worktree (optional) |
parentId |
UUID? |
Parent feature ID for dependency tracking (optional) |
| Property | Type | Description |
|---|---|---|
messages |
Message[] |
Conversation history with AI assistant |
plan |
Plan? |
Implementation plan (tasks, artifacts, reqs) |
relatedArtifacts |
Artifact[] |
Generated documents attached to this feature |
approvalGates |
ApprovalGates |
Human-in-the-loop approval gate configuration |
pr |
PullRequest? |
Pull request tracking data (null until created) |
attachments |
Attachment[]? |
Files attached by user when creating/messaging |
export type ApprovalGates = {
allowPrd: boolean; // Skip human review after requirements phase
allowPlan: boolean; // Skip human review after plan phase
allowMerge: boolean; // Skip human review after merge phase
};
export type PullRequest = {
url: string;
number: number;
status: PrStatus; // Open, Merged, Closed
commitHash?: string;
ciStatus?: CiStatus; // Pending, Success, Failure
ciFixAttempts?: number;
ciFixHistory?: CiFixRecord[];
};
export type Attachment = {
id: UUID;
name: string;
size: bigint;
mimeType: string;
path: string;
createdAt: any;
};
+-------------------------+
| Feature |
| |
| id, name, slug |
| userQuery, description |
| repositoryPath, branch |
| lifecycle, fast |
| push, openPr |
| approvalGates |
+----------+--------------+
|
+--------------------+------------------+
| | |
v v v
+-----------------+ +-----------------+ +------------------+
| Message[] | | Plan? --------+--| relatedArtifacts |
| | | | | Artifact[] |
| conversation | | requirements[] | +------------------+
| messages | | tasks[] |
+-----------------+ | artifacts[] |
+--------+--------+
|
+--------------+--------------+
| | |
v v v
+--------------+ +------------+ +------------+
| Requirement | | Task | | Artifact |
| | | | | |
| id, slug | | id | | id, name |
| userQuery | | title? | | type |
| type | | state | | category |
| researches[] | | baseBranch | | format |
+--------------+ | branch | | summary |
| dependsOn[]| | path |
| actions[] -+ | state |
+--------+---+ +------------+
|
v
+----------------------+
| ActionItem |
| |
| id, name |
| description, branch |
| dependsOn[] |
| acceptanceCriteria[]|
+----------------------+
Feature lifecycle determines available operations:
| Lifecycle | Allowed Operations |
|---|---|
| Started | Initialize feature metadata |
| Analyze | Repository analysis |
| Requirements | Add/modify requirements |
| Research | Technical investigation |
| Planning | Add/modify tasks, artifacts |
| Implementation | Update task state |
| Review | Review and approve changes |
| Maintain | All (new iteration) |
| Blocked | Await resolution |
As an aggregate root, Feature enforces these invariants:
Features are persisted via IFeatureRepository (in packages/core/src/application/ports/output/repositories/feature-repository.interface.ts):
interface IFeatureRepository {
create(feature: Feature): Promise<void>;
findById(id: string): Promise<Feature | null>;
findByIdPrefix(prefix: string): Promise<Feature | null>;
findBySlug(slug: string, repositoryPath: string): Promise<Feature | null>;
list(filters?: FeatureListFilters): Promise<Feature[]>;
update(feature: Feature): Promise<void>;
findByParentId(parentId: string): Promise<Feature[]>;
delete(id: string): Promise<void>;
}
Update when:
packages/core/src/domain/generated/output.ts)Related docs: