claude-flow-novice 2.14.11 → 2.14.13
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/skills/cfn-agent-selector/select-agents.sh +45 -0
- package/.claude/skills/cfn-loop-orchestration/helpers/context-injection.sh +69 -6
- package/.claude/skills/cfn-loop-orchestration/helpers/validate-task-context.sh +241 -0
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +22 -72
- package/.claude/skills/cfn-redis-coordination/get-context.sh +113 -0
- package/.claude/skills/cfn-redis-coordination/store-context.sh +74 -19
- package/claude-assets/skills/cfn-agent-selector/select-agents.sh +45 -0
- package/claude-assets/skills/cfn-loop-orchestration/helpers/context-injection.sh +69 -6
- package/claude-assets/skills/cfn-loop-orchestration/helpers/validate-task-context.sh +241 -0
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +22 -72
- package/claude-assets/skills/cfn-redis-coordination/get-context.sh +113 -0
- package/claude-assets/skills/cfn-redis-coordination/store-context.sh +74 -19
- package/package.json +1 -1
- package/scripts/init-project.js +56 -3
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Retrieve CFN Loop task context from Redis
|
|
3
|
+
# Used by CLI-spawned agents to get structured context from orchestrator
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# get-context.sh --task-id <id> [--namespace <ns>]
|
|
7
|
+
# get-context.sh --task-id <id> --key <key> [--namespace <ns>]
|
|
8
|
+
# get-context.sh <task_id> (legacy mode)
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
# Initialize variables
|
|
13
|
+
TASK_ID=""
|
|
14
|
+
KEY=""
|
|
15
|
+
NAMESPACE="swarm"
|
|
16
|
+
FORMAT="json" # json or raw
|
|
17
|
+
|
|
18
|
+
# Parse arguments
|
|
19
|
+
while [[ $# -gt 0 ]]; do
|
|
20
|
+
case $1 in
|
|
21
|
+
--task-id)
|
|
22
|
+
TASK_ID="$2"
|
|
23
|
+
shift 2
|
|
24
|
+
;;
|
|
25
|
+
--key)
|
|
26
|
+
KEY="$2"
|
|
27
|
+
shift 2
|
|
28
|
+
;;
|
|
29
|
+
--namespace)
|
|
30
|
+
NAMESPACE="$2"
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
--format)
|
|
34
|
+
FORMAT="$2"
|
|
35
|
+
shift 2
|
|
36
|
+
;;
|
|
37
|
+
*)
|
|
38
|
+
# Legacy mode: positional argument
|
|
39
|
+
if [ -z "$TASK_ID" ]; then
|
|
40
|
+
TASK_ID="$1"
|
|
41
|
+
fi
|
|
42
|
+
shift
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
done
|
|
46
|
+
|
|
47
|
+
# Validate required arguments
|
|
48
|
+
if [ -z "$TASK_ID" ]; then
|
|
49
|
+
echo "Error: --task-id or TASK_ID required" >&2
|
|
50
|
+
echo "Usage: $0 --task-id <id> [--key <key>] [--namespace <ns>] [--format <json|raw>]" >&2
|
|
51
|
+
echo " or: $0 <task_id> (legacy)" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
REDIS_KEY="${NAMESPACE}:${TASK_ID}:context"
|
|
56
|
+
|
|
57
|
+
# Check if context exists
|
|
58
|
+
if ! redis-cli EXISTS "$REDIS_KEY" >/dev/null 2>&1; then
|
|
59
|
+
echo "⚠️ No context found for task: $TASK_ID" >&2
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Handle specific key retrieval
|
|
64
|
+
if [ -n "$KEY" ]; then
|
|
65
|
+
VALUE=$(redis-cli HGET "$REDIS_KEY" "$KEY" 2>/dev/null || echo "")
|
|
66
|
+
if [ -z "$VALUE" ]; then
|
|
67
|
+
echo "⚠️ Key '$KEY' not found in context for task: $TASK_ID" >&2
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [ "$FORMAT" = "raw" ]; then
|
|
72
|
+
echo "$VALUE"
|
|
73
|
+
else
|
|
74
|
+
echo "{\"$KEY\":$VALUE}"
|
|
75
|
+
fi
|
|
76
|
+
exit 0
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Handle full context retrieval
|
|
80
|
+
ALL_FIELDS=$(redis-cli HGETALL "$REDIS_KEY" 2>/dev/null || echo "")
|
|
81
|
+
|
|
82
|
+
if [ -z "$ALL_FIELDS" ]; then
|
|
83
|
+
echo "⚠️ Empty context for task: $TASK_ID" >&2
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Format as JSON
|
|
88
|
+
if [ "$FORMAT" = "json" ]; then
|
|
89
|
+
echo "{"
|
|
90
|
+
first=true
|
|
91
|
+
while IFS= read -r field; do
|
|
92
|
+
if [ -z "$field" ]; then continue; fi
|
|
93
|
+
if [ "$first" = true ]; then
|
|
94
|
+
first=false
|
|
95
|
+
else
|
|
96
|
+
echo ","
|
|
97
|
+
fi
|
|
98
|
+
# Skip empty lines and properly format JSON values
|
|
99
|
+
if [[ $field =~ ^[0-9]+$ ]]; then
|
|
100
|
+
# Numeric value
|
|
101
|
+
echo -n " \"$field\": $(redis-cli HGET "$REDIS_KEY" "$field")"
|
|
102
|
+
else
|
|
103
|
+
# String value
|
|
104
|
+
value=$(redis-cli HGET "$REDIS_KEY" "$field" | sed 's/"/\\"/g')
|
|
105
|
+
echo -n " \"$field\": \"$value\""
|
|
106
|
+
fi
|
|
107
|
+
done <<< "$ALL_FIELDS"
|
|
108
|
+
echo ""
|
|
109
|
+
echo "}"
|
|
110
|
+
else
|
|
111
|
+
# Raw format
|
|
112
|
+
redis-cli HGETALL "$REDIS_KEY"
|
|
113
|
+
fi
|
|
@@ -1,34 +1,89 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Store CFN Loop task context in Redis
|
|
3
|
-
# Used by orchestrator to pass context to CLI-spawned agents
|
|
3
|
+
# Used by orchestrator to pass structured context to CLI-spawned agents
|
|
4
4
|
#
|
|
5
|
-
# Usage:
|
|
5
|
+
# Usage:
|
|
6
|
+
# store-context.sh --task-id <id> --key <key> --value <value> [--namespace <ns>]
|
|
7
|
+
# store-context.sh <task_id> <context_json> (legacy mode)
|
|
6
8
|
|
|
7
9
|
set -euo pipefail
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
# Initialize variables
|
|
12
|
+
TASK_ID=""
|
|
13
|
+
KEY=""
|
|
14
|
+
VALUE=""
|
|
15
|
+
NAMESPACE="swarm"
|
|
16
|
+
CONTEXT=""
|
|
11
17
|
|
|
18
|
+
# Parse arguments
|
|
19
|
+
while [[ $# -gt 0 ]]; do
|
|
20
|
+
case $1 in
|
|
21
|
+
--task-id)
|
|
22
|
+
TASK_ID="$2"
|
|
23
|
+
shift 2
|
|
24
|
+
;;
|
|
25
|
+
--key)
|
|
26
|
+
KEY="$2"
|
|
27
|
+
shift 2
|
|
28
|
+
;;
|
|
29
|
+
--value)
|
|
30
|
+
VALUE="$2"
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
--namespace)
|
|
34
|
+
NAMESPACE="$2"
|
|
35
|
+
shift 2
|
|
36
|
+
;;
|
|
37
|
+
*)
|
|
38
|
+
# Legacy mode: positional arguments
|
|
39
|
+
if [ -z "$TASK_ID" ]; then
|
|
40
|
+
TASK_ID="$1"
|
|
41
|
+
elif [ -z "$CONTEXT" ]; then
|
|
42
|
+
CONTEXT="$1"
|
|
43
|
+
fi
|
|
44
|
+
shift
|
|
45
|
+
;;
|
|
46
|
+
esac
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
# Validate required arguments
|
|
12
50
|
if [ -z "$TASK_ID" ]; then
|
|
13
|
-
echo "Error: TASK_ID required" >&2
|
|
14
|
-
echo "Usage: $0 <
|
|
51
|
+
echo "Error: --task-id or TASK_ID required" >&2
|
|
52
|
+
echo "Usage: $0 --task-id <id> --key <key> --value <value> [--namespace <ns>]" >&2
|
|
53
|
+
echo " or: $0 <task_id> <context_json> (legacy)" >&2
|
|
15
54
|
exit 1
|
|
16
55
|
fi
|
|
17
56
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
57
|
+
# Handle structured mode (new)
|
|
58
|
+
if [ -n "$KEY" ] && [ -n "$VALUE" ]; then
|
|
59
|
+
# Store structured context with specific key
|
|
60
|
+
REDIS_KEY="${NAMESPACE}:${TASK_ID}:context"
|
|
61
|
+
|
|
62
|
+
redis-cli HSET "$REDIS_KEY" \
|
|
63
|
+
"$KEY" "$VALUE" \
|
|
64
|
+
"updated_at" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
65
|
+
> /dev/null
|
|
66
|
+
|
|
67
|
+
# Set TTL (24 hours)
|
|
68
|
+
redis-cli EXPIRE "$REDIS_KEY" 86400 > /dev/null
|
|
69
|
+
|
|
70
|
+
echo "✅ Context stored: $KEY for task: $TASK_ID"
|
|
71
|
+
exit 0
|
|
22
72
|
fi
|
|
23
73
|
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
74
|
+
# Handle legacy mode
|
|
75
|
+
if [ -n "$CONTEXT" ]; then
|
|
76
|
+
redis-cli HSET "swarm:${TASK_ID}:context" \
|
|
77
|
+
"task_description" "$CONTEXT" \
|
|
78
|
+
"stored_at" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
79
|
+
> /dev/null
|
|
80
|
+
|
|
81
|
+
# Set TTL (24 hours)
|
|
82
|
+
redis-cli EXPIRE "swarm:${TASK_ID}:context" 86400 > /dev/null
|
|
29
83
|
|
|
30
|
-
|
|
31
|
-
|
|
84
|
+
echo "✅ Context stored for task: $TASK_ID"
|
|
85
|
+
exit 0
|
|
86
|
+
fi
|
|
32
87
|
|
|
33
|
-
echo "
|
|
34
|
-
exit
|
|
88
|
+
echo "Error: Either --key/--value or <context_json> required" >&2
|
|
89
|
+
exit 1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow-novice",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.13",
|
|
4
4
|
"description": "AI agent orchestration framework with namespace-isolated skills, agents, and CFN Loop validation. Safe installation with ~0.01% collision risk.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
package/scripts/init-project.js
CHANGED
|
@@ -227,12 +227,65 @@ async function installLizard() {
|
|
|
227
227
|
console.log(chalk.gray(' or run: ./tools/install-lizard.sh'));
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
// Parse command line arguments
|
|
231
|
+
function parseArgs() {
|
|
232
|
+
const args = process.argv.slice(2);
|
|
233
|
+
const options = {
|
|
234
|
+
force: false
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
for (const arg of args) {
|
|
238
|
+
if (arg === '--force' || arg === '-f') {
|
|
239
|
+
options.force = true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return options;
|
|
244
|
+
}
|
|
245
|
+
|
|
230
246
|
async function initializeCfnProject() {
|
|
231
|
-
//
|
|
247
|
+
// Parse command line arguments
|
|
248
|
+
const options = parseArgs();
|
|
249
|
+
|
|
250
|
+
// Check initialization status and handle incomplete setups
|
|
232
251
|
const markerPath = '.claude/.cfn-initialized';
|
|
252
|
+
const requiredPaths = [
|
|
253
|
+
'.claude/agents/cfn-dev-team',
|
|
254
|
+
'.claude/skills',
|
|
255
|
+
'.claude/hooks',
|
|
256
|
+
'.claude/commands'
|
|
257
|
+
];
|
|
258
|
+
|
|
233
259
|
if (fs.existsSync(markerPath)) {
|
|
234
|
-
//
|
|
235
|
-
|
|
260
|
+
// Check if initialization appears complete
|
|
261
|
+
const missingPaths = requiredPaths.filter(path => !fs.existsSync(path));
|
|
262
|
+
|
|
263
|
+
if (missingPaths.length === 0 && !options.force) {
|
|
264
|
+
console.log(chalk.green('✅ CFN already properly initialized'));
|
|
265
|
+
console.log(chalk.gray(' Use --force to reinitialize'));
|
|
266
|
+
return;
|
|
267
|
+
} else if (options.force) {
|
|
268
|
+
console.log(chalk.yellow('🚀 Force reinitializing CFN...'));
|
|
269
|
+
console.log(chalk.gray('Removing previous installation...'));
|
|
270
|
+
fs.rmSync(markerPath, { force: true });
|
|
271
|
+
// Remove existing directories for clean reinitialization
|
|
272
|
+
requiredPaths.forEach(path => {
|
|
273
|
+
if (fs.existsSync(path)) {
|
|
274
|
+
fs.rmSync(path, { recursive: true, force: true });
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
console.log(chalk.gray('Previous installation removed'));
|
|
278
|
+
} else {
|
|
279
|
+
console.log(chalk.yellow('⚠️ CFN initialization incomplete - reinitializing...'));
|
|
280
|
+
console.log(chalk.gray(`Missing components: ${missingPaths.join(', ')}`));
|
|
281
|
+
console.log(chalk.gray('Removing incomplete initialization marker...'));
|
|
282
|
+
fs.rmSync(markerPath, { force: true });
|
|
283
|
+
// Continue with full initialization
|
|
284
|
+
}
|
|
285
|
+
} else {
|
|
286
|
+
if (options.force) {
|
|
287
|
+
console.log(chalk.yellow('🚀 Force initializing CFN...'));
|
|
288
|
+
}
|
|
236
289
|
}
|
|
237
290
|
|
|
238
291
|
console.log(chalk.blue('\n🚀 Claude Flow Novice CFN Initialization\n'));
|