moflo 4.8.11 → 4.8.12
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/browser/browser-agent.yaml +182 -0
- package/.claude/guidance/moflo-bootstrap.md +129 -0
- package/.claude/helpers/gate-hook.mjs +50 -0
- package/.claude/helpers/gate.cjs +19 -117
- package/.claude/helpers/hook-handler.cjs +66 -324
- package/.claude/helpers/post-commit +16 -0
- package/.claude/helpers/pre-commit +26 -0
- package/.claude/helpers/prompt-hook.mjs +72 -0
- package/.claude/scripts/build-embeddings.mjs +549 -0
- package/.claude/scripts/generate-code-map.mjs +697 -0
- package/.claude/scripts/hooks.mjs +656 -0
- package/.claude/scripts/index-guidance.mjs +893 -0
- package/.claude/scripts/index-tests.mjs +710 -0
- package/.claude/scripts/semantic-search.mjs +473 -0
- package/.claude/scripts/session-start-launcher.mjs +226 -0
- package/.claude/settings.json +351 -290
- package/.claude/settings.local.json +2 -1
- package/.claude/skills/browser/SKILL.md +204 -0
- package/.claude/workflow-state.json +9 -0
- package/bin/index-guidance.mjs +1 -1
- package/bin/index-tests.mjs +1 -1
- package/bin/semantic-search.mjs +1 -1
- package/bin/setup-project.mjs +61 -64
- package/package.json +2 -2
- package/src/@claude-flow/cli/dist/src/init/claudemd-generator.d.ts +29 -24
- package/src/@claude-flow/cli/dist/src/init/claudemd-generator.js +73 -494
- package/src/@claude-flow/cli/dist/src/init/moflo-init.d.ts +30 -30
- package/src/@claude-flow/cli/dist/src/init/moflo-init.js +712 -717
- package/src/@claude-flow/cli/package.json +106 -106
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Browser Agent Configuration
|
|
2
|
+
# AI-powered web browser automation using agent-browser
|
|
3
|
+
#
|
|
4
|
+
# Capabilities:
|
|
5
|
+
# - Web navigation and interaction
|
|
6
|
+
# - AI-optimized snapshots with element refs
|
|
7
|
+
# - Form filling and submission
|
|
8
|
+
# - Screenshot capture
|
|
9
|
+
# - Network interception
|
|
10
|
+
# - Multi-session coordination
|
|
11
|
+
|
|
12
|
+
name: browser-agent
|
|
13
|
+
description: Web automation specialist using agent-browser with AI-optimized snapshots
|
|
14
|
+
version: 1.0.0
|
|
15
|
+
|
|
16
|
+
# Routing configuration
|
|
17
|
+
routing:
|
|
18
|
+
complexity: medium
|
|
19
|
+
model: sonnet # Good at visual reasoning and DOM interpretation
|
|
20
|
+
priority: normal
|
|
21
|
+
keywords:
|
|
22
|
+
- browser
|
|
23
|
+
- web
|
|
24
|
+
- scrape
|
|
25
|
+
- screenshot
|
|
26
|
+
- navigate
|
|
27
|
+
- login
|
|
28
|
+
- form
|
|
29
|
+
- click
|
|
30
|
+
- automate
|
|
31
|
+
|
|
32
|
+
# Agent capabilities
|
|
33
|
+
capabilities:
|
|
34
|
+
- web-navigation
|
|
35
|
+
- form-interaction
|
|
36
|
+
- screenshot-capture
|
|
37
|
+
- data-extraction
|
|
38
|
+
- network-interception
|
|
39
|
+
- session-management
|
|
40
|
+
- multi-tab-coordination
|
|
41
|
+
|
|
42
|
+
# Available tools (MCP tools with browser/ prefix)
|
|
43
|
+
tools:
|
|
44
|
+
navigation:
|
|
45
|
+
- browser/open
|
|
46
|
+
- browser/back
|
|
47
|
+
- browser/forward
|
|
48
|
+
- browser/reload
|
|
49
|
+
- browser/close
|
|
50
|
+
snapshot:
|
|
51
|
+
- browser/snapshot
|
|
52
|
+
- browser/screenshot
|
|
53
|
+
- browser/pdf
|
|
54
|
+
interaction:
|
|
55
|
+
- browser/click
|
|
56
|
+
- browser/fill
|
|
57
|
+
- browser/type
|
|
58
|
+
- browser/press
|
|
59
|
+
- browser/hover
|
|
60
|
+
- browser/select
|
|
61
|
+
- browser/check
|
|
62
|
+
- browser/uncheck
|
|
63
|
+
- browser/scroll
|
|
64
|
+
- browser/upload
|
|
65
|
+
info:
|
|
66
|
+
- browser/get-text
|
|
67
|
+
- browser/get-html
|
|
68
|
+
- browser/get-value
|
|
69
|
+
- browser/get-attr
|
|
70
|
+
- browser/get-title
|
|
71
|
+
- browser/get-url
|
|
72
|
+
- browser/get-count
|
|
73
|
+
state:
|
|
74
|
+
- browser/is-visible
|
|
75
|
+
- browser/is-enabled
|
|
76
|
+
- browser/is-checked
|
|
77
|
+
wait:
|
|
78
|
+
- browser/wait
|
|
79
|
+
eval:
|
|
80
|
+
- browser/eval
|
|
81
|
+
storage:
|
|
82
|
+
- browser/cookies-get
|
|
83
|
+
- browser/cookies-set
|
|
84
|
+
- browser/cookies-clear
|
|
85
|
+
- browser/localstorage-get
|
|
86
|
+
- browser/localstorage-set
|
|
87
|
+
network:
|
|
88
|
+
- browser/network-route
|
|
89
|
+
- browser/network-unroute
|
|
90
|
+
- browser/network-requests
|
|
91
|
+
tabs:
|
|
92
|
+
- browser/tab-list
|
|
93
|
+
- browser/tab-new
|
|
94
|
+
- browser/tab-switch
|
|
95
|
+
- browser/tab-close
|
|
96
|
+
- browser/session-list
|
|
97
|
+
settings:
|
|
98
|
+
- browser/set-viewport
|
|
99
|
+
- browser/set-device
|
|
100
|
+
- browser/set-geolocation
|
|
101
|
+
- browser/set-offline
|
|
102
|
+
- browser/set-media
|
|
103
|
+
debug:
|
|
104
|
+
- browser/trace-start
|
|
105
|
+
- browser/trace-stop
|
|
106
|
+
- browser/console
|
|
107
|
+
- browser/errors
|
|
108
|
+
- browser/highlight
|
|
109
|
+
- browser/state-save
|
|
110
|
+
- browser/state-load
|
|
111
|
+
find:
|
|
112
|
+
- browser/find-role
|
|
113
|
+
- browser/find-text
|
|
114
|
+
- browser/find-label
|
|
115
|
+
- browser/find-testid
|
|
116
|
+
|
|
117
|
+
# Memory configuration
|
|
118
|
+
memory:
|
|
119
|
+
namespace: browser-sessions
|
|
120
|
+
persist: true
|
|
121
|
+
patterns:
|
|
122
|
+
- login-flows
|
|
123
|
+
- form-submissions
|
|
124
|
+
- scraping-patterns
|
|
125
|
+
- navigation-sequences
|
|
126
|
+
|
|
127
|
+
# Swarm integration
|
|
128
|
+
swarm:
|
|
129
|
+
roles:
|
|
130
|
+
- navigator # Handles authentication and navigation
|
|
131
|
+
- scraper # Extracts data using snapshots
|
|
132
|
+
- validator # Verifies extracted data
|
|
133
|
+
- tester # Runs automated tests
|
|
134
|
+
- monitor # Watches for errors and network issues
|
|
135
|
+
topology: hierarchical # Coordinator manages browser agents
|
|
136
|
+
max_sessions: 5
|
|
137
|
+
|
|
138
|
+
# Hooks integration
|
|
139
|
+
hooks:
|
|
140
|
+
pre_task:
|
|
141
|
+
- route # Get optimal routing
|
|
142
|
+
- memory_search # Check for similar patterns
|
|
143
|
+
post_task:
|
|
144
|
+
- memory_store # Save successful patterns
|
|
145
|
+
- post_edit # Train on outcomes
|
|
146
|
+
|
|
147
|
+
# Default configuration
|
|
148
|
+
defaults:
|
|
149
|
+
timeout: 30000
|
|
150
|
+
headless: true
|
|
151
|
+
viewport:
|
|
152
|
+
width: 1280
|
|
153
|
+
height: 720
|
|
154
|
+
|
|
155
|
+
# Example workflows
|
|
156
|
+
workflows:
|
|
157
|
+
login:
|
|
158
|
+
description: Authenticate to a website
|
|
159
|
+
steps:
|
|
160
|
+
- open: "{url}/login"
|
|
161
|
+
- snapshot: { interactive: true }
|
|
162
|
+
- fill: { target: "@e1", value: "{username}" }
|
|
163
|
+
- fill: { target: "@e2", value: "{password}" }
|
|
164
|
+
- click: "@e3"
|
|
165
|
+
- wait: { url: "**/dashboard" }
|
|
166
|
+
- state-save: "auth-state.json"
|
|
167
|
+
|
|
168
|
+
scrape_list:
|
|
169
|
+
description: Extract data from a list page
|
|
170
|
+
steps:
|
|
171
|
+
- open: "{url}"
|
|
172
|
+
- snapshot: { interactive: true, compact: true }
|
|
173
|
+
- eval: "Array.from(document.querySelectorAll('{selector}')).map(el => el.textContent)"
|
|
174
|
+
|
|
175
|
+
form_submit:
|
|
176
|
+
description: Fill and submit a form
|
|
177
|
+
steps:
|
|
178
|
+
- open: "{url}"
|
|
179
|
+
- snapshot: { interactive: true }
|
|
180
|
+
- fill_fields: "{fields}"
|
|
181
|
+
- click: "{submit_button}"
|
|
182
|
+
- wait: { text: "{success_text}" }
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<!-- AUTO-GENERATED by moflo session-start. Do not edit — changes will be overwritten. -->
|
|
2
|
+
<!-- Source: node_modules/moflo/.claude/guidance/agent-bootstrap.md -->
|
|
3
|
+
|
|
4
|
+
# MoFlo Agent Bootstrap Guide
|
|
5
|
+
|
|
6
|
+
**Purpose:** Quick-start reference for subagents spawned by coordinators. Every subagent should follow this protocol before doing any work.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Search Memory FIRST
|
|
11
|
+
|
|
12
|
+
**Before reading any files or exploring code, search memory for guidance relevant to your task.**
|
|
13
|
+
|
|
14
|
+
### Three namespaces to search:
|
|
15
|
+
|
|
16
|
+
| Namespace | When to search | What it returns |
|
|
17
|
+
|-----------|---------------|-----------------|
|
|
18
|
+
| `guidance` | Understanding patterns, rules, conventions | Guidance docs, coding rules, domain context |
|
|
19
|
+
| `code-map` | Finding where code lives (files, types, services) | Project overviews, directory contents, type-to-file mappings |
|
|
20
|
+
| `patterns` | Prior solutions, gotchas, implementation patterns | Learned patterns from previous task execution |
|
|
21
|
+
|
|
22
|
+
**Always search `patterns` alongside `guidance`.** It contains solutions to problems already solved — skipping it means repeating past mistakes or re-discovering known approaches.
|
|
23
|
+
|
|
24
|
+
**Search `code-map` BEFORE using Glob/Grep for navigation.** It's faster and returns structured results including file-level type mappings.
|
|
25
|
+
|
|
26
|
+
### Option A: MCP Tools (Preferred)
|
|
27
|
+
|
|
28
|
+
If you have MCP tools available (check for `mcp__moflo__*`), use them directly:
|
|
29
|
+
|
|
30
|
+
| Tool | Purpose |
|
|
31
|
+
|------|---------|
|
|
32
|
+
| `mcp__moflo__memory_search` | Semantic search with domain-aware embeddings |
|
|
33
|
+
| `mcp__moflo__memory_store` | Store patterns with auto-vectorization |
|
|
34
|
+
| `mcp__moflo__hooks_route` | Get agent routing suggestions |
|
|
35
|
+
|
|
36
|
+
### Option B: CLI via Bash
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx flo memory search --query "[describe your task]" --namespace guidance --limit 5
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Your task involves... | Search namespace | Example query |
|
|
43
|
+
|-----------------------|------------------|---------------|
|
|
44
|
+
| Database/entities | `guidance` + `patterns` | `"database entity migration"` |
|
|
45
|
+
| Frontend components | `guidance` + `patterns` | `"React frontend component"` |
|
|
46
|
+
| API endpoints | `guidance` + `patterns` | `"API route endpoint pattern"` |
|
|
47
|
+
| Authentication | `guidance` + `patterns` | `"auth middleware JWT"` |
|
|
48
|
+
| Unit tests | `guidance` + `patterns` | `"test mock vitest"` |
|
|
49
|
+
| Prior solutions/gotchas | `patterns` | `"audit log service pattern"` |
|
|
50
|
+
| Where is a file/type? | `code-map` | `"CompanyEntity file location"` |
|
|
51
|
+
| What's in a directory? | `code-map` | `"back-office api routes"` |
|
|
52
|
+
|
|
53
|
+
Use results with score > 0.3. If no good results, fall back to reading project guidance docs.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 2. Check Project-Specific Bootstrap
|
|
58
|
+
|
|
59
|
+
**After reading this file, check for a project-specific bootstrap:**
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Project-specific bootstrap (has domain rules, patterns, templates)
|
|
63
|
+
cat .claude/guidance/agent-bootstrap.md 2>/dev/null | head -10
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
If `.claude/guidance/agent-bootstrap.md` exists, **read it next**. It contains project-specific rules (entity patterns, multi-tenancy, tech stack conventions) that override generic guidance.
|
|
67
|
+
|
|
68
|
+
If no project bootstrap exists, look for general project guidance:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ls .claude/guidance/ 2>/dev/null
|
|
72
|
+
cat .claude/guidance/core.md 2>/dev/null | head -50
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Project guidance always takes precedence over generic patterns.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 3. Universal Rules
|
|
80
|
+
|
|
81
|
+
### Memory Protocol
|
|
82
|
+
- Search memory before exploring files
|
|
83
|
+
- Store discoveries back to memory when done
|
|
84
|
+
- Use `patterns` namespace for solutions and gotchas
|
|
85
|
+
- Use `decisions` namespace for architectural choices
|
|
86
|
+
|
|
87
|
+
### Git/Branches
|
|
88
|
+
- Use conventional commit prefixes: `feat:`, `fix:`, `refactor:`, `test:`, `chore:`
|
|
89
|
+
- Use branch prefixes: `feature/`, `fix/`, `refactor/`
|
|
90
|
+
- Use kebab-case for branch names
|
|
91
|
+
|
|
92
|
+
### File Organization
|
|
93
|
+
- Never save working files to repository root
|
|
94
|
+
- Keep changes focused (3-10 files)
|
|
95
|
+
- Stay within feature scope
|
|
96
|
+
|
|
97
|
+
### Build & Test
|
|
98
|
+
- Build and test after code changes
|
|
99
|
+
- Never leave failing tests
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 4. Store Discoveries
|
|
104
|
+
|
|
105
|
+
If you discover something new (pattern, solution, gotcha), store it:
|
|
106
|
+
|
|
107
|
+
### MCP (Preferred):
|
|
108
|
+
```
|
|
109
|
+
mcp__moflo__memory_store
|
|
110
|
+
namespace: "patterns"
|
|
111
|
+
key: "brief-descriptive-key"
|
|
112
|
+
value: "1-2 sentence insight"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### CLI Fallback:
|
|
116
|
+
```bash
|
|
117
|
+
npx flo memory store --namespace patterns --key "brief-descriptive-key" --value "1-2 sentence insight"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Store:** Solutions to tricky bugs, patterns that worked, gotchas, workarounds
|
|
121
|
+
**Skip:** Summaries of retrieved guidance, general rules, file locations
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 5. When Complete
|
|
126
|
+
|
|
127
|
+
1. Report findings to coordinator
|
|
128
|
+
2. Store learnings if you discovered something new
|
|
129
|
+
3. Coordinator will mark your task as completed
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
|
|
5
|
+
var command = process.argv[2];
|
|
6
|
+
if (!command) process.exit(0);
|
|
7
|
+
|
|
8
|
+
// Read stdin JSON from Claude Code
|
|
9
|
+
var stdinData = '';
|
|
10
|
+
try {
|
|
11
|
+
stdinData = await new Promise(function(res) {
|
|
12
|
+
var data = '';
|
|
13
|
+
var timeout = setTimeout(function() { res(data); }, 500);
|
|
14
|
+
process.stdin.setEncoding('utf-8');
|
|
15
|
+
process.stdin.on('data', function(chunk) { data += chunk; });
|
|
16
|
+
process.stdin.on('end', function() { clearTimeout(timeout); res(data); });
|
|
17
|
+
process.stdin.on('error', function() { clearTimeout(timeout); res(''); });
|
|
18
|
+
if (process.stdin.isTTY) { clearTimeout(timeout); res(''); }
|
|
19
|
+
});
|
|
20
|
+
} catch (e) { /* no stdin */ }
|
|
21
|
+
|
|
22
|
+
var hookContext = {};
|
|
23
|
+
try { if (stdinData.trim()) hookContext = JSON.parse(stdinData); } catch (e) {}
|
|
24
|
+
|
|
25
|
+
// Pass tool info as env vars for gate.cjs
|
|
26
|
+
var env = Object.assign({}, process.env);
|
|
27
|
+
if (hookContext.tool_name) env.TOOL_NAME = hookContext.tool_name;
|
|
28
|
+
if (hookContext.tool_input && typeof hookContext.tool_input === 'object') {
|
|
29
|
+
Object.keys(hookContext.tool_input).forEach(function(key) {
|
|
30
|
+
if (typeof hookContext.tool_input[key] === 'string') {
|
|
31
|
+
env['TOOL_INPUT_' + key] = hookContext.tool_input[key];
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Run gate.cjs with the enriched environment
|
|
37
|
+
var projectDir = (env.CLAUDE_PROJECT_DIR || process.cwd()).replace(/^\/([a-z])\//i, '$1:/');
|
|
38
|
+
var gateScript = resolve(projectDir, '.claude/helpers/gate.cjs');
|
|
39
|
+
try {
|
|
40
|
+
var output = execSync('node "' + gateScript + '" ' + command, {
|
|
41
|
+
env: env, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe']
|
|
42
|
+
});
|
|
43
|
+
if (output.trim()) process.stdout.write(output);
|
|
44
|
+
process.exit(0);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
// gate.cjs exit(2) = block, exit(1) = also block attempt — translate both to exit(2)
|
|
47
|
+
if (err.stderr) process.stderr.write(err.stderr);
|
|
48
|
+
if (err.stdout) process.stderr.write(err.stdout);
|
|
49
|
+
process.exit(err.status === 2 || err.status === 1 ? 2 : 0);
|
|
50
|
+
}
|
package/.claude/helpers/gate.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var fs = require('fs');
|
|
4
4
|
var path = require('path');
|
|
5
5
|
|
|
6
|
-
var PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
6
|
+
var PROJECT_DIR = (process.env.CLAUDE_PROJECT_DIR || process.cwd()).replace(/^\/([a-z])\//i, '$1:/');
|
|
7
7
|
var STATE_FILE = path.join(PROJECT_DIR, '.claude', 'workflow-state.json');
|
|
8
8
|
|
|
9
9
|
function readState() {
|
|
@@ -39,119 +39,23 @@ function loadGateConfig() {
|
|
|
39
39
|
var config = loadGateConfig();
|
|
40
40
|
var command = process.argv[2];
|
|
41
41
|
|
|
42
|
+
var EXEMPT = ['.claude/', '.claude\\', 'CLAUDE.md', 'MEMORY.md', 'workflow-state', 'node_modules'];
|
|
42
43
|
var DANGEROUS = ['rm -rf /', 'format c:', 'del /s /q c:\\', ':(){:|:&};:', 'mkfs.', '> /dev/sda'];
|
|
43
44
|
var DIRECTIVE_RE = /^(yes|no|yeah|yep|nope|sure|ok|okay|correct|right|exactly|perfect)\b/i;
|
|
44
45
|
var TASK_RE = /\b(fix|bug|error|implement|add|create|build|write|refactor|debug|test|feature|issue|security|optimi)\b/i;
|
|
45
46
|
|
|
46
|
-
// Deny a tool call cleanly via structured JSON (no "hook error" noise).
|
|
47
|
-
// Exit 0 + permissionDecision:"deny" is the Claude Code way to block a tool.
|
|
48
|
-
function blockTool(reason) {
|
|
49
|
-
console.log(JSON.stringify({
|
|
50
|
-
hookSpecificOutput: {
|
|
51
|
-
hookEventName: 'PreToolUse',
|
|
52
|
-
permissionDecision: 'deny',
|
|
53
|
-
permissionDecisionReason: reason
|
|
54
|
-
}
|
|
55
|
-
}));
|
|
56
|
-
process.exit(0);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Determine if a Grep/Glob target is a mechanical/administrative search
|
|
60
|
-
// that should bypass the memory-first gate. The idea: if memory/guidance
|
|
61
|
-
// wouldn't improve the search outcome, don't block it.
|
|
62
|
-
//
|
|
63
|
-
// Strategy: path is the strongest signal. When a path clearly points to
|
|
64
|
-
// tooling/deps/tests, allow it. When it points to source/docs/scripts,
|
|
65
|
-
// block it (require memory). Pattern-based rules only kick in when there's
|
|
66
|
-
// no path or when the path is neutral.
|
|
67
|
-
function isMechanicalSearch() {
|
|
68
|
-
var searchPath = (process.env.TOOL_INPUT_path || '').replace(/\\/g, '/').toLowerCase();
|
|
69
|
-
var pattern = (process.env.TOOL_INPUT_pattern || '').toLowerCase();
|
|
70
|
-
var filePath = (process.env.TOOL_INPUT_file_path || '').replace(/\\/g, '/').toLowerCase();
|
|
71
|
-
var anyPath = searchPath || filePath;
|
|
72
|
-
|
|
73
|
-
// --- PATH-BASED RULES (strongest signal, checked first) ---
|
|
74
|
-
|
|
75
|
-
if (anyPath) {
|
|
76
|
-
// Always mechanical: dependencies, tooling internals, CI, test dirs
|
|
77
|
-
var mechanicalPaths = [
|
|
78
|
-
'node_modules/', '.claude/', '.claude-flow/', '.swarm/', '.github/',
|
|
79
|
-
'tests/', 'test/', 'config/', 'examples/',
|
|
80
|
-
];
|
|
81
|
-
for (var i = 0; i < mechanicalPaths.length; i++) {
|
|
82
|
-
if (anyPath.indexOf(mechanicalPaths[i]) >= 0) return true;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Targeting a specific config/meta file by path extension
|
|
86
|
-
if (/\.(json|yaml|yml|toml|lock|env|cjs|mjs)$/i.test(anyPath)) return true;
|
|
87
|
-
|
|
88
|
-
// If path points to source, docs, or scripts — these are knowledge-rich.
|
|
89
|
-
// Do NOT fall through to pattern-based exemptions; the path is authoritative.
|
|
90
|
-
// (Still allow test-file glob patterns even within source dirs.)
|
|
91
|
-
var knowledgePaths = [
|
|
92
|
-
'src/', 'back-office/', 'front-office/', 'docs/', 'scripts/', 'lib/',
|
|
93
|
-
];
|
|
94
|
-
var inKnowledgePath = false;
|
|
95
|
-
for (var k = 0; k < knowledgePaths.length; k++) {
|
|
96
|
-
if (anyPath.indexOf(knowledgePaths[k]) >= 0) { inKnowledgePath = true; break; }
|
|
97
|
-
}
|
|
98
|
-
if (inKnowledgePath) {
|
|
99
|
-
// Exception: searching for test/spec files within source is structural
|
|
100
|
-
if (/\*\*?[/\\]?\*?\.(test|spec)\.(ts|js|tsx|jsx)\b/i.test(pattern)) return true;
|
|
101
|
-
// Everything else in a knowledge path requires memory
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// --- PATTERN-BASED RULES (no path, or path is neutral) ---
|
|
107
|
-
|
|
108
|
-
// Glob patterns looking for config/build/tooling files by extension
|
|
109
|
-
if (/\*\*?[/\\]?\*?\.(json|yaml|yml|toml|lock|env|config|cjs|mjs)\b/i.test(pattern)) return true;
|
|
110
|
-
|
|
111
|
-
// Glob patterns for specific config filenames (eslintrc, Dockerfile, etc.)
|
|
112
|
-
if (/\*\*?[/\\]?\*?\.?(eslint|prettier|babel|stylelint|editor|git|docker|nginx|jest|vitest|vite|webpack|rollup|esbuild|tsconfig|browserslist)/i.test(pattern)) return true;
|
|
113
|
-
|
|
114
|
-
// Glob patterns for lock files and test files (structural lookups)
|
|
115
|
-
if (/\*\*?[/\\]?\*?[\w-]*[-.]lock\b/i.test(pattern)) return true;
|
|
116
|
-
if (/\*\*?[/\\]?\*?\.(test|spec)\.(ts|js|tsx|jsx)\b/i.test(pattern)) return true;
|
|
117
|
-
|
|
118
|
-
// Config/tooling name searches (bare names without a path).
|
|
119
|
-
// Only exempt if ALL tokens in a pipe-separated pattern are config names.
|
|
120
|
-
// "webpack|vite" = exempt. "webpack|merchant" = NOT exempt.
|
|
121
|
-
var CONFIG_NAME = /^\.?(eslint|prettier|babel|stylelint|editor|gitignore|gitattributes|dockerignore|dockerfile|docker-compose|nginx|jest|vitest|vite|webpack|rollup|esbuild|tsconfig|changelog|license|makefile|procfile|browserslist|commitlint|husky|lint-staged)\b/i;
|
|
122
|
-
var tokens = pattern.split(/[|,\s]+/).filter(function(t) { return t.length > 0; });
|
|
123
|
-
if (tokens.length > 0 && tokens.every(function(t) { return CONFIG_NAME.test(t.trim()); })) return true;
|
|
124
|
-
|
|
125
|
-
// Known tooling/meta file names as substrings (but avoid false matches like "process.env")
|
|
126
|
-
var toolingNames = [
|
|
127
|
-
'claude.md', 'memory.md', 'workflow-state', '.mcp.json',
|
|
128
|
-
'package.json', 'package-lock', 'daemon.lock', 'moflo.yaml',
|
|
129
|
-
];
|
|
130
|
-
var target = pattern + ' ' + anyPath;
|
|
131
|
-
for (var j = 0; j < toolingNames.length; j++) {
|
|
132
|
-
if (target.indexOf(toolingNames[j]) >= 0) return true;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Env file lookups (but NOT "process.env" which is source code searching)
|
|
136
|
-
if (/^\.env\b/.test(pattern) || /\*\*?[/\\]?\.env/.test(pattern)) return true;
|
|
137
|
-
|
|
138
|
-
// Git/process/system-level pattern searches
|
|
139
|
-
if (/^(git\b|pid|daemon|lock|wmic|tasklist|powershell|ps\s)/i.test(pattern)) return true;
|
|
140
|
-
|
|
141
|
-
// CI/CD folder exploration
|
|
142
|
-
if (/\.github/i.test(pattern)) return true;
|
|
143
|
-
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
47
|
switch (command) {
|
|
148
48
|
case 'check-before-agent': {
|
|
149
49
|
var s = readState();
|
|
150
|
-
|
|
151
|
-
|
|
50
|
+
// Hard gate: memory must be searched
|
|
51
|
+
if (config.memory_first && s.memoryRequired && !s.memorySearched) {
|
|
52
|
+
process.stderr.write('BLOCKED: Search memory (mcp__moflo__memory_search) before spawning agents.\n');
|
|
53
|
+
process.exit(2);
|
|
152
54
|
}
|
|
153
|
-
|
|
154
|
-
|
|
55
|
+
// Soft gate: TaskCreate recommended but not blocking
|
|
56
|
+
// (TaskCreate PostToolUse doesn't fire in Claude Code, so we can't track it reliably)
|
|
57
|
+
if (config.task_create_first && !s.tasksCreated) {
|
|
58
|
+
process.stdout.write('REMINDER: Use TaskCreate before spawning agents. Task tool is blocked until then.\n');
|
|
155
59
|
}
|
|
156
60
|
break;
|
|
157
61
|
}
|
|
@@ -159,21 +63,19 @@ switch (command) {
|
|
|
159
63
|
if (!config.memory_first) break;
|
|
160
64
|
var s = readState();
|
|
161
65
|
if (s.memorySearched || !s.memoryRequired) break;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
66
|
+
var target = (process.env.TOOL_INPUT_pattern || '') + ' ' + (process.env.TOOL_INPUT_path || '');
|
|
67
|
+
if (EXEMPT.some(function(p) { return target.indexOf(p) >= 0; })) break;
|
|
68
|
+
process.stderr.write('BLOCKED: Search memory before exploring files. Use mcp__moflo__memory_search.\n');
|
|
69
|
+
process.exit(2);
|
|
166
70
|
}
|
|
167
71
|
case 'check-before-read': {
|
|
168
72
|
if (!config.memory_first) break;
|
|
169
73
|
var s = readState();
|
|
170
74
|
if (s.memorySearched || !s.memoryRequired) break;
|
|
171
|
-
var fp =
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
writeState(s);
|
|
176
|
-
blockTool('Search memory before reading guidance files. Use mcp__moflo__memory_search with namespace "guidance".');
|
|
75
|
+
var fp = process.env.TOOL_INPUT_file_path || '';
|
|
76
|
+
if (fp.indexOf('.claude/guidance/') < 0 && fp.indexOf('.claude\\guidance\\') < 0) break;
|
|
77
|
+
process.stderr.write('BLOCKED: Search memory before reading guidance files. Use mcp__moflo__memory_search.\n');
|
|
78
|
+
process.exit(2);
|
|
177
79
|
}
|
|
178
80
|
case 'record-task-created': {
|
|
179
81
|
var s = readState();
|
|
@@ -219,7 +121,7 @@ switch (command) {
|
|
|
219
121
|
var ic = s.interactionCount;
|
|
220
122
|
if (ic > 30) console.log('Context: CRITICAL. Commit, store learnings, suggest new session.');
|
|
221
123
|
else if (ic > 20) console.log('Context: DEPLETED. Checkpoint progress. Recommend /compact or fresh session.');
|
|
222
|
-
else if (ic > 10) console.log('Context: MODERATE. Re-state goal before architectural decisions.');
|
|
124
|
+
else if (ic > 10) console.log('Context: MODERATE. Re-state goal before architectural decisions. Use agents for >300 LOC.');
|
|
223
125
|
}
|
|
224
126
|
break;
|
|
225
127
|
}
|