devforgeai 1.0.7 → 1.0.9
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/docs/CNAME +1 -0
- package/docs/NPM-Publish.md +341 -0
- package/docs/api/API.md +1054 -0
- package/docs/architecture/ARCHITECTURE.md +724 -0
- package/docs/guides/DEVELOPER-GUIDE.md +398 -0
- package/docs/guides/ROADMAP.md +48 -0
- package/docs/guides/TROUBLESHOOTING.md +631 -0
- package/docs/index.html +2045 -0
- package/package.json +2 -2
- package/src/cli/commands/install.js +7 -2
- package/src/cli/lib/components.js +5 -9
- package/src/cli/lib/ide/claude-code.js +24 -9
- package/src/cli/lib/settings-merger.js +160 -0
- package/devforgeai/specs/context/.gitkeep +0 -0
- package/devforgeai/specs/context/anti-patterns.md +0 -285
- package/devforgeai/specs/context/architecture-constraints.md +0 -323
- package/devforgeai/specs/context/coding-standards.md +0 -472
- package/devforgeai/specs/context/dependencies.md +0 -208
- package/devforgeai/specs/context/source-tree.md +0 -1217
- package/devforgeai/specs/context/tech-stack.md +0 -560
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devforgeai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "DevForgeAI is a spec-driven development framework designed to enable AI-assisted software development with zero technical debt through automated validation, architectural constraints enforcement, and test-driven development workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"src/claude/skills/",
|
|
39
39
|
"src/scripts/*.sh",
|
|
40
40
|
"src/scripts/*.json",
|
|
41
|
-
"
|
|
41
|
+
"docs/"
|
|
42
42
|
],
|
|
43
43
|
"repository": {
|
|
44
44
|
"type": "git",
|
|
@@ -204,9 +204,14 @@ async function action(directory, opts) {
|
|
|
204
204
|
ide: ['claude-code'],
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
-
// IDE setup
|
|
207
|
+
// IDE setup (merge settings on update, overwrite on reinstall)
|
|
208
208
|
const claudeCode = new ClaudeCodeIDE();
|
|
209
|
-
await claudeCode.setup(installDir, copier
|
|
209
|
+
const ideResult = await claudeCode.setup(installDir, copier, {
|
|
210
|
+
reinstall: !opts._updateMode,
|
|
211
|
+
});
|
|
212
|
+
if (!opts.quiet && ideResult.message) {
|
|
213
|
+
formatter.info(ideResult.message);
|
|
214
|
+
}
|
|
210
215
|
|
|
211
216
|
// Phase 9: Summary
|
|
212
217
|
if (!opts.quiet) {
|
|
@@ -11,7 +11,6 @@ const COMPONENTS = [
|
|
|
11
11
|
{ from: 'CLAUDE.md', to: 'CLAUDE.md', template: true },
|
|
12
12
|
{ from: 'src/claude/rules/', to: '.claude/rules/', template: false },
|
|
13
13
|
{ from: 'src/claude/memory/', to: '.claude/memory/', template: false },
|
|
14
|
-
{ from: 'devforgeai/specs/context/', to: 'devforgeai/specs/context/', template: true },
|
|
15
14
|
],
|
|
16
15
|
},
|
|
17
16
|
{
|
|
@@ -71,15 +70,12 @@ const COMPONENTS = [
|
|
|
71
70
|
required: false,
|
|
72
71
|
defaultSelected: true,
|
|
73
72
|
directories: [
|
|
74
|
-
'src/',
|
|
75
|
-
'tests/',
|
|
76
|
-
'docs/',
|
|
77
73
|
'devforgeai/',
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
'
|
|
81
|
-
'
|
|
82
|
-
'
|
|
74
|
+
],
|
|
75
|
+
sources: [
|
|
76
|
+
{ from: 'docs/api/', to: 'docs/api/', template: false },
|
|
77
|
+
{ from: 'docs/architecture/', to: 'docs/architecture/', template: false },
|
|
78
|
+
{ from: 'docs/guides/', to: 'docs/guides/', template: false },
|
|
83
79
|
],
|
|
84
80
|
},
|
|
85
81
|
];
|
|
@@ -1,23 +1,38 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const fsp = fs.promises;
|
|
1
4
|
const { BaseIDE } = require('./base');
|
|
5
|
+
const { SettingsMerger } = require('../settings-merger');
|
|
2
6
|
|
|
3
7
|
class ClaudeCodeIDE extends BaseIDE {
|
|
4
8
|
constructor() {
|
|
5
9
|
super({ name: 'claude-code', displayName: 'Claude Code' });
|
|
6
10
|
}
|
|
7
11
|
|
|
8
|
-
async setup(targetRoot, copier) {
|
|
9
|
-
|
|
10
|
-
// by the core-framework, agents, skills, commands, hooks components.
|
|
11
|
-
// This integration ensures the directory structure is correct
|
|
12
|
-
// and any Claude Code-specific config is in place.
|
|
12
|
+
async setup(targetRoot, copier, options = {}) {
|
|
13
|
+
const merger = new SettingsMerger(targetRoot);
|
|
13
14
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Load template settings from the package source
|
|
16
|
+
const templatePath = path.join(copier.sourceRoot, 'src', 'claude', 'settings.json');
|
|
17
|
+
let templateSettings;
|
|
18
|
+
try {
|
|
19
|
+
const raw = await fsp.readFile(templatePath, 'utf8');
|
|
20
|
+
templateSettings = JSON.parse(raw);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
return { success: false, message: `Could not read template settings: ${err.message}` };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const mode = options.reinstall ? 'overwrite' : 'merge';
|
|
26
|
+
const result = await merger.install(templateSettings, { mode });
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
success: true,
|
|
30
|
+
message: `Claude Code settings ${result.action}${result.backupCreated ? ' (backup created)' : ''}`,
|
|
31
|
+
};
|
|
17
32
|
}
|
|
18
33
|
|
|
19
34
|
describe() {
|
|
20
|
-
return 'Claude Code — .claude/ directory with agents, skills, commands, rules, hooks';
|
|
35
|
+
return 'Claude Code — .claude/ directory with agents, skills, commands, rules, hooks, settings';
|
|
21
36
|
}
|
|
22
37
|
}
|
|
23
38
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const fsp = fs.promises;
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
class SettingsMerger {
|
|
8
|
+
constructor(targetRoot) {
|
|
9
|
+
if (!targetRoot) {
|
|
10
|
+
throw new Error('SettingsMerger requires targetRoot');
|
|
11
|
+
}
|
|
12
|
+
this.targetRoot = path.resolve(targetRoot);
|
|
13
|
+
this.settingsPath = path.join(this.targetRoot, '.claude', 'settings.json');
|
|
14
|
+
this.backupPath = path.join(this.targetRoot, '.claude', 'settings.json.bak');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Install settings.json into target project.
|
|
19
|
+
* @param {object} templateSettings - The DevForgeAI template settings object
|
|
20
|
+
* @param {object} options - { mode: 'merge' | 'overwrite' }
|
|
21
|
+
* @returns {object} { action: string, backupCreated: boolean }
|
|
22
|
+
*/
|
|
23
|
+
async install(templateSettings, options = {}) {
|
|
24
|
+
const mode = options.mode || 'merge';
|
|
25
|
+
|
|
26
|
+
await fsp.mkdir(path.dirname(this.settingsPath), { recursive: true });
|
|
27
|
+
|
|
28
|
+
let existing = null;
|
|
29
|
+
try {
|
|
30
|
+
const raw = await fsp.readFile(this.settingsPath, 'utf8');
|
|
31
|
+
existing = JSON.parse(raw);
|
|
32
|
+
} catch {
|
|
33
|
+
// No existing file or invalid JSON — treat as fresh install
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!existing || mode === 'overwrite') {
|
|
37
|
+
await fsp.writeFile(this.settingsPath, JSON.stringify(templateSettings, null, 2) + '\n', 'utf8');
|
|
38
|
+
return { action: existing ? 'overwritten' : 'created', backupCreated: false };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Merge mode: backup first, then deep merge
|
|
42
|
+
await this.backup(existing);
|
|
43
|
+
const merged = this.merge(existing, templateSettings);
|
|
44
|
+
await fsp.writeFile(this.settingsPath, JSON.stringify(merged, null, 2) + '\n', 'utf8');
|
|
45
|
+
return { action: 'merged', backupCreated: true };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Deep merge template into existing settings.
|
|
50
|
+
* Existing values are preserved; template fills gaps.
|
|
51
|
+
*/
|
|
52
|
+
merge(existing, template) {
|
|
53
|
+
const result = JSON.parse(JSON.stringify(existing));
|
|
54
|
+
|
|
55
|
+
// Merge permissions
|
|
56
|
+
if (template.permissions) {
|
|
57
|
+
result.permissions = this.mergePermissions(
|
|
58
|
+
result.permissions || {},
|
|
59
|
+
template.permissions
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Merge hooks
|
|
64
|
+
if (template.hooks) {
|
|
65
|
+
result.hooks = this.mergeHooks(
|
|
66
|
+
result.hooks || {},
|
|
67
|
+
template.hooks
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Set statusLine if missing
|
|
72
|
+
if (template.statusLine && !result.statusLine) {
|
|
73
|
+
result.statusLine = template.statusLine;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Set includeCoAuthoredBy if missing
|
|
77
|
+
if ('includeCoAuthoredBy' in template && !('includeCoAuthoredBy' in result)) {
|
|
78
|
+
result.includeCoAuthoredBy = template.includeCoAuthoredBy;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Merge permission arrays: union of allow/ask/deny with deduplication.
|
|
86
|
+
*/
|
|
87
|
+
mergePermissions(existing, incoming) {
|
|
88
|
+
const result = JSON.parse(JSON.stringify(existing));
|
|
89
|
+
|
|
90
|
+
if (incoming.defaultMode && !result.defaultMode) {
|
|
91
|
+
result.defaultMode = incoming.defaultMode;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (const key of ['allow', 'ask', 'deny']) {
|
|
95
|
+
if (incoming[key]) {
|
|
96
|
+
const existingSet = new Set(result[key] || []);
|
|
97
|
+
for (const item of incoming[key]) {
|
|
98
|
+
existingSet.add(item);
|
|
99
|
+
}
|
|
100
|
+
result[key] = [...existingSet];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Merge hooks by event name. Within each event, deduplicate by command path.
|
|
109
|
+
*/
|
|
110
|
+
mergeHooks(existing, incoming) {
|
|
111
|
+
const result = JSON.parse(JSON.stringify(existing));
|
|
112
|
+
|
|
113
|
+
for (const [eventName, incomingEntries] of Object.entries(incoming)) {
|
|
114
|
+
if (!result[eventName]) {
|
|
115
|
+
// Event doesn't exist — add all entries
|
|
116
|
+
result[eventName] = incomingEntries;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Event exists — deduplicate by command path
|
|
121
|
+
for (const incomingEntry of incomingEntries) {
|
|
122
|
+
const isDuplicate = result[eventName].some(existingEntry =>
|
|
123
|
+
this._hookEntriesMatch(existingEntry, incomingEntry)
|
|
124
|
+
);
|
|
125
|
+
if (!isDuplicate) {
|
|
126
|
+
result[eventName].push(incomingEntry);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Check if two hook entries match (same matcher + same command paths).
|
|
136
|
+
*/
|
|
137
|
+
_hookEntriesMatch(a, b) {
|
|
138
|
+
// Different matchers = different entries
|
|
139
|
+
const matcherA = a.matcher || '';
|
|
140
|
+
const matcherB = b.matcher || '';
|
|
141
|
+
if (matcherA !== matcherB) return false;
|
|
142
|
+
|
|
143
|
+
// Compare hook commands
|
|
144
|
+
const cmdsA = (a.hooks || []).map(h => h.command).sort();
|
|
145
|
+
const cmdsB = (b.hooks || []).map(h => h.command).sort();
|
|
146
|
+
|
|
147
|
+
if (cmdsA.length !== cmdsB.length) return false;
|
|
148
|
+
return cmdsA.every((cmd, i) => cmd === cmdsB[i]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Backup existing settings.json.
|
|
153
|
+
*/
|
|
154
|
+
async backup(existingObj) {
|
|
155
|
+
const content = JSON.stringify(existingObj, null, 2) + '\n';
|
|
156
|
+
await fsp.writeFile(this.backupPath, content, 'utf8');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
module.exports = { SettingsMerger };
|
|
File without changes
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
# Anti-Patterns - DevForgeAI Framework
|
|
2
|
-
|
|
3
|
-
**Status**: LOCKED
|
|
4
|
-
**Last Updated**: 2026-02-05
|
|
5
|
-
**Version**: 1.1
|
|
6
|
-
|
|
7
|
-
## Framework Anti-Patterns
|
|
8
|
-
|
|
9
|
-
### Category 1: Tool Usage Violations (SEVERITY: CRITICAL)
|
|
10
|
-
|
|
11
|
-
❌ **FORBIDDEN: Using Bash for File Operations**
|
|
12
|
-
|
|
13
|
-
**Wrong**:
|
|
14
|
-
```markdown
|
|
15
|
-
Bash(command="cat story.md")
|
|
16
|
-
Bash(command="echo 'content' > file.md")
|
|
17
|
-
Bash(command="find . -name '*.md'")
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
**Correct**:
|
|
21
|
-
```markdown
|
|
22
|
-
Read(file_path="story.md")
|
|
23
|
-
Write(file_path="file.md", content="content")
|
|
24
|
-
Glob(pattern="**/*.md")
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**Rationale**: 40-73% token efficiency gain with native tools.
|
|
28
|
-
|
|
29
|
-
### Category 2: Monolithic Components (SEVERITY: HIGH)
|
|
30
|
-
|
|
31
|
-
❌ **FORBIDDEN: All-in-One Skill**
|
|
32
|
-
|
|
33
|
-
**Wrong**:
|
|
34
|
-
```
|
|
35
|
-
.claude/skills/devforgeai-everything/
|
|
36
|
-
└── SKILL.md (5,000 lines doing ideation + architecture + dev + qa + release)
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
**Correct**:
|
|
40
|
-
```
|
|
41
|
-
.claude/skills/
|
|
42
|
-
├── discovering-requirements/
|
|
43
|
-
├── designing-architecture/
|
|
44
|
-
├── implementing-stories/
|
|
45
|
-
├── validating-quality/
|
|
46
|
-
└── releasing-stories/
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
**Rationale**: Modularity enables independent updates and token efficiency.
|
|
50
|
-
|
|
51
|
-
### Category 3: Making Assumptions (SEVERITY: CRITICAL)
|
|
52
|
-
|
|
53
|
-
❌ **FORBIDDEN: Assuming Technology Choices**
|
|
54
|
-
|
|
55
|
-
**Wrong**:
|
|
56
|
-
```markdown
|
|
57
|
-
# AI sees "need caching" and adds Redis without asking
|
|
58
|
-
Install Redis for caching layer
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**Correct**:
|
|
62
|
-
```markdown
|
|
63
|
-
Question: "Spec requires caching. Which technology?"
|
|
64
|
-
Header: "Caching"
|
|
65
|
-
Options:
|
|
66
|
-
- "Redis (in-memory, distributed)"
|
|
67
|
-
- "Memcached (simple, fast)"
|
|
68
|
-
- "In-memory (no external service)"
|
|
69
|
-
multiSelect: false
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
**Rationale**: Assumptions cause technical debt.
|
|
73
|
-
|
|
74
|
-
### Category 4: Size Violations (SEVERITY: HIGH)
|
|
75
|
-
|
|
76
|
-
❌ **FORBIDDEN: Exceeding Component Size Limits**
|
|
77
|
-
|
|
78
|
-
**Wrong**:
|
|
79
|
-
```markdown
|
|
80
|
-
# SKILL.md with 2,000 lines of inline documentation
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
**Correct**:
|
|
84
|
-
```markdown
|
|
85
|
-
# SKILL.md with 500 lines + references/ for deep docs
|
|
86
|
-
For detailed scoring rubric, see references/complexity-assessment-matrix.md
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**Rationale**: Character budget constraints (15K for commands).
|
|
90
|
-
|
|
91
|
-
### Category 5: Language-Specific Framework Code (SEVERITY: CRITICAL)
|
|
92
|
-
|
|
93
|
-
❌ **FORBIDDEN: Python/C#/JavaScript in Framework**
|
|
94
|
-
|
|
95
|
-
**Wrong**:
|
|
96
|
-
```
|
|
97
|
-
.claude/skills/implementing-stories/
|
|
98
|
-
├── SKILL.md
|
|
99
|
-
└── scripts/
|
|
100
|
-
└── implement.py # Python implementation
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**Correct**:
|
|
104
|
-
```
|
|
105
|
-
.claude/skills/implementing-stories/
|
|
106
|
-
├── SKILL.md
|
|
107
|
-
└── references/
|
|
108
|
-
└── tdd-workflow-guide.md # Documentation only
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**Rationale**: Framework must be language-agnostic.
|
|
112
|
-
|
|
113
|
-
### Category 6: Context File Violations (SEVERITY: CRITICAL)
|
|
114
|
-
|
|
115
|
-
❌ **FORBIDDEN: Proceeding Without Context Files**
|
|
116
|
-
|
|
117
|
-
**Wrong**:
|
|
118
|
-
```markdown
|
|
119
|
-
# Development skill starts implementation without reading context
|
|
120
|
-
Implement feature X using EF Core
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
**Correct**:
|
|
124
|
-
```markdown
|
|
125
|
-
## Phase 1: Context Validation
|
|
126
|
-
Read all 6 context files
|
|
127
|
-
HALT if missing: "Run /create-context first"
|
|
128
|
-
Check tech-stack.md for ORM choice
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
**Rationale**: Context files prevent architectural violations.
|
|
132
|
-
|
|
133
|
-
### Category 7: Circular Dependencies (SEVERITY: HIGH)
|
|
134
|
-
|
|
135
|
-
❌ **FORBIDDEN: Skills Calling Each Other in Loops**
|
|
136
|
-
|
|
137
|
-
**Wrong**:
|
|
138
|
-
```
|
|
139
|
-
implementing-stories calls validating-quality
|
|
140
|
-
↓
|
|
141
|
-
validating-quality calls implementing-stories
|
|
142
|
-
↓
|
|
143
|
-
Infinite loop
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
**Correct**:
|
|
147
|
-
```
|
|
148
|
-
implementing-stories calls validating-quality (one-way)
|
|
149
|
-
validating-quality returns results
|
|
150
|
-
implementing-stories continues
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
**Rationale**: Prevents infinite loops and context overflow.
|
|
154
|
-
|
|
155
|
-
### Category 8: Narrative Documentation (SEVERITY: MEDIUM)
|
|
156
|
-
|
|
157
|
-
❌ **FORBIDDEN: Prose Instead of Instructions**
|
|
158
|
-
|
|
159
|
-
**Wrong**:
|
|
160
|
-
```markdown
|
|
161
|
-
The system should first analyze the codebase, and then it might want to consider generating tests...
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
**Correct**:
|
|
165
|
-
```markdown
|
|
166
|
-
1. Analyze codebase:
|
|
167
|
-
- Grep(pattern="class.*Test", glob="**/*.cs")
|
|
168
|
-
2. Generate tests:
|
|
169
|
-
- Use test-automator subagent
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
**Rationale**: Direct instructions are clearer for Claude.
|
|
173
|
-
|
|
174
|
-
### Category 9: Missing Frontmatter (SEVERITY: HIGH)
|
|
175
|
-
|
|
176
|
-
❌ **FORBIDDEN: Skills/Subagents/Commands Without Frontmatter**
|
|
177
|
-
|
|
178
|
-
**Wrong**:
|
|
179
|
-
```markdown
|
|
180
|
-
# My Skill
|
|
181
|
-
Instructions go here...
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
**Correct**:
|
|
185
|
-
```markdown
|
|
186
|
-
---
|
|
187
|
-
name: my-skill
|
|
188
|
-
description: Brief description of when to use
|
|
189
|
-
tools: Read, Write
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
# My Skill
|
|
193
|
-
Instructions go here...
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
**Rationale**: Frontmatter required for discovery.
|
|
197
|
-
|
|
198
|
-
### Category 10: Hardcoded Paths (SEVERITY: MEDIUM)
|
|
199
|
-
|
|
200
|
-
❌ **FORBIDDEN: Hardcoded File Paths**
|
|
201
|
-
|
|
202
|
-
**Wrong**:
|
|
203
|
-
```markdown
|
|
204
|
-
Read(file_path="/home/user/project/story.md")
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
**Correct**:
|
|
208
|
-
```markdown
|
|
209
|
-
Read(file_path="devforgeai/specs/Stories/$STORY_ID.md")
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
**Rationale**: Relative paths work across environments.
|
|
213
|
-
|
|
214
|
-
### Category 11: Code Search Tool Selection (SEVERITY: MEDIUM)
|
|
215
|
-
|
|
216
|
-
**Treelint-Supported Languages:** Python (`.py`), TypeScript (`.ts`, `.tsx`), JavaScript (`.js`, `.jsx`), Rust (`.rs`), Markdown (`.md`)
|
|
217
|
-
|
|
218
|
-
**Grep is Correct for:** Unsupported languages, simple text-pattern searches (TODOs, string literals), fallback when Treelint is unavailable.
|
|
219
|
-
|
|
220
|
-
❌ **FORBIDDEN: Using Treelint for Unsupported File Types**
|
|
221
|
-
|
|
222
|
-
**Wrong**:
|
|
223
|
-
```markdown
|
|
224
|
-
# Treelint does not support C#, Java, Go, SQL - returns errors
|
|
225
|
-
Bash(command="treelint search --type function myfile.cs")
|
|
226
|
-
Bash(command="treelint search --type class MyClass.java")
|
|
227
|
-
Bash(command="treelint deps --calls project.go")
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
**Correct**:
|
|
231
|
-
```markdown
|
|
232
|
-
# Use Grep for unsupported languages
|
|
233
|
-
Grep(pattern="class\\s+\\w+", glob="**/*.cs")
|
|
234
|
-
Grep(pattern="public\\s+void", glob="**/*.java")
|
|
235
|
-
Grep(pattern="func\\s+\\w+", glob="**/*.go")
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
**Rationale**: Treelint returns errors for unsupported file types, wasting tokens on error responses instead of useful results.
|
|
239
|
-
|
|
240
|
-
❌ **FORBIDDEN: Using Grep When Treelint Available for Supported Languages**
|
|
241
|
-
|
|
242
|
-
**Wrong**:
|
|
243
|
-
```markdown
|
|
244
|
-
# Using Grep for semantic code search in Treelint-supported languages
|
|
245
|
-
Grep(pattern="def\\s+validate", glob="**/*.py")
|
|
246
|
-
Grep(pattern="function\\s+handle", glob="**/*.ts")
|
|
247
|
-
Grep(pattern="class\\s+Service", glob="**/*.js")
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
**Correct**:
|
|
251
|
-
```markdown
|
|
252
|
-
# Use Treelint for semantic AST-aware search
|
|
253
|
-
Bash(command="treelint search --type function --name 'validate*' --format json")
|
|
254
|
-
Bash(command="treelint search --type class --name 'Service*' --format json")
|
|
255
|
-
Bash(command="treelint deps --calls --format json")
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
**Rationale**: Treelint provides 99.93% token reduction vs Grep for semantic code search (Source: ADR-013, RESEARCH-007). AST-aware search eliminates false positives from comments, strings, and partial matches. Grep remains valid for simple text patterns (TODOs, string literals) even in supported languages, and as fallback when Treelint is unavailable.
|
|
259
|
-
|
|
260
|
-
## Anti-Pattern Detection Protocol
|
|
261
|
-
|
|
262
|
-
When framework components detect anti-patterns:
|
|
263
|
-
|
|
264
|
-
1. **HALT immediately**
|
|
265
|
-
2. **Report specific violation** with file:line reference
|
|
266
|
-
3. **Provide correction example**
|
|
267
|
-
4. **Request user confirmation** before proceeding
|
|
268
|
-
|
|
269
|
-
## Enforcement Checklist
|
|
270
|
-
|
|
271
|
-
Before committing framework changes:
|
|
272
|
-
- [ ] No Bash for file operations (use Read/Write/Edit/Glob/Grep)
|
|
273
|
-
- [ ] Components within size limits (skills <1000, commands <500)
|
|
274
|
-
- [ ] No language-specific code in framework
|
|
275
|
-
- [ ] All ambiguities use AskUserQuestion
|
|
276
|
-
- [ ] Context files read before development
|
|
277
|
-
- [ ] No circular dependencies
|
|
278
|
-
- [ ] Direct instructions, not narrative prose
|
|
279
|
-
- [ ] All components have frontmatter
|
|
280
|
-
- [ ] No hardcoded absolute paths
|
|
281
|
-
- [ ] Code search tool selection correct (Treelint for supported languages, Grep for unsupported)
|
|
282
|
-
|
|
283
|
-
---
|
|
284
|
-
|
|
285
|
-
**REMEMBER**: Projects using DevForgeAI will have their own anti-patterns.md with project-specific forbidden patterns (SQL injection, N+1 queries, God objects, etc.).
|