nomarmy 0.1.0-alpha.0

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.
Files changed (74) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +25 -0
  3. package/README.md +484 -0
  4. package/bin/nomarmy.mjs +2248 -0
  5. package/config/agents.yml.example +63 -0
  6. package/config/common.env +31 -0
  7. package/config/profiles/bedrock-cheap.env +26 -0
  8. package/config/profiles/bedrock.env +28 -0
  9. package/config/profiles/cpu-linux.env +8 -0
  10. package/config/profiles/dgx-spark.env +12 -0
  11. package/config/profiles/macbook-pro.env +9 -0
  12. package/config/profiles/nvidia-linux.env +9 -0
  13. package/docker/Dockerfile +15 -0
  14. package/docker/Dockerfile.go +29 -0
  15. package/docker/Dockerfile.rust +19 -0
  16. package/e2e.sh +153 -0
  17. package/install.sh +125 -0
  18. package/lib/agents.mjs +285 -0
  19. package/lib/army.mjs +400 -0
  20. package/lib/budget.mjs +368 -0
  21. package/lib/claude-transcript.mjs +150 -0
  22. package/lib/config.mjs +193 -0
  23. package/lib/connect.mjs +409 -0
  24. package/lib/coordinator-instructions.mjs +23 -0
  25. package/lib/decompose.mjs +389 -0
  26. package/lib/dispatch-config.mjs +164 -0
  27. package/lib/dispatch-schema.mjs +280 -0
  28. package/lib/doctor.mjs +443 -0
  29. package/lib/evidence.mjs +679 -0
  30. package/lib/gguf.mjs +589 -0
  31. package/lib/hardware.mjs +476 -0
  32. package/lib/health.mjs +278 -0
  33. package/lib/model-catalog.mjs +71 -0
  34. package/lib/notifier-app.mjs +95 -0
  35. package/lib/notify.mjs +66 -0
  36. package/lib/openclaw-config.mjs +65 -0
  37. package/lib/openclaw-errors.mjs +40 -0
  38. package/lib/propose.mjs +110 -0
  39. package/lib/prune.mjs +77 -0
  40. package/lib/repo-query.mjs +267 -0
  41. package/lib/runs.mjs +150 -0
  42. package/lib/sabotage.mjs +128 -0
  43. package/lib/sandbox-images.mjs +434 -0
  44. package/lib/scan.mjs +1538 -0
  45. package/lib/schema.mjs +288 -0
  46. package/lib/scout.mjs +544 -0
  47. package/lib/sizing.mjs +1322 -0
  48. package/lib/slots.mjs +112 -0
  49. package/lib/statusline.mjs +126 -0
  50. package/lib/subscription-config.mjs +68 -0
  51. package/lib/subscription-setup.mjs +217 -0
  52. package/lib/transcript.mjs +195 -0
  53. package/lib/verify.mjs +700 -0
  54. package/mcp/server.mjs +4206 -0
  55. package/notifier/icon.swift +34 -0
  56. package/notifier/main.swift +52 -0
  57. package/notifier/nomarmy-icon.png +0 -0
  58. package/package.json +67 -0
  59. package/playbooks/feature.md +43 -0
  60. package/policies/coder.md +49 -0
  61. package/policies/orchestrator.md +35 -0
  62. package/policies/reviewer.md +35 -0
  63. package/policies/scout.md +65 -0
  64. package/scripts/configure-openclaw.sh +96 -0
  65. package/scripts/configure-orchestrator.sh +84 -0
  66. package/scripts/install-llama-cpp.sh +16 -0
  67. package/scripts/lib.sh +198 -0
  68. package/scripts/select-model.mjs +96 -0
  69. package/scripts/select-model.sh +4 -0
  70. package/scripts/setup-sandbox.sh +38 -0
  71. package/scripts/start-inference.sh +46 -0
  72. package/scripts/stop-inference.sh +5 -0
  73. package/scripts/uninstall.sh +6 -0
  74. package/scripts/verify-install.sh +68 -0
