moflo 4.8.69 → 4.8.70
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/guidance/shipped/moflo-spell-sandboxing.md +65 -0
- package/package.json +2 -2
- package/src/modules/cli/dist/src/epic/spells/auto-merge.yaml +4 -0
- package/src/modules/cli/dist/src/epic/spells/single-branch.yaml +7 -0
- package/src/modules/cli/dist/src/version.js +1 -1
- package/src/modules/cli/package.json +1 -1
|
@@ -233,6 +233,71 @@ Semantics (from `resolveEffectiveSandbox()` in `src/modules/spells/src/core/plat
|
|
|
233
233
|
|
|
234
234
|
Existing projects that predate this block get it auto-appended on session start — never require `moflo init` to re-run after a version bump.
|
|
235
235
|
|
|
236
|
+
## Authoring Checklist — Always Double-Check Step Permissions
|
|
237
|
+
|
|
238
|
+
Before shipping any new or edited spell step, walk through every item. Silently-missing permissions don't fail with `CAPABILITY_DENIED` — they fail confusingly several steps later.
|
|
239
|
+
|
|
240
|
+
1. **What does the command actually do?** List every external effect — file reads/writes, git/gh calls, outbound HTTP, Claude subagents, credential use.
|
|
241
|
+
2. **Which capabilities map to those effects?** `fs:read`, `fs:write`, `shell`, `net`, `credentials`, `agent`, `browser`, `memory`.
|
|
242
|
+
3. **What is the minimum `permissionLevel`?**
|
|
243
|
+
- Pure analysis (read only) → `readonly`
|
|
244
|
+
- Edits project files but no shell/network → `standard`
|
|
245
|
+
- Runs shell commands, **or needs network inside a bwrap-sandboxed step** → `elevated`
|
|
246
|
+
- Spawns Claude subagents with unrestricted tools → `autonomous`
|
|
247
|
+
4. **Does this step need network?** If so, either give it `permissionLevel: elevated` or declare the `net` capability explicitly. See the Troubleshooting section — bwrap strips network from any bash step that has neither, and the failure surfaces as a DNS error, not a permission error.
|
|
248
|
+
5. **Does the command chain multiple statements (`;`, `&&`, `||`)?** Lead the command with `set -e`. A trailing tolerated-failure cleanup like `git stash pop ... || true` will otherwise return 0 for the whole step even when the real work (checkout, pull, push) failed.
|
|
249
|
+
6. **Does this step produce state that later steps rely on?** If this step silently no-ops, will the downstream symptom be understandable? If not, tighten the failure mode (`set -e`, explicit error, `failOnError: true`).
|
|
250
|
+
|
|
251
|
+
When reviewing a spell PR, scan every bash step for a missing `permissionLevel` and ask: *does this step touch the network, or does it depend on network state from earlier?* If yes, `elevated` (or an explicit `net` grant) is required.
|
|
252
|
+
|
|
253
|
+
## Troubleshooting
|
|
254
|
+
|
|
255
|
+
### Symptom: bash step fails with DNS / SSH resolution errors inside a spell
|
|
256
|
+
|
|
257
|
+
Typical error messages from inside a bash step:
|
|
258
|
+
|
|
259
|
+
- `ssh: Could not resolve hostname github.com: Temporary failure in name resolution`
|
|
260
|
+
- `fatal: Could not read from remote repository.`
|
|
261
|
+
- `curl: (6) Could not resolve host ...`
|
|
262
|
+
- `getaddrinfo ENOTFOUND ...`
|
|
263
|
+
- Any other DNS/connection failure, even though the **same command works in your normal shell**.
|
|
264
|
+
|
|
265
|
+
**Tell-tale clue:** the error mentions `Temporary failure in name resolution` (a glibc-specific wording). That means the step is running inside a Linux sandbox (`bwrap` on Linux / WSL), **not** your outer shell — Git Bash or PowerShell won't produce that exact message.
|
|
266
|
+
|
|
267
|
+
**Root cause:** `src/modules/spells/src/core/bwrap-sandbox.ts` isolates the network by default:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
if (!hasNet && !needsToolHomeAccess(options.permissionLevel)) {
|
|
271
|
+
args.push('--unshare-net'); // ← no network, no DNS
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
A bash step gets network access only when **one** of these is true:
|
|
276
|
+
|
|
277
|
+
1. The step declares a `net` capability, **or**
|
|
278
|
+
2. The step's `permissionLevel` is `elevated` or `autonomous`.
|
|
279
|
+
|
|
280
|
+
If neither applies, bwrap runs the command in a namespace with `--unshare-net`, and DNS silently fails. There is no log line announcing the network was taken away — you just see the command's own DNS error.
|
|
281
|
+
|
|
282
|
+
**Fix:** for any bash step that does `git pull`/`git push`/`git fetch`, `gh` API calls, `curl`, `npm install`, or any other outbound network:
|
|
283
|
+
|
|
284
|
+
```yaml
|
|
285
|
+
- id: create-branch
|
|
286
|
+
type: bash
|
|
287
|
+
permissionLevel: elevated # ← grants network in bwrap
|
|
288
|
+
config:
|
|
289
|
+
command: "git pull origin main && ..."
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Or declare the `net` capability explicitly if the step doesn't need the full `elevated` profile (note: `bash-command.ts` must include `net` in its declared capabilities for the engine to accept the grant — otherwise you'll see `Capability violation: step type "bash" does not declare capability "net"`).
|
|
293
|
+
|
|
294
|
+
**Quick diagnosis checklist** when a spell's bash step can't reach the network:
|
|
295
|
+
|
|
296
|
+
1. Does the same command work in your outer shell? If yes, it's sandbox-related, not config.
|
|
297
|
+
2. Is the error wording glibc-style (`Temporary failure in name resolution`)? → bwrap is involved.
|
|
298
|
+
3. Open the spell YAML — does the failing step have `permissionLevel: elevated`? If not, add it and retry.
|
|
299
|
+
4. If you use `set -e` in a multi-command bash step, **do it**. Without it, a trailing `... || true` (common for stash-pop cleanups) will mask the real network failure and you'll see a confusing error several steps later (e.g. "pathspec did not match" when a branch that was never pulled/created is later checked out).
|
|
300
|
+
|
|
236
301
|
## See Also
|
|
237
302
|
|
|
238
303
|
- `.claude/guidance/shipped/moflo-spell-engine.md` — Spell engine usage and YAML format
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moflo",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.70",
|
|
4
4
|
"description": "MoFlo — AI agent orchestration for Claude Code. Forked from ruflo/claude-flow with patches applied to source, plus feature-level orchestration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"@types/js-yaml": "^4.0.9",
|
|
113
113
|
"@types/node": "^20.19.37",
|
|
114
114
|
"eslint": "^8.0.0",
|
|
115
|
-
"moflo": "^4.8.
|
|
115
|
+
"moflo": "^4.8.69",
|
|
116
116
|
"tsx": "^4.21.0",
|
|
117
117
|
"typescript": "^5.9.3",
|
|
118
118
|
"vitest": "^4.0.0"
|
|
@@ -58,6 +58,8 @@ steps:
|
|
|
58
58
|
# on dirty tree, missing auth, or unreachable remote.
|
|
59
59
|
- id: checkout-base
|
|
60
60
|
type: bash
|
|
61
|
+
# elevated — bwrap network access for git pull (see single-branch create-branch).
|
|
62
|
+
permissionLevel: elevated
|
|
61
63
|
preflight:
|
|
62
64
|
- name: "no unmerged files"
|
|
63
65
|
command: "git diff --name-only --diff-filter=U"
|
|
@@ -123,6 +125,8 @@ steps:
|
|
|
123
125
|
# 5: Pull merged changes
|
|
124
126
|
- id: pull-merged
|
|
125
127
|
type: bash
|
|
128
|
+
# elevated — bwrap network access for git pull (see checkout-base).
|
|
129
|
+
permissionLevel: elevated
|
|
126
130
|
config:
|
|
127
131
|
# set -e: fail fast if checkout/pull fails (see checkout-base).
|
|
128
132
|
command: "set -e; git stash --include-untracked -q 2>/dev/null || true; git checkout {args.base_branch}; git pull origin {args.base_branch}; git stash pop -q 2>/dev/null || true"
|
|
@@ -55,6 +55,11 @@ steps:
|
|
|
55
55
|
# Preflights run BEFORE any step — fail fast on dirty tree or auth issues
|
|
56
56
|
- id: create-branch
|
|
57
57
|
type: bash
|
|
58
|
+
# elevated — needed for bwrap to share the host network so `git pull`
|
|
59
|
+
# can reach github. Without it, bwrap adds --unshare-net and the pull
|
|
60
|
+
# fails with a DNS / SSH resolution error even though the outer shell
|
|
61
|
+
# has working network.
|
|
62
|
+
permissionLevel: elevated
|
|
58
63
|
preflight:
|
|
59
64
|
- name: "no unmerged files"
|
|
60
65
|
command: "git diff --name-only --diff-filter=U"
|
|
@@ -134,6 +139,8 @@ steps:
|
|
|
134
139
|
# Preflight: verify origin remote exists so push won't fail mid-way
|
|
135
140
|
- id: push-branch
|
|
136
141
|
type: bash
|
|
142
|
+
# elevated — bwrap network access for git push (see create-branch).
|
|
143
|
+
permissionLevel: elevated
|
|
137
144
|
preflight:
|
|
138
145
|
- name: "origin remote configured"
|
|
139
146
|
command: "git remote get-url origin"
|