vibe-forge 0.1.0 → 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/commands/forge.md +147 -0
- package/.claude/settings.local.json +7 -0
- package/LICENSE +21 -21
- package/README.md +230 -211
- package/agents/forge-master/capabilities.md +144 -144
- package/agents/forge-master/context-template.md +128 -128
- package/bin/cli.js +3 -1
- package/bin/forge-daemon.sh +195 -71
- package/bin/forge-setup.sh +6 -6
- package/bin/forge-spawn.sh +46 -46
- package/bin/forge.sh +76 -127
- package/bin/lib/agents.sh +157 -0
- package/bin/lib/colors.sh +44 -0
- package/bin/lib/config.sh +259 -0
- package/bin/lib/constants.sh +143 -0
- package/config/agents.json +76 -0
- package/config/task-template.md +87 -87
- package/docs/TODO.md +65 -0
- package/docs/security.md +144 -0
- package/package.json +11 -2
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Vibe Forge - Configuration Management
|
|
4
|
+
# Source this file in other scripts: source "$SCRIPT_DIR/lib/config.sh"
|
|
5
|
+
#
|
|
6
|
+
# SECURITY: This module provides safe JSON parsing without grep/cut vulnerabilities.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
# Ensure colors are loaded for error messages
|
|
10
|
+
if ! type log_error &>/dev/null; then
|
|
11
|
+
echo "Error: colors.sh must be sourced before config.sh" >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# =============================================================================
|
|
16
|
+
# Agent Configuration Loading
|
|
17
|
+
# =============================================================================
|
|
18
|
+
|
|
19
|
+
# load_agents_from_json AGENTS_JSON_FILE
|
|
20
|
+
# Loads agent configuration from JSON file into shell variables.
|
|
21
|
+
# Sets: VALID_AGENTS array, AGENT_ALIASES associative array, AGENT_DISPLAY_NAMES
|
|
22
|
+
#
|
|
23
|
+
# SECURITY: Uses safe JSON parsing via Node.js
|
|
24
|
+
load_agents_from_json() {
|
|
25
|
+
local agents_file="$1"
|
|
26
|
+
|
|
27
|
+
if [[ ! -f "$agents_file" ]]; then
|
|
28
|
+
return 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
if ! command -v node &>/dev/null; then
|
|
32
|
+
log_error "Node.js required for agent configuration"
|
|
33
|
+
return 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Parse agents JSON and output shell variable assignments
|
|
37
|
+
# SECURITY: File path passed as argument, not interpolated
|
|
38
|
+
# NOTE: We output direct assignments (not declare -A) since arrays are pre-declared globally
|
|
39
|
+
local agent_data
|
|
40
|
+
agent_data=$(node -e '
|
|
41
|
+
const fs = require("fs");
|
|
42
|
+
const file = process.argv[1];
|
|
43
|
+
try {
|
|
44
|
+
const data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
45
|
+
const agents = data.agents || {};
|
|
46
|
+
|
|
47
|
+
// Output VALID_AGENTS array
|
|
48
|
+
const validAgents = Object.keys(agents);
|
|
49
|
+
console.log("VALID_AGENTS=(" + validAgents.map(a => `"${a}"`).join(" ") + ")");
|
|
50
|
+
|
|
51
|
+
// Output AGENT_ALIASES assignments (array already declared globally)
|
|
52
|
+
for (const [canonical, info] of Object.entries(agents)) {
|
|
53
|
+
// Add self-mapping
|
|
54
|
+
console.log(`AGENT_ALIASES["${canonical}"]="${canonical}"`);
|
|
55
|
+
// Add aliases
|
|
56
|
+
if (info.aliases) {
|
|
57
|
+
for (const alias of info.aliases) {
|
|
58
|
+
console.log(`AGENT_ALIASES["${alias}"]="${canonical}"`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Output AGENT_DISPLAY_NAMES assignments
|
|
64
|
+
for (const [canonical, info] of Object.entries(agents)) {
|
|
65
|
+
const displayName = info.name || canonical;
|
|
66
|
+
console.log(`AGENT_DISPLAY_NAMES["${canonical}"]="${displayName}"`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Output AGENT_ROLES assignments
|
|
70
|
+
for (const [canonical, info] of Object.entries(agents)) {
|
|
71
|
+
const role = info.role || "";
|
|
72
|
+
console.log(`AGENT_ROLES["${canonical}"]="${role}"`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Output AGENT_PERSONALITY_FILES assignments
|
|
76
|
+
for (const [canonical, info] of Object.entries(agents)) {
|
|
77
|
+
const pfile = info.personality_file || "";
|
|
78
|
+
console.log(`AGENT_PERSONALITY_FILES["${canonical}"]="${pfile}"`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
} catch (e) {
|
|
82
|
+
console.error("Error parsing agents.json:", e.message);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
' -- "$agents_file" 2>/dev/null) || return 1
|
|
86
|
+
|
|
87
|
+
# Evaluate the output to set variables
|
|
88
|
+
eval "$agent_data"
|
|
89
|
+
|
|
90
|
+
# Mark as loaded
|
|
91
|
+
AGENTS_LOADED="true"
|
|
92
|
+
return 0
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# json_get_string FILE KEY
|
|
96
|
+
# Safely extracts a string value from a JSON file.
|
|
97
|
+
# Uses node.js for safe parsing (available since we require Node 16+)
|
|
98
|
+
#
|
|
99
|
+
# SECURITY: This avoids grep/cut vulnerabilities by using proper JSON parsing.
|
|
100
|
+
# SECURITY: File and key are passed as command-line arguments, not interpolated.
|
|
101
|
+
json_get_string() {
|
|
102
|
+
local file="$1"
|
|
103
|
+
local key="$2"
|
|
104
|
+
|
|
105
|
+
if [[ ! -f "$file" ]]; then
|
|
106
|
+
return 1
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# Use Node.js for safe JSON parsing
|
|
110
|
+
# SECURITY: Pass file and key as arguments to avoid injection
|
|
111
|
+
if command -v node &>/dev/null; then
|
|
112
|
+
node -e '
|
|
113
|
+
const fs = require("fs");
|
|
114
|
+
const file = process.argv[1];
|
|
115
|
+
const key = process.argv[2];
|
|
116
|
+
try {
|
|
117
|
+
const data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
118
|
+
const value = data[key];
|
|
119
|
+
if (value !== undefined && value !== null) {
|
|
120
|
+
console.log(String(value));
|
|
121
|
+
}
|
|
122
|
+
} catch (e) {
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
' -- "$file" "$key" 2>/dev/null
|
|
126
|
+
return $?
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
# Fallback: Use Python if available
|
|
130
|
+
# SECURITY: Pass file and key as arguments to avoid injection
|
|
131
|
+
if command -v python3 &>/dev/null; then
|
|
132
|
+
python3 -c '
|
|
133
|
+
import json, sys
|
|
134
|
+
try:
|
|
135
|
+
file_path = sys.argv[1]
|
|
136
|
+
key = sys.argv[2]
|
|
137
|
+
with open(file_path) as f:
|
|
138
|
+
data = json.load(f)
|
|
139
|
+
value = data.get(key)
|
|
140
|
+
if value is not None:
|
|
141
|
+
print(str(value))
|
|
142
|
+
except:
|
|
143
|
+
sys.exit(1)
|
|
144
|
+
' "$file" "$key" 2>/dev/null
|
|
145
|
+
return $?
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
# No safe parser available - exit with error
|
|
149
|
+
log_error "No JSON parser available. Install Node.js or Python 3."
|
|
150
|
+
return 1
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# load_forge_config CONFIG_FILE
|
|
154
|
+
# Loads configuration from the forge config file into environment variables.
|
|
155
|
+
# Sets: PLATFORM, GIT_BASH_PATH, TERMINAL_TYPE, FORGE_VALIDATED
|
|
156
|
+
#
|
|
157
|
+
# Returns: 0 on success, 1 on failure
|
|
158
|
+
load_forge_config() {
|
|
159
|
+
local config_file="$1"
|
|
160
|
+
|
|
161
|
+
if [[ ! -f "$config_file" ]]; then
|
|
162
|
+
log_error "Vibe Forge not initialized."
|
|
163
|
+
echo "Run 'forge init' first." >&2
|
|
164
|
+
return 1
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Load config values safely
|
|
168
|
+
PLATFORM=$(json_get_string "$config_file" "platform") || PLATFORM=""
|
|
169
|
+
GIT_BASH_PATH=$(json_get_string "$config_file" "git_bash_path") || GIT_BASH_PATH=""
|
|
170
|
+
TERMINAL_TYPE=$(json_get_string "$config_file" "terminal_type") || TERMINAL_TYPE="manual"
|
|
171
|
+
FORGE_VALIDATED=$(json_get_string "$config_file" "validated") || FORGE_VALIDATED="false"
|
|
172
|
+
|
|
173
|
+
# Validate required fields
|
|
174
|
+
if [[ -z "$PLATFORM" ]]; then
|
|
175
|
+
log_error "Invalid config: missing platform"
|
|
176
|
+
return 1
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
return 0
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
# setup_windows_env
|
|
183
|
+
# Sets up Windows-specific environment variables and PATH.
|
|
184
|
+
# Call this after load_forge_config on Windows.
|
|
185
|
+
setup_windows_env() {
|
|
186
|
+
if [[ "$PLATFORM" != "windows" ]]; then
|
|
187
|
+
return 0
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# Export Git Bash path for Claude Code
|
|
191
|
+
if [[ -n "$GIT_BASH_PATH" ]]; then
|
|
192
|
+
# Convert forward slashes to backslashes for Windows
|
|
193
|
+
local git_bash_win="${GIT_BASH_PATH//\//\\}"
|
|
194
|
+
export CLAUDE_CODE_GIT_BASH_PATH="$git_bash_win"
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# Add npm global path if not already in PATH
|
|
198
|
+
local npm_path=""
|
|
199
|
+
|
|
200
|
+
# Try with USER variable
|
|
201
|
+
if [[ -n "$USER" ]]; then
|
|
202
|
+
npm_path="/c/Users/$USER/AppData/Roaming/npm"
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
# Try with USERPROFILE
|
|
206
|
+
if [[ -z "$npm_path" || ! -d "$npm_path" ]] && [[ -n "$USERPROFILE" ]]; then
|
|
207
|
+
npm_path="${USERPROFILE//\\//}/AppData/Roaming/npm"
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
# Add to PATH if exists and not already there
|
|
211
|
+
if [[ -n "$npm_path" && -d "$npm_path" && ":$PATH:" != *":$npm_path:"* ]]; then
|
|
212
|
+
export PATH="$npm_path:$PATH"
|
|
213
|
+
fi
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# require_forge_config FORGE_ROOT
|
|
217
|
+
# Loads config and exits with error if not initialized.
|
|
218
|
+
# Convenience function that combines load + validation.
|
|
219
|
+
require_forge_config() {
|
|
220
|
+
local forge_root="$1"
|
|
221
|
+
local config_file="$forge_root/.forge/config.json"
|
|
222
|
+
|
|
223
|
+
load_forge_config "$config_file" || exit 1
|
|
224
|
+
setup_windows_env
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
# write_json_config FILE KEY VALUE
|
|
228
|
+
# Safely writes/updates a key in a JSON config file.
|
|
229
|
+
# Creates file if it doesn't exist.
|
|
230
|
+
#
|
|
231
|
+
# SECURITY: File, key, and value are passed as command-line arguments, not interpolated.
|
|
232
|
+
write_json_config() {
|
|
233
|
+
local file="$1"
|
|
234
|
+
local key="$2"
|
|
235
|
+
local value="$3"
|
|
236
|
+
|
|
237
|
+
# Use Node.js for safe JSON manipulation
|
|
238
|
+
# SECURITY: Pass all values as arguments to avoid injection
|
|
239
|
+
if command -v node &>/dev/null; then
|
|
240
|
+
node -e '
|
|
241
|
+
const fs = require("fs");
|
|
242
|
+
const file = process.argv[1];
|
|
243
|
+
const key = process.argv[2];
|
|
244
|
+
const value = process.argv[3];
|
|
245
|
+
let data = {};
|
|
246
|
+
try {
|
|
247
|
+
if (fs.existsSync(file)) {
|
|
248
|
+
data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {}
|
|
251
|
+
data[key] = value;
|
|
252
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
|
|
253
|
+
' -- "$file" "$key" "$value" 2>/dev/null
|
|
254
|
+
return $?
|
|
255
|
+
fi
|
|
256
|
+
|
|
257
|
+
log_error "Node.js required for config writing"
|
|
258
|
+
return 1
|
|
259
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Vibe Forge - Shared Constants
|
|
4
|
+
# Source this file in other scripts: source "$SCRIPT_DIR/lib/constants.sh"
|
|
5
|
+
#
|
|
6
|
+
# NOTE: Agent configuration should be loaded from config/agents.json via
|
|
7
|
+
# load_agents_from_json() in config.sh. The hardcoded values below are
|
|
8
|
+
# fallback defaults for when JSON loading is not possible (e.g., tests).
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
# Timing
|
|
12
|
+
POLL_INTERVAL=2 # seconds between daemon task checks
|
|
13
|
+
NOTIFICATION_DEBOUNCE=1 # seconds to avoid notification spam
|
|
14
|
+
|
|
15
|
+
# Directory structure (relative to FORGE_ROOT)
|
|
16
|
+
CONFIG_DIR=".forge"
|
|
17
|
+
TASKS_DIR="tasks"
|
|
18
|
+
TASKS_PENDING="$TASKS_DIR/pending"
|
|
19
|
+
TASKS_IN_PROGRESS="$TASKS_DIR/in-progress"
|
|
20
|
+
TASKS_COMPLETED="$TASKS_DIR/completed"
|
|
21
|
+
TASKS_REVIEW="$TASKS_DIR/review"
|
|
22
|
+
TASKS_APPROVED="$TASKS_DIR/approved"
|
|
23
|
+
TASKS_NEEDS_CHANGES="$TASKS_DIR/needs-changes"
|
|
24
|
+
TASKS_MERGED="$TASKS_DIR/merged"
|
|
25
|
+
CONTEXT_DIR="context"
|
|
26
|
+
AGENTS_DIR="agents"
|
|
27
|
+
|
|
28
|
+
# Config files
|
|
29
|
+
AGENTS_CONFIG="config/agents.json"
|
|
30
|
+
|
|
31
|
+
# =============================================================================
|
|
32
|
+
# Agent Configuration (Fallback Defaults)
|
|
33
|
+
# =============================================================================
|
|
34
|
+
# These values are overwritten when load_agents_from_json() is called.
|
|
35
|
+
# They exist as fallback for contexts where JSON loading isn't available.
|
|
36
|
+
|
|
37
|
+
# Flag to track if agents were loaded from JSON
|
|
38
|
+
AGENTS_LOADED="${AGENTS_LOADED:-false}"
|
|
39
|
+
|
|
40
|
+
# Valid agent names (whitelist for security)
|
|
41
|
+
# These are the ONLY valid canonical agent names
|
|
42
|
+
VALID_AGENTS=(
|
|
43
|
+
"anvil"
|
|
44
|
+
"furnace"
|
|
45
|
+
"crucible"
|
|
46
|
+
"sentinel"
|
|
47
|
+
"scribe"
|
|
48
|
+
"herald"
|
|
49
|
+
"ember"
|
|
50
|
+
"aegis"
|
|
51
|
+
"hub"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Agent aliases map (for resolve_agent)
|
|
55
|
+
# Format: alias=canonical
|
|
56
|
+
declare -A AGENT_ALIASES=(
|
|
57
|
+
# Anvil aliases
|
|
58
|
+
["anvil"]="anvil"
|
|
59
|
+
["frontend"]="anvil"
|
|
60
|
+
["ui"]="anvil"
|
|
61
|
+
["fe"]="anvil"
|
|
62
|
+
# Furnace aliases
|
|
63
|
+
["furnace"]="furnace"
|
|
64
|
+
["backend"]="furnace"
|
|
65
|
+
["api"]="furnace"
|
|
66
|
+
["be"]="furnace"
|
|
67
|
+
# Crucible aliases
|
|
68
|
+
["crucible"]="crucible"
|
|
69
|
+
["test"]="crucible"
|
|
70
|
+
["testing"]="crucible"
|
|
71
|
+
["qa"]="crucible"
|
|
72
|
+
["tester"]="crucible"
|
|
73
|
+
# Sentinel aliases
|
|
74
|
+
["sentinel"]="sentinel"
|
|
75
|
+
["review"]="sentinel"
|
|
76
|
+
["reviewer"]="sentinel"
|
|
77
|
+
["cr"]="sentinel"
|
|
78
|
+
# Scribe aliases
|
|
79
|
+
["scribe"]="scribe"
|
|
80
|
+
["docs"]="scribe"
|
|
81
|
+
["documentation"]="scribe"
|
|
82
|
+
["doc"]="scribe"
|
|
83
|
+
# Herald aliases
|
|
84
|
+
["herald"]="herald"
|
|
85
|
+
["release"]="herald"
|
|
86
|
+
["deploy"]="herald"
|
|
87
|
+
["deployment"]="herald"
|
|
88
|
+
# Ember aliases
|
|
89
|
+
["ember"]="ember"
|
|
90
|
+
["devops"]="ember"
|
|
91
|
+
["ops"]="ember"
|
|
92
|
+
["infra"]="ember"
|
|
93
|
+
["infrastructure"]="ember"
|
|
94
|
+
# Aegis aliases
|
|
95
|
+
["aegis"]="aegis"
|
|
96
|
+
["security"]="aegis"
|
|
97
|
+
["sec"]="aegis"
|
|
98
|
+
["appsec"]="aegis"
|
|
99
|
+
# Hub aliases
|
|
100
|
+
["hub"]="hub"
|
|
101
|
+
["planning"]="hub"
|
|
102
|
+
["master"]="hub"
|
|
103
|
+
["forge-master"]="hub"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Agent display names
|
|
107
|
+
declare -A AGENT_DISPLAY_NAMES=(
|
|
108
|
+
["anvil"]="Anvil"
|
|
109
|
+
["furnace"]="Furnace"
|
|
110
|
+
["crucible"]="Crucible"
|
|
111
|
+
["sentinel"]="Sentinel"
|
|
112
|
+
["scribe"]="Scribe"
|
|
113
|
+
["herald"]="Herald"
|
|
114
|
+
["ember"]="Ember"
|
|
115
|
+
["aegis"]="Aegis"
|
|
116
|
+
["hub"]="Planning Hub"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Agent roles
|
|
120
|
+
declare -A AGENT_ROLES=(
|
|
121
|
+
["anvil"]="Frontend Developer"
|
|
122
|
+
["furnace"]="Backend Developer"
|
|
123
|
+
["crucible"]="Tester / QA"
|
|
124
|
+
["sentinel"]="Code Reviewer"
|
|
125
|
+
["scribe"]="Documentation"
|
|
126
|
+
["herald"]="Release Manager"
|
|
127
|
+
["ember"]="DevOps"
|
|
128
|
+
["aegis"]="Security"
|
|
129
|
+
["hub"]="Planning & Coordination"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Agent personality files (relative to FORGE_ROOT)
|
|
133
|
+
declare -A AGENT_PERSONALITY_FILES=(
|
|
134
|
+
["anvil"]="agents/anvil/personality.md"
|
|
135
|
+
["furnace"]="agents/furnace/personality.md"
|
|
136
|
+
["crucible"]="agents/crucible/personality.md"
|
|
137
|
+
["sentinel"]="agents/sentinel/personality.md"
|
|
138
|
+
["scribe"]="agents/scribe/personality.md"
|
|
139
|
+
["herald"]="agents/herald/personality.md"
|
|
140
|
+
["ember"]="agents/ember/personality.md"
|
|
141
|
+
["aegis"]="agents/aegis/personality.md"
|
|
142
|
+
["hub"]="agents/planning-hub/personality.md"
|
|
143
|
+
)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agents": {
|
|
3
|
+
"anvil": {
|
|
4
|
+
"name": "Anvil",
|
|
5
|
+
"icon": "🔨",
|
|
6
|
+
"role": "Frontend Developer",
|
|
7
|
+
"aliases": ["frontend", "ui", "fe"],
|
|
8
|
+
"type": "worker",
|
|
9
|
+
"personality_file": "agents/anvil/personality.md"
|
|
10
|
+
},
|
|
11
|
+
"furnace": {
|
|
12
|
+
"name": "Furnace",
|
|
13
|
+
"icon": "🔥",
|
|
14
|
+
"role": "Backend Developer",
|
|
15
|
+
"aliases": ["backend", "api", "be"],
|
|
16
|
+
"type": "worker",
|
|
17
|
+
"personality_file": "agents/furnace/personality.md"
|
|
18
|
+
},
|
|
19
|
+
"crucible": {
|
|
20
|
+
"name": "Crucible",
|
|
21
|
+
"icon": "🧪",
|
|
22
|
+
"role": "Tester / QA",
|
|
23
|
+
"aliases": ["test", "testing", "qa", "tester"],
|
|
24
|
+
"type": "worker",
|
|
25
|
+
"personality_file": "agents/crucible/personality.md"
|
|
26
|
+
},
|
|
27
|
+
"sentinel": {
|
|
28
|
+
"name": "Sentinel",
|
|
29
|
+
"icon": "🛡️",
|
|
30
|
+
"role": "Code Reviewer",
|
|
31
|
+
"aliases": ["review", "reviewer", "cr"],
|
|
32
|
+
"type": "core",
|
|
33
|
+
"personality_file": "agents/sentinel/personality.md"
|
|
34
|
+
},
|
|
35
|
+
"scribe": {
|
|
36
|
+
"name": "Scribe",
|
|
37
|
+
"icon": "📜",
|
|
38
|
+
"role": "Documentation",
|
|
39
|
+
"aliases": ["docs", "documentation", "doc"],
|
|
40
|
+
"type": "worker",
|
|
41
|
+
"personality_file": "agents/scribe/personality.md"
|
|
42
|
+
},
|
|
43
|
+
"herald": {
|
|
44
|
+
"name": "Herald",
|
|
45
|
+
"icon": "📯",
|
|
46
|
+
"role": "Release Manager",
|
|
47
|
+
"aliases": ["release", "deploy", "deployment"],
|
|
48
|
+
"type": "worker",
|
|
49
|
+
"personality_file": "agents/herald/personality.md"
|
|
50
|
+
},
|
|
51
|
+
"ember": {
|
|
52
|
+
"name": "Ember",
|
|
53
|
+
"icon": "⚙️",
|
|
54
|
+
"role": "DevOps",
|
|
55
|
+
"aliases": ["devops", "ops", "infra", "infrastructure"],
|
|
56
|
+
"type": "specialist",
|
|
57
|
+
"personality_file": "agents/ember/personality.md"
|
|
58
|
+
},
|
|
59
|
+
"aegis": {
|
|
60
|
+
"name": "Aegis",
|
|
61
|
+
"icon": "🔒",
|
|
62
|
+
"role": "Security",
|
|
63
|
+
"aliases": ["security", "sec", "appsec"],
|
|
64
|
+
"type": "specialist",
|
|
65
|
+
"personality_file": "agents/aegis/personality.md"
|
|
66
|
+
},
|
|
67
|
+
"hub": {
|
|
68
|
+
"name": "Planning Hub",
|
|
69
|
+
"icon": "🔥",
|
|
70
|
+
"role": "Planning & Coordination",
|
|
71
|
+
"aliases": ["planning", "master", "forge-master"],
|
|
72
|
+
"type": "core",
|
|
73
|
+
"personality_file": "agents/planning-hub/personality.md"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
package/config/task-template.md
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: task-{ID}
|
|
3
|
-
title: "{TITLE}"
|
|
4
|
-
type: {TYPE} # frontend | backend | test | docs | review | release | devops | security
|
|
5
|
-
priority: {PRIORITY} # critical | high | medium | low
|
|
6
|
-
status: pending
|
|
7
|
-
assigned_to: null
|
|
8
|
-
blocked_by: []
|
|
9
|
-
depends_on: []
|
|
10
|
-
created: {TIMESTAMP}
|
|
11
|
-
updated: {TIMESTAMP}
|
|
12
|
-
estimated_complexity: {COMPLEXITY} # trivial | low | medium | high | unknown
|
|
13
|
-
epic: {EPIC_ID}
|
|
14
|
-
story: {STORY_ID} # optional
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
# Context
|
|
18
|
-
|
|
19
|
-
## Parent Epic
|
|
20
|
-
See: /specs/epics/{EPIC_ID}.md
|
|
21
|
-
|
|
22
|
-
## Relevant Files
|
|
23
|
-
<!-- List ONLY files the agent needs to read or modify -->
|
|
24
|
-
- /path/to/relevant/file.ts (reason: what to do here)
|
|
25
|
-
- /path/to/reference/file.ts (reference only)
|
|
26
|
-
|
|
27
|
-
## Dependencies
|
|
28
|
-
<!-- Other tasks that must complete first -->
|
|
29
|
-
- task-{DEP_ID} (status: pending|completed)
|
|
30
|
-
|
|
31
|
-
## Background
|
|
32
|
-
<!-- Brief context the agent needs - keep minimal, reference docs instead -->
|
|
33
|
-
{BACKGROUND}
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
# Acceptance Criteria
|
|
38
|
-
|
|
39
|
-
<!-- Checkboxes for each requirement - agent marks complete as they work -->
|
|
40
|
-
- [ ] {CRITERION_1}
|
|
41
|
-
- [ ] {CRITERION_2}
|
|
42
|
-
- [ ] {CRITERION_3}
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
# Agent Instructions
|
|
47
|
-
|
|
48
|
-
<!-- Specific instructions for the assigned agent -->
|
|
49
|
-
{AGENT_TYPE}: {SPECIFIC_INSTRUCTIONS}
|
|
50
|
-
|
|
51
|
-
**Boundaries:**
|
|
52
|
-
- DO modify: {ALLOWED_PATHS}
|
|
53
|
-
- DO NOT modify: {FORBIDDEN_PATHS}
|
|
54
|
-
- If blocked, write blocker to task file and notify Forge Master
|
|
55
|
-
|
|
56
|
-
**On Completion:**
|
|
57
|
-
1. Ensure all acceptance criteria checked
|
|
58
|
-
2. Run relevant tests
|
|
59
|
-
3. Move this file to `/tasks/completed/`
|
|
60
|
-
4. Include completion summary below
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
# Output Expected
|
|
65
|
-
|
|
66
|
-
- [ ] Files created/modified (list paths in completion)
|
|
67
|
-
- [ ] Tests passing (include count)
|
|
68
|
-
- [ ] No linting errors
|
|
69
|
-
- [ ] Completion summary written
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
# Completion Summary
|
|
74
|
-
<!-- Filled by agent on completion -->
|
|
75
|
-
|
|
76
|
-
```yaml
|
|
77
|
-
completed_by: null
|
|
78
|
-
completed_at: null
|
|
79
|
-
duration_minutes: null
|
|
80
|
-
files_modified: []
|
|
81
|
-
files_created: []
|
|
82
|
-
tests_added: 0
|
|
83
|
-
tests_passing: 0
|
|
84
|
-
notes: ""
|
|
85
|
-
blockers_encountered: []
|
|
86
|
-
ready_for_review: false
|
|
87
|
-
```
|
|
1
|
+
---
|
|
2
|
+
id: task-{ID}
|
|
3
|
+
title: "{TITLE}"
|
|
4
|
+
type: {TYPE} # frontend | backend | test | docs | review | release | devops | security
|
|
5
|
+
priority: {PRIORITY} # critical | high | medium | low
|
|
6
|
+
status: pending
|
|
7
|
+
assigned_to: null
|
|
8
|
+
blocked_by: []
|
|
9
|
+
depends_on: []
|
|
10
|
+
created: {TIMESTAMP}
|
|
11
|
+
updated: {TIMESTAMP}
|
|
12
|
+
estimated_complexity: {COMPLEXITY} # trivial | low | medium | high | unknown
|
|
13
|
+
epic: {EPIC_ID}
|
|
14
|
+
story: {STORY_ID} # optional
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Context
|
|
18
|
+
|
|
19
|
+
## Parent Epic
|
|
20
|
+
See: /specs/epics/{EPIC_ID}.md
|
|
21
|
+
|
|
22
|
+
## Relevant Files
|
|
23
|
+
<!-- List ONLY files the agent needs to read or modify -->
|
|
24
|
+
- /path/to/relevant/file.ts (reason: what to do here)
|
|
25
|
+
- /path/to/reference/file.ts (reference only)
|
|
26
|
+
|
|
27
|
+
## Dependencies
|
|
28
|
+
<!-- Other tasks that must complete first -->
|
|
29
|
+
- task-{DEP_ID} (status: pending|completed)
|
|
30
|
+
|
|
31
|
+
## Background
|
|
32
|
+
<!-- Brief context the agent needs - keep minimal, reference docs instead -->
|
|
33
|
+
{BACKGROUND}
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# Acceptance Criteria
|
|
38
|
+
|
|
39
|
+
<!-- Checkboxes for each requirement - agent marks complete as they work -->
|
|
40
|
+
- [ ] {CRITERION_1}
|
|
41
|
+
- [ ] {CRITERION_2}
|
|
42
|
+
- [ ] {CRITERION_3}
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
# Agent Instructions
|
|
47
|
+
|
|
48
|
+
<!-- Specific instructions for the assigned agent -->
|
|
49
|
+
{AGENT_TYPE}: {SPECIFIC_INSTRUCTIONS}
|
|
50
|
+
|
|
51
|
+
**Boundaries:**
|
|
52
|
+
- DO modify: {ALLOWED_PATHS}
|
|
53
|
+
- DO NOT modify: {FORBIDDEN_PATHS}
|
|
54
|
+
- If blocked, write blocker to task file and notify Forge Master
|
|
55
|
+
|
|
56
|
+
**On Completion:**
|
|
57
|
+
1. Ensure all acceptance criteria checked
|
|
58
|
+
2. Run relevant tests
|
|
59
|
+
3. Move this file to `/tasks/completed/`
|
|
60
|
+
4. Include completion summary below
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
# Output Expected
|
|
65
|
+
|
|
66
|
+
- [ ] Files created/modified (list paths in completion)
|
|
67
|
+
- [ ] Tests passing (include count)
|
|
68
|
+
- [ ] No linting errors
|
|
69
|
+
- [ ] Completion summary written
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
# Completion Summary
|
|
74
|
+
<!-- Filled by agent on completion -->
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
completed_by: null
|
|
78
|
+
completed_at: null
|
|
79
|
+
duration_minutes: null
|
|
80
|
+
files_modified: []
|
|
81
|
+
files_created: []
|
|
82
|
+
tests_added: 0
|
|
83
|
+
tests_passing: 0
|
|
84
|
+
notes: ""
|
|
85
|
+
blockers_encountered: []
|
|
86
|
+
ready_for_review: false
|
|
87
|
+
```
|