@itz4blitz/agentful 0.1.11 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/architect.md +30 -527
- package/.claude/agents/orchestrator.md +104 -622
- package/.claude/agents/product-analyzer.md +4 -4
- package/.claude/commands/agentful-agents.md +668 -0
- package/.claude/commands/agentful-analyze.md +564 -0
- package/.claude/commands/agentful-product.md +59 -674
- package/.claude/commands/agentful-skills.md +635 -0
- package/.claude/commands/agentful-start.md +4 -4
- package/.claude/commands/agentful-status.md +2 -2
- package/.claude/commands/agentful.md +222 -13
- package/.claude/product/README.md +32 -0
- package/.claude/settings.json +25 -1
- package/.claude/skills/conversation/SKILL.md +292 -15
- package/README.md +24 -7
- package/bin/cli.js +15 -87
- package/bin/hooks/README.md +120 -0
- package/bin/hooks/analyze-trigger.sh +57 -0
- package/bin/hooks/health-check.sh +36 -0
- package/lib/agent-generator.js +123 -30
- package/lib/domain-detector.js +4 -4
- package/lib/template-engine.js +87 -0
- package/package.json +18 -7
- package/template/CLAUDE.md +72 -192
- package/templates/agents/domain-agent.template.md +208 -0
- package/templates/agents/tech-agent.template.md +124 -0
- package/version.json +1 -1
|
@@ -9,6 +9,26 @@ tools: Read, Write, Edit, Glob, Grep
|
|
|
9
9
|
|
|
10
10
|
This skill provides natural language processing capabilities for understanding user intent, managing conversation context, resolving references, and maintaining conversation history.
|
|
11
11
|
|
|
12
|
+
## When to Use
|
|
13
|
+
|
|
14
|
+
This skill is invoked when:
|
|
15
|
+
- User runs `/agentful <text>` with natural language input
|
|
16
|
+
- Any command receives ambiguous or unclear input
|
|
17
|
+
- Need to resolve pronouns or references from conversation history
|
|
18
|
+
- Need to classify user intent before routing to handlers
|
|
19
|
+
|
|
20
|
+
**Entry Point**: The `/agentful` command delegates to this skill for all natural language processing.
|
|
21
|
+
|
|
22
|
+
## Responsibilities
|
|
23
|
+
|
|
24
|
+
1. **Intent Classification** - Determine what the user wants (feature, bug fix, status, etc.)
|
|
25
|
+
2. **Reference Resolution** - Resolve "it", "that", "this" to actual feature names
|
|
26
|
+
3. **Entity Extraction** - Extract features, domains, subtasks mentioned
|
|
27
|
+
4. **Ambiguity Detection** - Identify unclear requests and ask clarifying questions
|
|
28
|
+
5. **Context Management** - Track conversation state, detect context loss
|
|
29
|
+
6. **Routing** - Route to appropriate handler (orchestrator, status, validate, etc.)
|
|
30
|
+
7. **History Tracking** - Maintain conversation history for context
|
|
31
|
+
|
|
12
32
|
## Core Functions
|
|
13
33
|
|
|
14
34
|
### 1. Intent Classification
|
|
@@ -796,6 +816,221 @@ function get_recent_context(
|
|
|
796
816
|
}
|
|
797
817
|
```
|
|
798
818
|
|
|
819
|
+
## Routing Logic
|
|
820
|
+
|
|
821
|
+
### Route to Handler
|
|
822
|
+
|
|
823
|
+
```typescript
|
|
824
|
+
/**
|
|
825
|
+
* Determine which handler should process the classified intent
|
|
826
|
+
* @param intent - Classified intent from user message
|
|
827
|
+
* @param entities - Extracted entities (features, domains, etc.)
|
|
828
|
+
* @param state - Current conversation state
|
|
829
|
+
* @returns Routing decision with handler and context
|
|
830
|
+
*/
|
|
831
|
+
function route_to_handler(
|
|
832
|
+
intent: IntentClassification,
|
|
833
|
+
entities: FeatureMention,
|
|
834
|
+
state: ConversationState
|
|
835
|
+
): RoutingDecision {
|
|
836
|
+
const intentName = intent.intent;
|
|
837
|
+
|
|
838
|
+
// Feature development or bug fixes → orchestrator
|
|
839
|
+
if (intentName === 'feature_request' || intentName === 'bug_report') {
|
|
840
|
+
return {
|
|
841
|
+
handler: 'orchestrator',
|
|
842
|
+
skill: null,
|
|
843
|
+
context: {
|
|
844
|
+
intent: intentName,
|
|
845
|
+
message: entities.feature_name
|
|
846
|
+
? `User wants to ${intentName === 'feature_request' ? 'build' : 'fix'} ${entities.feature_name}`
|
|
847
|
+
: 'User has a request that needs classification',
|
|
848
|
+
feature_id: entities.feature_id,
|
|
849
|
+
domain_id: entities.domain_id,
|
|
850
|
+
work_type: intentName === 'feature_request' ? 'FEATURE_DEVELOPMENT' : 'BUGFIX'
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Status inquiries → product-tracking skill
|
|
856
|
+
if (intentName === 'status_update') {
|
|
857
|
+
return {
|
|
858
|
+
handler: 'product-tracking',
|
|
859
|
+
skill: 'product-tracking',
|
|
860
|
+
context: {
|
|
861
|
+
intent: intentName,
|
|
862
|
+
feature_filter: entities.feature_id || null,
|
|
863
|
+
domain_filter: entities.domain_id || null
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// Validation requests → validation skill
|
|
869
|
+
if (/test|validate|check/i.test(intentName)) {
|
|
870
|
+
return {
|
|
871
|
+
handler: 'validation',
|
|
872
|
+
skill: 'validation',
|
|
873
|
+
context: {
|
|
874
|
+
intent: intentName,
|
|
875
|
+
scope: entities.feature_id ? 'feature' : 'all'
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// Decision handling → decision-handler
|
|
881
|
+
if (intentName === 'decision' || /decide|choice|option/i.test(intentName)) {
|
|
882
|
+
return {
|
|
883
|
+
handler: 'decision-handler',
|
|
884
|
+
skill: null,
|
|
885
|
+
context: {
|
|
886
|
+
intent: intentName
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// Product planning → product-planning skill
|
|
892
|
+
if (/plan|requirements|spec|analyze/i.test(intentName)) {
|
|
893
|
+
return {
|
|
894
|
+
handler: 'product-planning',
|
|
895
|
+
skill: 'product-planning',
|
|
896
|
+
context: {
|
|
897
|
+
intent: intentName
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// Approval/continue → orchestrator (resume current work)
|
|
903
|
+
if (intentName === 'approval' || intentName === 'continue') {
|
|
904
|
+
return {
|
|
905
|
+
handler: 'orchestrator',
|
|
906
|
+
skill: null,
|
|
907
|
+
context: {
|
|
908
|
+
intent: 'continue',
|
|
909
|
+
message: 'User approved or wants to continue current work',
|
|
910
|
+
resume_feature: state.current_feature
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// Rejection/stop → update state, don't delegate
|
|
916
|
+
if (intentName === 'rejection' || intentName === 'pause') {
|
|
917
|
+
return {
|
|
918
|
+
handler: 'inline',
|
|
919
|
+
skill: null,
|
|
920
|
+
context: {
|
|
921
|
+
intent: intentName,
|
|
922
|
+
action: 'pause_work'
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// Questions/clarifications → handle inline
|
|
928
|
+
if (intentName === 'question' || intentName === 'clarification') {
|
|
929
|
+
return {
|
|
930
|
+
handler: 'inline',
|
|
931
|
+
skill: null,
|
|
932
|
+
context: {
|
|
933
|
+
intent: intentName,
|
|
934
|
+
answer_from: ['conversation_history', 'product_spec', 'completion_status']
|
|
935
|
+
}
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// Default: handle inline or ask for clarification
|
|
940
|
+
return {
|
|
941
|
+
handler: 'inline',
|
|
942
|
+
skill: null,
|
|
943
|
+
context: {
|
|
944
|
+
intent: intentName,
|
|
945
|
+
needs_clarification: true
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
interface RoutingDecision {
|
|
951
|
+
handler: 'orchestrator' | 'product-tracking' | 'validation' | 'decision-handler' | 'product-planning' | 'inline';
|
|
952
|
+
skill: string | null; // Skill name for Task delegation
|
|
953
|
+
context: {
|
|
954
|
+
intent: string;
|
|
955
|
+
message?: string;
|
|
956
|
+
feature_id?: string;
|
|
957
|
+
domain_id?: string;
|
|
958
|
+
work_type?: string;
|
|
959
|
+
[key: string]: any;
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
### Execute Routing
|
|
965
|
+
|
|
966
|
+
```typescript
|
|
967
|
+
/**
|
|
968
|
+
* Execute the routing decision
|
|
969
|
+
* @param routing - Routing decision from route_to_handler
|
|
970
|
+
* @param userMessage - Original user message
|
|
971
|
+
* @param resolved - Resolved message with references expanded
|
|
972
|
+
*/
|
|
973
|
+
function execute_routing(
|
|
974
|
+
routing: RoutingDecision,
|
|
975
|
+
userMessage: string,
|
|
976
|
+
resolved: ResolvedMessage
|
|
977
|
+
): void {
|
|
978
|
+
switch (routing.handler) {
|
|
979
|
+
case 'orchestrator':
|
|
980
|
+
// Delegate to orchestrator agent
|
|
981
|
+
Task('orchestrator',
|
|
982
|
+
`${routing.context.message || userMessage}
|
|
983
|
+
|
|
984
|
+
Work Type: ${routing.context.work_type || 'FEATURE_DEVELOPMENT'}
|
|
985
|
+
${routing.context.feature_id ? `Feature: ${routing.context.feature_id}` : ''}
|
|
986
|
+
${routing.context.domain_id ? `Domain: ${routing.context.domain_id}` : ''}
|
|
987
|
+
|
|
988
|
+
Classify and execute appropriate workflow.`
|
|
989
|
+
);
|
|
990
|
+
break;
|
|
991
|
+
|
|
992
|
+
case 'product-tracking':
|
|
993
|
+
// Delegate to product-tracking skill
|
|
994
|
+
Task('product-tracking',
|
|
995
|
+
`Show status and progress.
|
|
996
|
+
${routing.context.feature_filter ? `Filter: feature ${routing.context.feature_filter}` : ''}
|
|
997
|
+
${routing.context.domain_filter ? `Filter: domain ${routing.context.domain_filter}` : ''}`
|
|
998
|
+
);
|
|
999
|
+
break;
|
|
1000
|
+
|
|
1001
|
+
case 'validation':
|
|
1002
|
+
// Delegate to validation skill
|
|
1003
|
+
Task('validation',
|
|
1004
|
+
`Run quality gates.
|
|
1005
|
+
Scope: ${routing.context.scope || 'all'}`
|
|
1006
|
+
);
|
|
1007
|
+
break;
|
|
1008
|
+
|
|
1009
|
+
case 'decision-handler':
|
|
1010
|
+
// For now, show how to use /agentful-decide
|
|
1011
|
+
return `You have pending decisions. Run \`/agentful-decide\` to review and resolve them.`;
|
|
1012
|
+
break;
|
|
1013
|
+
|
|
1014
|
+
case 'product-planning':
|
|
1015
|
+
// Delegate to product-planning skill
|
|
1016
|
+
Task('product-planning', userMessage);
|
|
1017
|
+
break;
|
|
1018
|
+
|
|
1019
|
+
case 'inline':
|
|
1020
|
+
// Handle inline (no delegation needed)
|
|
1021
|
+
if (routing.context.needs_clarification) {
|
|
1022
|
+
return generate_clarification_response(userMessage, routing.context);
|
|
1023
|
+
} else if (routing.context.action === 'pause_work') {
|
|
1024
|
+
pause_current_work();
|
|
1025
|
+
return 'Work paused. Run `/agentful` with your next request when ready to continue.';
|
|
1026
|
+
} else if (routing.context.intent === 'question') {
|
|
1027
|
+
return answer_question(userMessage, routing.context);
|
|
1028
|
+
}
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
```
|
|
1033
|
+
|
|
799
1034
|
## Integration with Orchestrator
|
|
800
1035
|
|
|
801
1036
|
### Delegation Interface
|
|
@@ -1037,9 +1272,9 @@ interface StaleContextResponse {
|
|
|
1037
1272
|
// Complete conversation processing flow
|
|
1038
1273
|
async function process_conversation(userMessage: string): Promise<ConversationResponse> {
|
|
1039
1274
|
// 1. Load conversation state and history
|
|
1040
|
-
const state = load_conversation_state();
|
|
1041
|
-
const history = read_conversation_history();
|
|
1042
|
-
const productSpec = load_product_spec();
|
|
1275
|
+
const state = load_conversation_state('.agentful/conversation-state.json');
|
|
1276
|
+
const history = read_conversation_history('.agentful/conversation-history.json');
|
|
1277
|
+
const productSpec = load_product_spec('.claude/product/');
|
|
1043
1278
|
|
|
1044
1279
|
// 2. Check for context loss
|
|
1045
1280
|
const contextRecovery = detect_context_loss(history.messages, state);
|
|
@@ -1079,8 +1314,8 @@ async function process_conversation(userMessage: string): Promise<ConversationRe
|
|
|
1079
1314
|
};
|
|
1080
1315
|
}
|
|
1081
1316
|
|
|
1082
|
-
// 8.
|
|
1083
|
-
const
|
|
1317
|
+
// 8. Route to appropriate handler
|
|
1318
|
+
const routing = route_to_handler(intent, entities, state);
|
|
1084
1319
|
|
|
1085
1320
|
// 9. Add user message to history
|
|
1086
1321
|
add_message_to_history({
|
|
@@ -1089,24 +1324,66 @@ async function process_conversation(userMessage: string): Promise<ConversationRe
|
|
|
1089
1324
|
intent: intent.intent,
|
|
1090
1325
|
entities: entities,
|
|
1091
1326
|
references_resolved: resolved.references
|
|
1092
|
-
});
|
|
1093
|
-
|
|
1094
|
-
// 10.
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1327
|
+
}, '.agentful/conversation-history.json');
|
|
1328
|
+
|
|
1329
|
+
// 10. Execute routing
|
|
1330
|
+
execute_routing(routing, userMessage, resolved);
|
|
1331
|
+
|
|
1332
|
+
// 11. Update conversation state
|
|
1333
|
+
state.last_message_time = new Date().toISOString();
|
|
1334
|
+
state.message_count++;
|
|
1335
|
+
if (entities.feature_id) {
|
|
1336
|
+
state.current_feature = {
|
|
1337
|
+
feature_id: entities.feature_id,
|
|
1338
|
+
feature_name: entities.feature_name,
|
|
1339
|
+
domain_id: entities.domain_id
|
|
1100
1340
|
};
|
|
1101
1341
|
}
|
|
1342
|
+
save_conversation_state(state);
|
|
1102
1343
|
|
|
1103
1344
|
return {
|
|
1104
|
-
type: '
|
|
1105
|
-
|
|
1345
|
+
type: 'routed',
|
|
1346
|
+
handler: routing.handler,
|
|
1347
|
+
context: routing.context
|
|
1106
1348
|
};
|
|
1107
1349
|
}
|
|
1108
1350
|
```
|
|
1109
1351
|
|
|
1352
|
+
### Complete Flow Diagram
|
|
1353
|
+
|
|
1354
|
+
```
|
|
1355
|
+
User Input
|
|
1356
|
+
↓
|
|
1357
|
+
Load State & History
|
|
1358
|
+
↓
|
|
1359
|
+
Context Loss Check ──→ [STALE] ──→ Confirm & Resume
|
|
1360
|
+
↓ [FRESH]
|
|
1361
|
+
Mind Change Detection ──→ [DETECTED] ──→ Reset Context
|
|
1362
|
+
↓ [CONTINUE]
|
|
1363
|
+
Reference Resolution
|
|
1364
|
+
↓
|
|
1365
|
+
Intent Classification
|
|
1366
|
+
↓
|
|
1367
|
+
Entity Extraction
|
|
1368
|
+
↓
|
|
1369
|
+
Ambiguity Detection ──→ [AMBIGUOUS] ──→ Ask Clarifying Question
|
|
1370
|
+
↓ [CLEAR]
|
|
1371
|
+
Route to Handler
|
|
1372
|
+
↓
|
|
1373
|
+
├─→ [orchestrator] ──→ Task('orchestrator', context)
|
|
1374
|
+
├─→ [product-tracking] ──→ Task('product-tracking', context)
|
|
1375
|
+
├─→ [validation] ──→ Task('validation', context)
|
|
1376
|
+
├─→ [decision-handler] ──→ Show /agentful-decide
|
|
1377
|
+
├─→ [product-planning] ──→ Task('product-planning', context)
|
|
1378
|
+
└─→ [inline] ──→ Generate Response Directly
|
|
1379
|
+
↓
|
|
1380
|
+
Add to History
|
|
1381
|
+
↓
|
|
1382
|
+
Update State
|
|
1383
|
+
↓
|
|
1384
|
+
Done
|
|
1385
|
+
```
|
|
1386
|
+
|
|
1110
1387
|
## File Locations
|
|
1111
1388
|
|
|
1112
1389
|
```
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# agentful
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Human-in-the-loop development framework for Claude Code.
|
|
4
4
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://www.npmjs.com/package/@itz4blitz/agentful)
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
agentful is a Claude Code configuration that provides structured
|
|
10
|
+
agentful is a Claude Code configuration that provides structured development through specialized AI agents. It coordinates multiple agents to implement features, write tests, and validate code quality according to a defined product specification, with human checkpoints for key decisions.
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
@@ -53,7 +53,7 @@ Create your specification manually:
|
|
|
53
53
|
claude # Start Claude Code
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Then use the `/agentful-start` command to begin
|
|
56
|
+
Then use the `/agentful-start` command to begin structured development.
|
|
57
57
|
|
|
58
58
|
#### New Projects (No Existing Code)
|
|
59
59
|
|
|
@@ -135,7 +135,7 @@ Code changes are validated against:
|
|
|
135
135
|
|
|
136
136
|
### State Tracking
|
|
137
137
|
|
|
138
|
-
Runtime state is stored in `.agentful
|
|
138
|
+
Runtime state is stored in `.agentful/` (gitignored, managed by npm package):
|
|
139
139
|
|
|
140
140
|
- `state.json` - Current task and phase
|
|
141
141
|
- `completion.json` - Feature completion status
|
|
@@ -144,13 +144,28 @@ Runtime state is stored in `.agentful/`:
|
|
|
144
144
|
- New projects: Starts with declared stack (`confidence: 0.4`)
|
|
145
145
|
- Existing projects: Detected from code (`confidence: 0.8-1.0`)
|
|
146
146
|
- Re-analyzed after first implementation in new projects
|
|
147
|
+
- `last-validation.json` - Latest test/lint results
|
|
148
|
+
- `conversation-history.json` - Session tracking
|
|
149
|
+
|
|
150
|
+
User configuration is stored in `.claude/` (version controlled):
|
|
151
|
+
|
|
152
|
+
- `agents/` - Agent definitions (core + custom + ephemeral)
|
|
153
|
+
- `commands/` - Slash commands
|
|
154
|
+
- `product/` - Product specifications
|
|
155
|
+
- `index.md` - Main product spec (user editable)
|
|
156
|
+
- `product-analysis.json` - Readiness analysis (generated by `/agentful-product`)
|
|
157
|
+
- `domains/` - Optional hierarchical structure
|
|
158
|
+
- `skills/` - Reusable skill modules
|
|
159
|
+
- `settings.json` - Project configuration
|
|
160
|
+
|
|
161
|
+
**See [ARCHITECTURE.md](./ARCHITECTURE.md) for detailed explanation of file organization.**
|
|
147
162
|
|
|
148
163
|
## Commands
|
|
149
164
|
|
|
150
165
|
| Command | Description |
|
|
151
166
|
|---------|-------------|
|
|
152
167
|
| `/agentful-product` | Smart product planning: create, analyze, and refine requirements |
|
|
153
|
-
| `/agentful-start` | Start or resume
|
|
168
|
+
| `/agentful-start` | Start or resume structured development |
|
|
154
169
|
| `/agentful-status` | Display progress and current state |
|
|
155
170
|
| `/agentful-validate` | Run all quality checks |
|
|
156
171
|
| `/agentful-decide` | Answer pending decisions |
|
|
@@ -188,11 +203,13 @@ your-project/
|
|
|
188
203
|
│ ├── commands/ # Slash commands
|
|
189
204
|
│ ├── skills/ # Reusable skills
|
|
190
205
|
│ └── settings.json # Configuration
|
|
191
|
-
├── .agentful/ # Runtime state
|
|
206
|
+
├── .agentful/ # Runtime state (gitignored)
|
|
192
207
|
│ ├── state.json
|
|
193
208
|
│ ├── completion.json
|
|
194
209
|
│ ├── decisions.json
|
|
195
|
-
│
|
|
210
|
+
│ ├── architecture.json
|
|
211
|
+
│ ├── last-validation.json
|
|
212
|
+
│ └── conversation-history.json
|
|
196
213
|
└── src/ # Source code
|
|
197
214
|
```
|
|
198
215
|
|
package/bin/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* agentful CLI
|
|
5
|
-
* An opinionated
|
|
5
|
+
* An opinionated human-in-the-loop product development kit for Claude Code
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import fs from 'fs';
|
|
@@ -11,6 +11,7 @@ import { fileURLToPath } from 'url';
|
|
|
11
11
|
import { analyzeProject, exportToArchitectureJson } from '../lib/project-analyzer.js';
|
|
12
12
|
import AgentGenerator from '../lib/agent-generator.js';
|
|
13
13
|
import DomainStructureGenerator from '../lib/domain-structure-generator.js';
|
|
14
|
+
import { detectTechStack } from '../lib/tech-stack-detector.js';
|
|
14
15
|
|
|
15
16
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
17
|
const __dirname = path.dirname(__filename);
|
|
@@ -74,9 +75,9 @@ function showHelp() {
|
|
|
74
75
|
console.log(` ${colors.dim}(Detection based on: # of domains, frameworks, monorepo status)${colors.reset}`);
|
|
75
76
|
console.log(` 2. ${colors.bright}Edit your product specification${colors.reset}`);
|
|
76
77
|
console.log(` 3. Run ${colors.bright}claude${colors.reset} to start Claude Code`);
|
|
77
|
-
console.log(` 4. Type ${colors.bright}/agentful${colors.reset} for natural conversation or ${colors.bright}/agentful-start${colors.reset} for
|
|
78
|
+
console.log(` 4. Type ${colors.bright}/agentful${colors.reset} for natural conversation or ${colors.bright}/agentful-start${colors.reset} for structured development`);
|
|
78
79
|
console.log('');
|
|
79
|
-
console.log('FOR
|
|
80
|
+
console.log('FOR EXTENDED DEVELOPMENT SESSIONS:');
|
|
80
81
|
console.log(` ${colors.cyan}/ralph-loop "/agentful-start" --max-iterations 50 --completion-promise "AGENTFUL_COMPLETE"${colors.reset}`);
|
|
81
82
|
console.log('');
|
|
82
83
|
}
|
|
@@ -442,7 +443,7 @@ ${analysis && analysis.domains.length > 0 ? analysis.domains.map((d, i) => `${i
|
|
|
442
443
|
}
|
|
443
444
|
|
|
444
445
|
console.log(` 2. ${colors.cyan}Run: claude${colors.reset}`);
|
|
445
|
-
console.log(` 3. ${colors.cyan}Type: /agentful${colors.reset} (natural) or ${colors.cyan}/agentful-start${colors.reset} (
|
|
446
|
+
console.log(` 3. ${colors.cyan}Type: /agentful${colors.reset} (natural) or ${colors.cyan}/agentful-start${colors.reset} (structured)`);
|
|
446
447
|
console.log('');
|
|
447
448
|
|
|
448
449
|
if (usingHierarchical) {
|
|
@@ -453,7 +454,7 @@ ${analysis && analysis.domains.length > 0 ? analysis.domains.map((d, i) => `${i
|
|
|
453
454
|
console.log('');
|
|
454
455
|
}
|
|
455
456
|
|
|
456
|
-
log(colors.dim, 'For
|
|
457
|
+
log(colors.dim, 'For extended development sessions with fewer interruptions:');
|
|
457
458
|
log(colors.cyan, ` /ralph-loop "/agentful-start" --max-iterations 50 --completion-promise "AGENTFUL_COMPLETE"`);
|
|
458
459
|
console.log('');
|
|
459
460
|
}
|
|
@@ -582,87 +583,13 @@ function showStatus() {
|
|
|
582
583
|
console.log('');
|
|
583
584
|
}
|
|
584
585
|
|
|
585
|
-
function detectTechStack() {
|
|
586
|
-
const targetDir = process.cwd();
|
|
587
|
-
const detected = {
|
|
588
|
-
language: null,
|
|
589
|
-
framework: null,
|
|
590
|
-
dependencies: [],
|
|
591
|
-
devDependencies: []
|
|
592
|
-
};
|
|
593
|
-
|
|
594
|
-
// Check for package.json (Node.js/JavaScript/TypeScript)
|
|
595
|
-
const packageJsonPath = path.join(targetDir, 'package.json');
|
|
596
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
597
|
-
try {
|
|
598
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
599
|
-
detected.dependencies = Object.keys(pkg.dependencies || {});
|
|
600
|
-
detected.devDependencies = Object.keys(pkg.devDependencies || {});
|
|
601
|
-
detected.language = pkg.type === 'module' ? 'TypeScript/ESM' : 'JavaScript/TypeScript';
|
|
602
|
-
|
|
603
|
-
// Detect framework
|
|
604
|
-
if (detected.dependencies.includes('next')) {
|
|
605
|
-
detected.framework = 'Next.js';
|
|
606
|
-
} else if (detected.dependencies.includes('react')) {
|
|
607
|
-
detected.framework = 'React';
|
|
608
|
-
} else if (detected.dependencies.includes('vue')) {
|
|
609
|
-
detected.framework = 'Vue';
|
|
610
|
-
} else if (detected.dependencies.includes('express')) {
|
|
611
|
-
detected.framework = 'Express';
|
|
612
|
-
} else if (detected.dependencies.includes('nestjs')) {
|
|
613
|
-
detected.framework = 'NestJS';
|
|
614
|
-
}
|
|
615
|
-
} catch (err) {
|
|
616
|
-
log(colors.yellow, '⚠️ Could not parse package.json');
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
// Check for requirements.txt or pyproject.toml (Python)
|
|
621
|
-
const requirementsPath = path.join(targetDir, 'requirements.txt');
|
|
622
|
-
const pyprojectPath = path.join(targetDir, 'pyproject.toml');
|
|
623
|
-
if (fs.existsSync(requirementsPath) || fs.existsSync(pyprojectPath)) {
|
|
624
|
-
detected.language = 'Python';
|
|
625
|
-
const requirements = fs.existsSync(requirementsPath)
|
|
626
|
-
? fs.readFileSync(requirementsPath, 'utf-8')
|
|
627
|
-
: '';
|
|
628
|
-
if (requirements.includes('django')) detected.framework = 'Django';
|
|
629
|
-
else if (requirements.includes('flask')) detected.framework = 'Flask';
|
|
630
|
-
else if (requirements.includes('fastapi')) detected.framework = 'FastAPI';
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Check for go.mod (Go)
|
|
634
|
-
if (fs.existsSync(path.join(targetDir, 'go.mod'))) {
|
|
635
|
-
detected.language = 'Go';
|
|
636
|
-
detected.framework = 'Standard Library';
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// Check for Cargo.toml (Rust)
|
|
640
|
-
if (fs.existsSync(path.join(targetDir, 'Cargo.toml'))) {
|
|
641
|
-
detected.language = 'Rust';
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// Check for .csproj or .fsproj (C#/.NET)
|
|
645
|
-
const csprojFiles = fs.readdirSync(targetDir).filter(f => f.endsWith('.csproj'));
|
|
646
|
-
if (csprojFiles.length > 0) {
|
|
647
|
-
detected.language = 'C#';
|
|
648
|
-
detected.framework = 'ASP.NET';
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// Check for pom.xml (Java)
|
|
652
|
-
if (fs.existsSync(path.join(targetDir, 'pom.xml'))) {
|
|
653
|
-
detected.language = 'Java';
|
|
654
|
-
detected.framework = 'Maven';
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
return detected;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
586
|
function generateAgentPrompt(stack) {
|
|
661
587
|
let prompt = `# Tech Stack Analysis\n\n`;
|
|
662
588
|
prompt += `**Language**: ${stack.language || 'Unknown'}\n`;
|
|
663
|
-
|
|
589
|
+
const primaryFramework = stack.frameworks && stack.frameworks.length > 0 ? stack.frameworks[0] : null;
|
|
590
|
+
prompt += `**Framework**: ${primaryFramework || 'None'}\n\n`;
|
|
664
591
|
|
|
665
|
-
if (stack.dependencies.length > 0) {
|
|
592
|
+
if (stack.dependencies && stack.dependencies.length > 0) {
|
|
666
593
|
prompt += `**Key Dependencies**:\n`;
|
|
667
594
|
stack.dependencies.slice(0, 10).forEach(dep => {
|
|
668
595
|
prompt += `- ${dep}\n`;
|
|
@@ -724,11 +651,11 @@ async function generateAgents() {
|
|
|
724
651
|
process.exit(1);
|
|
725
652
|
}
|
|
726
653
|
|
|
727
|
-
// Detect tech stack
|
|
654
|
+
// Detect tech stack using library function
|
|
728
655
|
log(colors.dim, 'Analyzing tech stack...');
|
|
729
|
-
const stack = detectTechStack();
|
|
656
|
+
const stack = await detectTechStack(process.cwd());
|
|
730
657
|
|
|
731
|
-
if (!stack.language) {
|
|
658
|
+
if (!stack.language || stack.language === 'unknown') {
|
|
732
659
|
log(colors.yellow, '⚠️ Could not detect language/framework');
|
|
733
660
|
log(colors.dim, 'Supported: Node.js, Python, Go, Rust, C#, Java');
|
|
734
661
|
console.log('');
|
|
@@ -739,7 +666,8 @@ async function generateAgents() {
|
|
|
739
666
|
return;
|
|
740
667
|
}
|
|
741
668
|
|
|
742
|
-
|
|
669
|
+
const primaryFramework = stack.frameworks.length > 0 ? stack.frameworks[0] : null;
|
|
670
|
+
log(colors.green, `✓ Detected: ${stack.language} ${primaryFramework ? `(${primaryFramework})` : ''}`);
|
|
743
671
|
log(colors.dim, ` Dependencies: ${stack.dependencies.length} packages`);
|
|
744
672
|
|
|
745
673
|
// Update architecture.json
|
|
@@ -762,7 +690,7 @@ async function generateAgents() {
|
|
|
762
690
|
|
|
763
691
|
log(colors.bright, 'Detected Stack:');
|
|
764
692
|
if (stack.language) log(colors.cyan, ` Language: ${stack.language}`);
|
|
765
|
-
if (
|
|
693
|
+
if (primaryFramework) log(colors.cyan, ` Framework: ${primaryFramework}`);
|
|
766
694
|
if (stack.dependencies.length > 0) {
|
|
767
695
|
log(colors.cyan, ` Dependencies: ${stack.dependencies.length} packages`);
|
|
768
696
|
}
|