@@ -0,0 +1,63 @@
1
+ # ~/.config/nomarmy/agents.yml (or $NOMARMY_CONFIG_DIR/agents.yml)
2
+ #
3
+ # Every model a nomArmy job can run on, by name. You rarely edit this by
4
+ # hand: `nomarmy agents add` walks through each kind (key registration,
5
+ # vendor logins, a real test call) and writes it for you.
6
+ #
7
+ # An api or subscription agent is an ACCOUNT, not a model. The model is
8
+ # picked per role (`nomarmy army assign sr-dev codex gpt-6-astra`, or `auto`
9
+ # to let the General choose per job), or by the General on a job; `model`
10
+ # here is only an optional default. Nothing ever picks between agents at
11
+ # random.
12
+ #
13
+ # `local` (the coder slot) is built in; you only list it to change it.
14
+ #
15
+ # Security: this file never holds a credential. An api agent names the
16
+ # environment variable its key was registered from (the key itself lives in
17
+ # OpenClaw's own store); a subscription agent's login lives in the vendor
18
+ # CLI's own session or your OS keychain. nomArmy refuses to load this file
19
+ # if another OS account owns it or can write to it.
20
+
21
+ agents:
22
+ # The local model's gpt slot (NOMARMY_WORKER_MODEL_FALLBACK).
23
+ local-gpt:
24
+ kind: local
25
+ slot: gpt
26
+
27
+ # A metered API key. provider is one of: xai, openai, anthropic,
28
+ # deepinfra, bedrock / azure-openai / openai-compatible (need base_url),
29
+ # or openclaw for any other OpenClaw provider by id:
30
+ # provider: openclaw
31
+ # openclaw_provider: deepseek
32
+ # plugin: clawhub:@openclaw/deepseek-provider # if it isn't built in
33
+ grok:
34
+ kind: api
35
+ provider: xai
36
+ model: grok-4.7 # optional default
37
+ auth_env: NOMARMY_XAI_API_KEY # the variable's NAME, never the key
38
+ thinking: high # true = follow the job, false = off, or a fixed level
39
+ # max_concurrent: 2
40
+ # context_window: 500000 # only for a model newer than OpenClaw's catalog
41
+
42
+ # ONE person's own subscription, never pooled: every job on it must name
43
+ # this owner in on_behalf_of. Set up with `nomarmy agents add subscription
44
+ # claude|codex|meta`.
45
+ claude:
46
+ kind: subscription
47
+ provider: claude-cli # Claude Pro/Max/Team seat
48
+ owner: "you@example.com"
49
+ codex:
50
+ kind: subscription
51
+ provider: openai # ChatGPT plan, via the Codex login
52
+ owner: "you@example.com"
53
+ muse:
54
+ kind: subscription
55
+ provider: meta # Muse Code subscription
56
+ owner: "you@example.com"
57
+ # max_concurrent: 1 # the default for a subscription
58
+
59
+ # One OpenClaw provider id holds one credential. OpenAI, Meta and xAI use the
60
+ # same id for the subscription and the API key, so an api agent and a
61
+ # subscription agent on the same provider are refused. Here, `grok` (xai)
62
+ # means you can't also add an xAI subscription agent. Claude never collides:
63
+ # its subscription is claude-cli, its API key is anthropic.
@@ -0,0 +1,31 @@
1
+ NOMARMY_MODEL_REPO=ggml-org/gpt-oss-20b-GGUF
2
+ NOMARMY_MODEL_QUANT=MXFP4
3
+ NOMARMY_MODEL_ALIAS=gpt-oss-20b
4
+ # Whether the configured model has a thinking/reasoning mode at all --
5
+ # Coder-Next does not. `nomarmy connect` reads this (and NOMARMY_WORKER_MODEL
6
+ # below) to keep the MCP registration's worker-routing env vars in sync with
7
+ # whatever model is actually configured here, instead of the two silently
8
+ # drifting apart (the exact bug this fixes: NOMARMY_WORKER_MODEL sat unused
9
+ # in this file for every model choice until now).
10
+ NOMARMY_MODEL_THINKING=true
11
+ NOMARMY_LLAMA_HOST=127.0.0.1
12
+ NOMARMY_LLAMA_PORT=8080
13
+ NOMARMY_LLAMA_CONTEXT=65536
14
+ NOMARMY_LLAMA_PARALLEL=1
15
+ NOMARMY_MAX_WORKERS=1
16
+ NOMARMY_AGENT_IMAGE=openclaw-nomarmy-coder:bookworm
17
+ NOMARMY_INSTALL_ROOT=$HOME/.local/share/nomarmy-local-agents
18
+
19
+ # Execution layer: 'local' runs llama-server on this machine, 'bedrock' calls a
20
+ # hosted OpenAI-compatible endpoint. Profiles override this.
21
+ NOMARMY_EXECUTION=local
22
+
23
+ # Worker model routing. The MCP server composes "<provider>/<model>" for
24
+ # OpenClaw, so these are the only place model identity is declared.
25
+ NOMARMY_WORKER_PROVIDER=llama-cpp
26
+ NOMARMY_WORKER_MODEL=gpt-oss-20b
27
+ NOMARMY_WORKER_MODEL_FALLBACK=gpt-oss-20b
28
+
29
+ # 'frontier' means the coordinator outranks the workers it reviews, which is
30
+ # what policies/reviewer.md assumes. 'degraded' is the explicit opt-out.
31
+ NOMARMY_ORCHESTRATOR_TRUST=frontier
@@ -0,0 +1,26 @@
1
+ # DEGRADED-ACCEPTANCE PROFILE: read policies/reviewer.md before using.
2
+ #
3
+ # Orchestrator and workers are the same capability class, so the coordinator is
4
+ # grading output from a peer rather than from below. Acceptance stops being an
5
+ # independent check. Use only where a wrong accept is cheap and reversible, and
6
+ # never for security decisions, architecture, or anything heading for a release.
7
+ #
8
+ # Note this path cannot be Claude Code: CLAUDE_CODE_USE_BEDROCK only routes
9
+ # Anthropic models. The coordinator here is OpenClaw driving the same MCP server.
10
+ NOMARMY_PROFILE=bedrock-cheap
11
+ NOMARMY_EXECUTION=bedrock
12
+
13
+ NOMARMY_BEDROCK_REGION=eu-west-2
14
+
15
+ # --- Orchestrator -----------------------------------------------------------
16
+ NOMARMY_ORCHESTRATOR_RUNTIME=openclaw
17
+ NOMARMY_ORCHESTRATOR_MODEL=qwen.qwen3-coder-next
18
+ NOMARMY_ORCHESTRATOR_TRUST=degraded
19
+
20
+ # --- Workers ----------------------------------------------------------------
21
+ NOMARMY_WORKER_PROVIDER=bedrock
22
+ NOMARMY_WORKER_AUTH_CHOICE=openai-compatible-existing-server
23
+ NOMARMY_WORKER_MODEL=qwen.qwen3-coder-next
24
+ NOMARMY_WORKER_MODEL_FALLBACK=nvidia.nemotron-nano-3-30b
25
+
26
+ NOMARMY_MAX_WORKERS=4
@@ -0,0 +1,28 @@
1
+ # Bedrock-hosted orchestrator and workers. No local inference, so this profile
2
+ # carries no GPU or OS requirement and runs anywhere AWS credentials resolve.
3
+ NOMARMY_PROFILE=bedrock
4
+ NOMARMY_EXECUTION=bedrock
5
+
6
+ # Region, models and worker count honour an environment override; the value here
7
+ # is the default. Base URL is derived from the region unless you set it.
8
+ NOMARMY_BEDROCK_REGION=eu-west-2
9
+ # NOMARMY_BEDROCK_BASE_URL=https://bedrock-runtime.eu-west-2.amazonaws.com/openai/v1
10
+
11
+ # --- Orchestrator -----------------------------------------------------------
12
+ # Claude Opus 5 served from Bedrock. The coordinator still outranks the workers
13
+ # it reviews, so policies/orchestrator.md and policies/reviewer.md hold as written.
14
+ NOMARMY_ORCHESTRATOR_RUNTIME=claude-code
15
+ NOMARMY_ORCHESTRATOR_MODEL=eu.anthropic.claude-opus-5
16
+ NOMARMY_ORCHESTRATOR_TRUST=frontier
17
+
18
+ # --- Workers ----------------------------------------------------------------
19
+ # Bedrock model IDs. Confirm against `aws bedrock list-foundation-models`;
20
+ # scripts/verify-install.sh checks these are invokable in your account.
21
+ NOMARMY_WORKER_PROVIDER=bedrock
22
+ NOMARMY_WORKER_AUTH_CHOICE=openai-compatible-existing-server
23
+ NOMARMY_WORKER_MODEL=qwen.qwen3-coder-next
24
+ NOMARMY_WORKER_MODEL_FALLBACK=nvidia.nemotron-3-super-120b
25
+
26
+ # Hosted inference removes the VRAM ceiling; the practical limit is now your
27
+ # Bedrock TPM quota and your budget. Still measure before raising further.
28
+ NOMARMY_MAX_WORKERS=4
@@ -0,0 +1,8 @@
1
+ # Generic Linux CPU-only worker. Use where CUDA is unavailable.
2
+ # Retained as the constrained profile: 16K context, one worker.
3
+ NOMARMY_PROFILE=cpu-linux
4
+ NOMARMY_LLAMA_GPU_LAYERS=0
5
+ NOMARMY_LLAMA_THREADS=8
6
+ NOMARMY_LLAMA_CONTEXT=16384
7
+ NOMARMY_LLAMA_PARALLEL=1
8
+ NOMARMY_MAX_WORKERS=1
@@ -0,0 +1,12 @@
1
+ # NVIDIA DGX Spark / GB10 Grace Blackwell, Linux ARM64, CUDA.
2
+ # Start conservative; raise parallelism only after E2E passes and memory is measured.
3
+ #
4
+ # NOTE: -c is divided across -np, so 65536 with 2 slots gives each nom 32K,
5
+ # below the v1.3 64K-per-nom target. Run `nomarmy sizing` on the machine and
6
+ # apply what it recommends rather than trusting these defaults.
7
+ NOMARMY_PROFILE=dgx-spark
8
+ NOMARMY_LLAMA_GPU_LAYERS=999
9
+ NOMARMY_LLAMA_THREADS=16
10
+ NOMARMY_LLAMA_CONTEXT=65536
11
+ NOMARMY_LLAMA_PARALLEL=2
12
+ NOMARMY_MAX_WORKERS=2
@@ -0,0 +1,9 @@
1
+ # Apple Silicon / Metal. Conservative defaults for 64 GB unified memory.
2
+ NOMARMY_PROFILE=macbook-pro
3
+ NOMARMY_LLAMA_GPU_LAYERS=999
4
+ NOMARMY_LLAMA_THREADS=12
5
+ # v1.3 raises this from 32K: the autonomous explore/implement/test/repair loop
6
+ # needs more room than a one-shot edit. 64 GB unified memory carries 64K.
7
+ NOMARMY_LLAMA_CONTEXT=65536
8
+ NOMARMY_LLAMA_PARALLEL=1
9
+ NOMARMY_MAX_WORKERS=1
@@ -0,0 +1,9 @@
1
+ # Generic NVIDIA Linux/CUDA worker. Tune for available VRAM/system memory.
2
+ NOMARMY_PROFILE=nvidia-linux
3
+ NOMARMY_LLAMA_GPU_LAYERS=999
4
+ NOMARMY_LLAMA_THREADS=12
5
+ # Conservative for unknown VRAM. Raise to 65536 for the v1.3 autonomous loop
6
+ # where the card allows: NOMARMY_LLAMA_CONTEXT=65536 ./install.sh --profile nvidia-linux
7
+ NOMARMY_LLAMA_CONTEXT=32768
8
+ NOMARMY_LLAMA_PARALLEL=1
9
+ NOMARMY_MAX_WORKERS=1
@@ -0,0 +1,15 @@
1
+ FROM node:24-bookworm-slim
2
+ ENV DEBIAN_FRONTEND=noninteractive
3
+ RUN apt-get update && apt-get install -y --no-install-recommends \
4
+ bash ca-certificates curl git jq python3 python3-pip python3-venv ripgrep \
5
+ && rm -rf /var/lib/apt/lists/*
6
+ # node:24-bookworm-slim already ships a non-root "node" user at uid/gid 1000,
7
+ # the same uid this Dockerfile used to try to create a "sandbox" user at.
8
+ # useradd silently failed on every build (masked by `|| true`), so `USER
9
+ # sandbox` below referred to a user that was never actually created --
10
+ # `docker run` for any command failed with "unable to find user sandbox: no
11
+ # matching entries in passwd file." Use the user the base image already
12
+ # provides instead of colliding with it.
13
+ USER node
14
+ WORKDIR /workspace
15
+ CMD ["sleep", "infinity"]
@@ -0,0 +1,29 @@
1
+ FROM node:24-bookworm-slim
2
+ ENV DEBIAN_FRONTEND=noninteractive
3
+ # Same base as docker/Dockerfile plus a Go toolchain -- the worker's own
4
+ # tool-calling harness needs Node regardless of the target repo's language.
5
+ RUN apt-get update && apt-get install -y --no-install-recommends \
6
+ bash ca-certificates curl git jq python3 python3-pip python3-venv ripgrep \
7
+ && rm -rf /var/lib/apt/lists/*
8
+ # Debian bookworm's packaged golang-go lags stable Go by multiple years
9
+ # (verified live: apt installed 1.19 here while go.dev's stable was 1.27) --
10
+ # same reasoning as using rustup instead of apt for Rust in Dockerfile.rust.
11
+ # Pinned, not "latest", for a reproducible build; bump GO_VERSION by hand
12
+ # periodically against https://go.dev/dl/.
13
+ ENV GO_VERSION=1.27.1
14
+ RUN ARCH="$(dpkg --print-architecture)" \
15
+ && case "$ARCH" in \
16
+ amd64) GOARCH=amd64 ;; \
17
+ arm64) GOARCH=arm64 ;; \
18
+ *) echo "unsupported architecture for Go install: $ARCH" >&2; exit 1 ;; \
19
+ esac \
20
+ && curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${GOARCH}.tar.gz" -o /tmp/go.tgz \
21
+ && tar -C /usr/local -xzf /tmp/go.tgz \
22
+ && rm /tmp/go.tgz
23
+ ENV PATH="/usr/local/go/bin:${PATH}"
24
+ ENV GOPATH=/home/node/go
25
+ ENV PATH="${GOPATH}/bin:${PATH}"
26
+ USER node
27
+ RUN mkdir -p "${GOPATH}"
28
+ WORKDIR /workspace
29
+ CMD ["sleep", "infinity"]
@@ -0,0 +1,19 @@
1
+ FROM node:24-bookworm-slim
2
+ ENV DEBIAN_FRONTEND=noninteractive
3
+ # Same base as docker/Dockerfile plus a Rust toolchain -- the worker's own
4
+ # tool-calling harness needs Node regardless of the target repo's language.
5
+ # Debian bookworm's packaged rustc/cargo lags stable Rust noticeably, and
6
+ # real Cargo.toml files routinely need a recent edition/toolchain, so this
7
+ # uses rustup (network access is fine here -- this is the BUILD step,
8
+ # offline, on the host; the running container it produces still gets
9
+ # --network none like every other job sandbox).
10
+ RUN apt-get update && apt-get install -y --no-install-recommends \
11
+ bash ca-certificates curl git jq python3 python3-pip python3-venv ripgrep build-essential \
12
+ && rm -rf /var/lib/apt/lists/*
13
+ USER node
14
+ ENV RUSTUP_HOME=/home/node/.rustup
15
+ ENV CARGO_HOME=/home/node/.cargo
16
+ ENV PATH="${CARGO_HOME}/bin:${PATH}"
17
+ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
18
+ WORKDIR /workspace
19
+ CMD ["sleep", "infinity"]
package/e2e.sh ADDED
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ # shellcheck disable=SC1091
6
+ source "$ROOT/scripts/lib.sh"
7
+
8
+ PROFILE=""
9
+
10
+ while [[ $# -gt 0 ]]; do
11
+ case "$1" in
12
+ --profile)
13
+ PROFILE="$2"
14
+ shift 2
15
+ ;;
16
+ *)
17
+ echo "Unknown arg $1"
18
+ exit 2
19
+ ;;
20
+ esac
21
+ done
22
+
23
+ load_profile "$PROFILE"
24
+
25
+ echo "=== nomArmy E2E: $NOMARMY_PROFILE ==="
26
+
27
+ "$ROOT/scripts/start-inference.sh" "$NOMARMY_PROFILE"
28
+
29
+ if nomarmy_is_cloud; then
30
+ echo "INFO hosted inference at $NOMARMY_BEDROCK_BASE_URL"
31
+
32
+ # Reachability and model entitlement are an AWS concern on this path, so the
33
+ # provider listing stands in for the local health and discovery checks.
34
+ openclaw models list --provider "$NOMARMY_WORKER_PROVIDER" \
35
+ | grep -q "$NOMARMY_WORKER_MODEL"
36
+
37
+ echo "PASS model discovery"
38
+ else
39
+ curl -fsS \
40
+ "http://$NOMARMY_LLAMA_HOST:$NOMARMY_LLAMA_PORT/health" \
41
+ >/dev/null
42
+
43
+ echo "PASS inference health"
44
+
45
+ MODELS="$(
46
+ curl -fsS \
47
+ "http://$NOMARMY_LLAMA_HOST:$NOMARMY_LLAMA_PORT/v1/models"
48
+ )"
49
+
50
+ echo "$MODELS" | grep -q "$NOMARMY_MODEL_ALIAS"
51
+
52
+ echo "PASS model discovery"
53
+ fi
54
+
55
+ # Under $HOME, not the system tmpdir: Podman Machine on macOS only allows
56
+ # bind-mounting paths under the host home directory, and the cleanup step
57
+ # below bind-mounts this directory into a container.
58
+ TMP="$(mktemp -d "$HOME/.nomarmy-e2e.XXXXXX")"
59
+
60
+ cleanup() {
61
+ local exit_code=$?
62
+
63
+ if [[ -n "${TMP:-}" && -d "$TMP" ]]; then
64
+
65
+ # OpenClaw's Podman sandbox may create files that the host user
66
+ # cannot delete directly. Use a disposable container to clean
67
+ # the temporary workspace first.
68
+ if command -v podman >/dev/null 2>&1 && podman info >/dev/null 2>&1; then
69
+ podman run --rm \
70
+ -v "$TMP:/cleanup" \
71
+ alpine:3.20 \
72
+ sh -c '
73
+ find /cleanup -mindepth 1 -maxdepth 1 -exec rm -rf -- {} + \
74
+ 2>/dev/null || true
75
+ ' \
76
+ >/dev/null 2>&1 || true
77
+ fi
78
+
79
+ rm -rf "$TMP" 2>/dev/null || true
80
+
81
+ if [[ -d "$TMP" ]]; then
82
+ echo "WARN: E2E temporary directory could not be completely removed:"
83
+ echo " $TMP"
84
+ fi
85
+ fi
86
+
87
+ exit "$exit_code"
88
+ }
89
+
90
+ trap cleanup EXIT INT TERM
91
+
92
+ cd "$TMP"
93
+
94
+ git init -q
95
+ git config user.email e2e@nomarmy.local
96
+ git config user.name "nomArmy E2E"
97
+
98
+ cat > calc.js <<'JS'
99
+ export function add(a,b){ return a-b; }
100
+ JS
101
+
102
+ cat > test.mjs <<'JS'
103
+ import { add } from './calc.js';
104
+
105
+ if (add(2,3)!==5) {
106
+ console.error('FAIL');
107
+ process.exit(1);
108
+ }
109
+
110
+ console.log('PASS');
111
+ JS
112
+
113
+ cat > package.json <<'JSON'
114
+ {
115
+ "type": "module",
116
+ "scripts": {
117
+ "test": "node test.mjs"
118
+ }
119
+ }
120
+ JSON
121
+
122
+ git add .
123
+ git commit -qm baseline
124
+
125
+ PROMPT='Fix the bug so npm test passes. Work only in the workspace. Run npm test. Do not run git. Final response MUST begin with exactly four lines: STATUS: done | partial | blocked; CHANGES: <brief>; VERIFICATION: pass | partial | failed - <brief>; NOT DONE: <list or none>.'
126
+
127
+ OUT="$TMP/openclaw.json"
128
+
129
+ openclaw agent exec "$PROMPT" \
130
+ --model "$NOMARMY_WORKER_PROVIDER/$NOMARMY_WORKER_MODEL" \
131
+ --cwd "$TMP" \
132
+ --code-mode direct \
133
+ --local-model-lean \
134
+ --thinking off \
135
+ --timeout 600 \
136
+ --json \
137
+ > "$OUT"
138
+
139
+ # Independent verification. We do not trust the worker's claim
140
+ # that its implementation is correct.
141
+ npm test
142
+
143
+ grep -Eq 'STATUS: (done|partial|blocked)' "$OUT"
144
+ echo "PASS worker report contract"
145
+
146
+ # The worker must have actually modified the implementation.
147
+ if git diff --exit-code -- calc.js >/dev/null; then
148
+ echo "ERROR: worker made no code change"
149
+ exit 1
150
+ fi
151
+
152
+ echo "PASS autonomous edit + verification"
153
+ echo "=== E2E PASS ==="
package/install.sh ADDED
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
+ # shellcheck disable=SC1091
5
+ source "$ROOT/scripts/lib.sh"
6
+ PROFILE=""
7
+ WITH_CLAUDE=1
8
+ while [[ $# -gt 0 ]]; do case "$1" in --profile) PROFILE="$2"; shift 2;; --no-claude) WITH_CLAUDE=0; shift;; *) echo "Unknown arg: $1"; exit 2;; esac; done
9
+ load_profile "$PROFILE"
10
+ echo "==> nomArmy install ($NOMARMY_PROFILE)"
11
+ OS_NAME="$(uname -s)"
12
+ case "$OS_NAME" in
13
+ Darwin)
14
+ need brew || { echo 'ERROR: Homebrew is required on macOS. Install it from https://brew.sh, then rerun.'; exit 1; }
15
+ command -v curl >/dev/null 2>&1 || brew install curl
16
+ command -v git >/dev/null 2>&1 || brew install git
17
+ command -v node >/dev/null 2>&1 || brew install node
18
+ if ! nomarmy_is_cloud; then
19
+ command -v xcode-select >/dev/null 2>&1 && xcode-select -p >/dev/null 2>&1 || { echo 'ERROR: Xcode Command Line Tools are required. Run: xcode-select --install'; exit 1; }
20
+ command -v cmake >/dev/null 2>&1 || brew install cmake
21
+ fi
22
+ # A Homebrew formula, not a cask -- installs headlessly like curl/git/node,
23
+ # no manual first-launch the way Docker Desktop needs.
24
+ command -v podman >/dev/null 2>&1 || brew install podman
25
+ ;;
26
+ Linux)
27
+ if nomarmy_is_cloud; then
28
+ # No local model is built or served, so the C++ toolchain is not needed.
29
+ need curl; need git; need node; need npm
30
+ else
31
+ if ! command -v cmake >/dev/null 2>&1 || ! command -v c++ >/dev/null 2>&1 || ! command -v curl >/dev/null 2>&1 || ! command -v git >/dev/null 2>&1 || ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then install_build_dependencies; fi
32
+ need curl; need git; need cmake; need c++; need node; need npm
33
+ if [[ "$NOMARMY_PROFILE" == dgx-spark || "$NOMARMY_PROFILE" == nvidia-linux ]]; then need nvidia-smi; need nvcc; fi
34
+ fi
35
+ # Podman runs rootless, directly on the host kernel here -- no daemon to
36
+ # enable or start, unlike Docker Engine.
37
+ command -v podman >/dev/null 2>&1 || install_podman
38
+ ;;
39
+ MINGW*|MSYS*|CYGWIN*|Windows_NT)
40
+ cat >&2 <<'MSG'
41
+ ERROR: install.sh does not run natively on Windows. Three options, and the usual
42
+ advice is not always the better one:
43
+
44
+ 1. WSL2, then run the Linux install inside your distro (supported path)
45
+ Podman runs natively inside the WSL2 distro itself -- nothing to install
46
+ on the Windows host, and no Docker Desktop licensing exposure there.
47
+ Note: WSL2 defaults to ~50% of host RAM, shared across every distro. On
48
+ a 32 GB machine that caps the model at ~16 GB. Raise it in
49
+ %UserProfile%\.wslconfig, which needs `wsl --shutdown` and will restart
50
+ every running container.
51
+
52
+ 2. Native Windows llama.cpp built from source, then point nomArmy at it.
53
+ Gets the full host RAM. Needs a C++ toolchain:
54
+ winget install Microsoft.VisualStudio.2022.BuildTools --override \
55
+ "--wait --passive --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
56
+ Prebuilt llama.cpp Windows binaries are NOT a reliable shortcut: on some
57
+ CPUs every compute backend crashes at startup (access violation) while
58
+ non-compute binaries run fine. The cause is dynamic backend loading, so
59
+ build it statically instead -- these flags are verified working:
60
+ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
61
+ -DGGML_BACKEND_DL=OFF -DBUILD_SHARED_LIBS=OFF \
62
+ -DGGML_NATIVE=ON -DLLAMA_CURL=OFF
63
+ GGML_BACKEND_DL=OFF is the one that matters: it links the CPU backend in
64
+ rather than probing for it at runtime.
65
+
66
+ 3. Run workers on a Bedrock profile and skip local inference entirely:
67
+ ./install.sh --profile bedrock
68
+
69
+ Run `nomarmy sizing` on the host first -- it reports which of these your
70
+ hardware can actually support before you commit to one.
71
+ MSG
72
+ exit 1
73
+ ;;
74
+ *)
75
+ echo "ERROR: $OS_NAME is not a supported host. See the README for supported platforms." >&2
76
+ exit 1
77
+ ;;
78
+ esac
79
+ need node; need npm
80
+
81
+ # The nomarmy CLI and the MCP server both import from lib/, which has real
82
+ # dependencies. Without this a fresh clone cannot run `nomarmy` at all -- the
83
+ # first import of `yaml` fails. This is separate from the copy the worker setup
84
+ # scripts install into $NOMARMY_AGENT_INSTALL_DIR.
85
+ echo '==> Installing nomArmy dependencies'
86
+ (cd "$ROOT" && npm install --omit=dev --no-audit --no-fund)
87
+
88
+ # Put `nomarmy` on PATH. Non-fatal by design: linking needs a writable npm
89
+ # global prefix, and the CLI is equally usable as `node bin/nomarmy.mjs`.
90
+ if (cd "$ROOT" && npm link >/dev/null 2>&1); then
91
+ echo '==> Linked the nomarmy CLI onto PATH'
92
+ else
93
+ echo 'NOTE: could not link the nomarmy CLI (npm global prefix not writable).'
94
+ echo " Run it directly instead: node $ROOT/bin/nomarmy.mjs <command>"
95
+ fi
96
+ # The sandbox is required on every profile, cloud included: it is what keeps
97
+ # repository content away from host credentials. Podman readiness (starting
98
+ # the macOS VM if needed) is verified later, in scripts/setup-sandbox.sh --
99
+ # on a fresh macOS install nothing has initialized that VM yet at this point.
100
+ if nomarmy_is_cloud; then need aws || { echo 'ERROR: the AWS CLI is required for cloud profiles.'; exit 1; }; fi
101
+ "$ROOT/scripts/install-llama-cpp.sh" "$NOMARMY_PROFILE"
102
+ if ! command -v openclaw >/dev/null 2>&1; then
103
+ echo '==> Installing OpenClaw (non-interactive)'
104
+ curl -fsSL https://openclaw.ai/install.sh | bash -s -- --no-onboard
105
+ export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH"
106
+ fi
107
+ need openclaw
108
+ if ! nomarmy_is_cloud; then openclaw plugins install @openclaw/llama-cpp-provider || true; fi
109
+ "$ROOT/scripts/start-inference.sh" "$NOMARMY_PROFILE"
110
+ # Sandbox before provider config: configure-openclaw.sh refuses to store a real
111
+ # Bedrock credential unless the coder sandbox is already network-isolated.
112
+ "$ROOT/scripts/setup-sandbox.sh"
113
+ "$ROOT/scripts/configure-openclaw.sh" "$NOMARMY_PROFILE"
114
+ if [[ "$WITH_CLAUDE" == 1 ]]; then
115
+ if command -v claude >/dev/null 2>&1; then node "$ROOT/bin/nomarmy.mjs" connect claude; else echo 'NOTE: Claude Code not found; worker stack installed. Install Claude Code then run: nomarmy connect claude'; fi
116
+ fi
117
+ if command -v codex >/dev/null 2>&1; then node "$ROOT/bin/nomarmy.mjs" connect codex; else echo 'NOTE: Codex not found; run: nomarmy connect codex (after installing Codex)'; fi
118
+ "$ROOT/scripts/verify-install.sh" "$NOMARMY_PROFILE"
119
+ if nomarmy_is_cloud && [[ "${NOMARMY_ORCHESTRATOR_RUNTIME:-}" == "claude-code" ]]; then
120
+ echo
121
+ echo "==> Next: point the orchestrator at Bedrock"
122
+ echo " ./scripts/configure-orchestrator.sh $NOMARMY_PROFILE # print the settings"
123
+ echo " ./scripts/configure-orchestrator.sh $NOMARMY_PROFILE --apply # write them to Claude Code"
124
+ fi
125
+ echo "==> Install complete. Run: ./e2e.sh --profile $NOMARMY_PROFILE"