@caseyharalson/orrery 0.7.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/.devcontainer.example/Dockerfile +149 -0
- package/.devcontainer.example/devcontainer.json +61 -0
- package/.devcontainer.example/init-firewall.sh +175 -0
- package/LICENSE +21 -0
- package/README.md +139 -0
- package/agent/skills/discovery/SKILL.md +428 -0
- package/agent/skills/discovery/schemas/plan-schema.yaml +138 -0
- package/agent/skills/orrery-execute/SKILL.md +107 -0
- package/agent/skills/orrery-report/SKILL.md +119 -0
- package/agent/skills/orrery-review/SKILL.md +105 -0
- package/agent/skills/orrery-verify/SKILL.md +105 -0
- package/agent/skills/refine-plan/SKILL.md +291 -0
- package/agent/skills/simulate-plan/SKILL.md +244 -0
- package/bin/orrery.js +5 -0
- package/lib/cli/commands/help.js +21 -0
- package/lib/cli/commands/ingest-plan.js +56 -0
- package/lib/cli/commands/init.js +21 -0
- package/lib/cli/commands/install-devcontainer.js +97 -0
- package/lib/cli/commands/install-skills.js +182 -0
- package/lib/cli/commands/orchestrate.js +27 -0
- package/lib/cli/commands/resume.js +146 -0
- package/lib/cli/commands/status.js +137 -0
- package/lib/cli/commands/validate-plan.js +288 -0
- package/lib/cli/index.js +57 -0
- package/lib/orchestration/agent-invoker.js +595 -0
- package/lib/orchestration/condensed-plan.js +128 -0
- package/lib/orchestration/config.js +213 -0
- package/lib/orchestration/dependency-resolver.js +149 -0
- package/lib/orchestration/edit-invoker.js +115 -0
- package/lib/orchestration/index.js +1065 -0
- package/lib/orchestration/plan-loader.js +212 -0
- package/lib/orchestration/progress-tracker.js +208 -0
- package/lib/orchestration/report-format.js +80 -0
- package/lib/orchestration/review-invoker.js +305 -0
- package/lib/utils/agent-detector.js +47 -0
- package/lib/utils/git.js +297 -0
- package/lib/utils/paths.js +43 -0
- package/lib/utils/plan-detect.js +24 -0
- package/lib/utils/skill-copier.js +79 -0
- package/package.json +58 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04
|
|
2
|
+
|
|
3
|
+
# ---- Base config ----
|
|
4
|
+
ARG TZ=America/Chicago
|
|
5
|
+
ENV TZ="${TZ}"
|
|
6
|
+
ENV DEVCONTAINER=true
|
|
7
|
+
|
|
8
|
+
ARG USERNAME=vscode
|
|
9
|
+
ENV HOME=/home/${USERNAME}
|
|
10
|
+
|
|
11
|
+
# Use bash with pipefail for build RUN steps by default (safer than /bin/sh)
|
|
12
|
+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
13
|
+
|
|
14
|
+
# ---- OS packages ----
|
|
15
|
+
RUN apt-get update \
|
|
16
|
+
&& export DEBIAN_FRONTEND=noninteractive \
|
|
17
|
+
&& apt-get -y install --no-install-recommends \
|
|
18
|
+
ca-certificates \
|
|
19
|
+
curl \
|
|
20
|
+
dnsutils \
|
|
21
|
+
fzf \
|
|
22
|
+
gh \
|
|
23
|
+
git \
|
|
24
|
+
gnupg2 \
|
|
25
|
+
iproute2 \
|
|
26
|
+
ipset \
|
|
27
|
+
iptables \
|
|
28
|
+
jq \
|
|
29
|
+
less \
|
|
30
|
+
man-db \
|
|
31
|
+
nano \
|
|
32
|
+
procps \
|
|
33
|
+
sudo \
|
|
34
|
+
unzip \
|
|
35
|
+
vim \
|
|
36
|
+
wget \
|
|
37
|
+
zsh \
|
|
38
|
+
aggregate \
|
|
39
|
+
&& apt-get autoremove -y \
|
|
40
|
+
&& apt-get clean -y \
|
|
41
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
42
|
+
|
|
43
|
+
# ---- Workspace + config dirs + persistent history ----
|
|
44
|
+
RUN mkdir -p /workspace \
|
|
45
|
+
/commandhistory \
|
|
46
|
+
"${HOME}/.claude" \
|
|
47
|
+
"${HOME}/.codex" \
|
|
48
|
+
"${HOME}/.gemini" \
|
|
49
|
+
&& touch /commandhistory/.bash_history \
|
|
50
|
+
&& chown -R "${USERNAME}:${USERNAME}" \
|
|
51
|
+
/workspace \
|
|
52
|
+
/commandhistory \
|
|
53
|
+
"${HOME}/.claude" \
|
|
54
|
+
"${HOME}/.codex" \
|
|
55
|
+
"${HOME}/.gemini"
|
|
56
|
+
|
|
57
|
+
# Persist bash history (devcontainer orientation)
|
|
58
|
+
RUN echo "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
|
|
59
|
+
> /etc/profile.d/00-devcontainer-history.sh \
|
|
60
|
+
&& chmod 0644 /etc/profile.d/00-devcontainer-history.sh
|
|
61
|
+
|
|
62
|
+
# ---- git-delta ----
|
|
63
|
+
ARG GIT_DELTA_VERSION=0.18.2
|
|
64
|
+
RUN ARCH="$(dpkg --print-architecture)" \
|
|
65
|
+
&& wget -q "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" \
|
|
66
|
+
&& dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" \
|
|
67
|
+
&& rm -f "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"
|
|
68
|
+
|
|
69
|
+
# ---- Switch to vscode user for user-scoped tool installs ----
|
|
70
|
+
USER ${USERNAME}
|
|
71
|
+
|
|
72
|
+
# Use bash -lc for nvm-driven commands (nvm.sh expects bash-ish behavior)
|
|
73
|
+
SHELL ["/bin/bash", "-lc"]
|
|
74
|
+
|
|
75
|
+
# ---- nvm + Node LTS ----
|
|
76
|
+
ARG NVM_VERSION=v0.39.7
|
|
77
|
+
RUN curl -fsSL "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" | bash \
|
|
78
|
+
&& export NVM_DIR="$HOME/.nvm" \
|
|
79
|
+
&& source "$NVM_DIR/nvm.sh" \
|
|
80
|
+
&& nvm install --lts \
|
|
81
|
+
&& nvm alias default lts/* \
|
|
82
|
+
&& nvm use default \
|
|
83
|
+
&& npm --version \
|
|
84
|
+
&& node --version
|
|
85
|
+
|
|
86
|
+
# Make nvm available in interactive shells (bash + zsh)
|
|
87
|
+
RUN echo 'export NVM_DIR="$HOME/.nvm"' >> "${HOME}/.bashrc" \
|
|
88
|
+
&& echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> "${HOME}/.bashrc" \
|
|
89
|
+
&& echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> "${HOME}/.bashrc" \
|
|
90
|
+
&& echo 'export NVM_DIR="$HOME/.nvm"' >> "${HOME}/.zshrc" \
|
|
91
|
+
&& echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> "${HOME}/.zshrc" \
|
|
92
|
+
&& echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> "${HOME}/.zshrc"
|
|
93
|
+
|
|
94
|
+
# ---- uv ----
|
|
95
|
+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
96
|
+
|
|
97
|
+
# Ensure uv is on PATH for vscode user
|
|
98
|
+
ENV PATH="${HOME}/.cargo/bin:${PATH}"
|
|
99
|
+
|
|
100
|
+
# ---- zsh + powerlevel10k (zsh-in-docker) ----
|
|
101
|
+
ARG ZSH_IN_DOCKER_VERSION=1.2.0
|
|
102
|
+
RUN sh -c "$(wget -qO- "https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh")" -- \
|
|
103
|
+
-p git \
|
|
104
|
+
-a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
|
|
105
|
+
-a 'export NVM_DIR="$HOME/.nvm"' \
|
|
106
|
+
-a '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' \
|
|
107
|
+
-a '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' \
|
|
108
|
+
-a "setopt nonomatch" \
|
|
109
|
+
-x
|
|
110
|
+
|
|
111
|
+
# ---- fzf shell integration (manual) ----
|
|
112
|
+
RUN mkdir -p "${HOME}/.fzf" \
|
|
113
|
+
&& wget -qO "${HOME}/.fzf/key-bindings.zsh" https://raw.githubusercontent.com/junegunn/fzf/master/shell/key-bindings.zsh \
|
|
114
|
+
&& wget -qO "${HOME}/.fzf/completion.zsh" https://raw.githubusercontent.com/junegunn/fzf/master/shell/completion.zsh \
|
|
115
|
+
&& echo '[ -f ~/.fzf/key-bindings.zsh ] && source ~/.fzf/key-bindings.zsh' >> "${HOME}/.zshrc" \
|
|
116
|
+
&& echo '[ -f ~/.fzf/completion.zsh ] && source ~/.fzf/completion.zsh' >> "${HOME}/.zshrc"
|
|
117
|
+
|
|
118
|
+
# ---- Install CLI tools via npm (Claude, Codex, Gemini, Orrery) ----
|
|
119
|
+
ARG CLAUDE_CODE_VERSION=latest
|
|
120
|
+
ARG CODEX_VERSION=latest
|
|
121
|
+
ARG GEMINI_VERSION=latest
|
|
122
|
+
ARG ORRERY_VERSION=latest
|
|
123
|
+
|
|
124
|
+
RUN export NVM_DIR="$HOME/.nvm" \
|
|
125
|
+
&& source "$NVM_DIR/nvm.sh" \
|
|
126
|
+
&& nvm use default \
|
|
127
|
+
&& npm install -g \
|
|
128
|
+
"@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}" \
|
|
129
|
+
"@openai/codex@${CODEX_VERSION}" \
|
|
130
|
+
"@google/gemini-cli@${GEMINI_VERSION}" \
|
|
131
|
+
"@caseyharalson/orrery@${ORRERY_VERSION}"
|
|
132
|
+
|
|
133
|
+
# ---- Back to root for firewall script setup ----
|
|
134
|
+
USER root
|
|
135
|
+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
136
|
+
|
|
137
|
+
COPY init-firewall.sh /usr/local/bin/init-firewall.sh
|
|
138
|
+
RUN chmod +x /usr/local/bin/init-firewall.sh \
|
|
139
|
+
&& echo "${USERNAME} ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/${USERNAME}-firewall \
|
|
140
|
+
&& chmod 0440 /etc/sudoers.d/${USERNAME}-firewall
|
|
141
|
+
|
|
142
|
+
# ---- Defaults ----
|
|
143
|
+
WORKDIR /workspace
|
|
144
|
+
USER ${USERNAME}
|
|
145
|
+
|
|
146
|
+
# Keep zsh as the default interactive shell
|
|
147
|
+
ENV SHELL=/bin/zsh
|
|
148
|
+
ENV EDITOR=nano
|
|
149
|
+
ENV VISUAL=nano
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Orrery Dev Container",
|
|
3
|
+
"build": {
|
|
4
|
+
"dockerfile": "Dockerfile",
|
|
5
|
+
"args": {
|
|
6
|
+
"TZ": "${localEnv:TZ:America/Chicago}",
|
|
7
|
+
"CLAUDE_CODE_VERSION": "latest",
|
|
8
|
+
"CODEX_VERSION": "latest",
|
|
9
|
+
"GEMINI_VERSION": "latest",
|
|
10
|
+
"ORRERY_VERSION": "latest",
|
|
11
|
+
"GIT_DELTA_VERSION": "0.18.2",
|
|
12
|
+
"ZSH_IN_DOCKER_VERSION": "1.2.0"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"runArgs": ["--cap-add=NET_ADMIN", "--cap-add=NET_RAW"],
|
|
16
|
+
"customizations": {
|
|
17
|
+
"vscode": {
|
|
18
|
+
"extensions": [
|
|
19
|
+
"anthropic.claude-code",
|
|
20
|
+
"dbaeumer.vscode-eslint",
|
|
21
|
+
"esbenp.prettier-vscode",
|
|
22
|
+
"eamodio.gitlens",
|
|
23
|
+
"ms-azuretools.vscode-docker"
|
|
24
|
+
],
|
|
25
|
+
"settings": {
|
|
26
|
+
"editor.formatOnSave": true,
|
|
27
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
28
|
+
"editor.codeActionsOnSave": {
|
|
29
|
+
"source.fixAll.eslint": "explicit"
|
|
30
|
+
},
|
|
31
|
+
"terminal.integrated.defaultProfile.linux": "zsh",
|
|
32
|
+
"terminal.integrated.profiles.linux": {
|
|
33
|
+
"bash": {
|
|
34
|
+
"path": "bash",
|
|
35
|
+
"icon": "terminal-bash"
|
|
36
|
+
},
|
|
37
|
+
"zsh": {
|
|
38
|
+
"path": "zsh"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"remoteUser": "vscode",
|
|
45
|
+
"mounts": [
|
|
46
|
+
"source=orrery-bashhistory-${devcontainerId},target=/commandhistory,type=volume",
|
|
47
|
+
"source=shared-sandbox-claude-code-config,target=/home/vscode/.claude,type=volume",
|
|
48
|
+
"source=shared-sandbox-codex-config,target=/home/vscode/.codex,type=volume",
|
|
49
|
+
"source=shared-sandbox-gemini-config,target=/home/vscode/.gemini,type=volume"
|
|
50
|
+
],
|
|
51
|
+
"containerEnv": {
|
|
52
|
+
"NODE_OPTIONS": "--max-old-space-size=4096",
|
|
53
|
+
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude",
|
|
54
|
+
"CODEX_HOME": "/home/vscode/.codex",
|
|
55
|
+
"POWERLEVEL9K_DISABLE_GITSTATUS": "true",
|
|
56
|
+
"ORRERY_AGENT_PRIORITY": "codex,gemini,claude",
|
|
57
|
+
"ORRERY_REVIEW_ENABLED": "true"
|
|
58
|
+
},
|
|
59
|
+
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
|
|
60
|
+
"workspaceFolder": "/workspace"
|
|
61
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail # Exit on error, undefined vars, and pipeline failures
|
|
3
|
+
IFS=$'\n\t' # Stricter word splitting
|
|
4
|
+
|
|
5
|
+
# 1. Extract Docker DNS info BEFORE any flushing
|
|
6
|
+
DOCKER_DNS_RULES=$(iptables-save -t nat | grep "127\.0\.0\.11" || true)
|
|
7
|
+
|
|
8
|
+
# Flush existing rules and delete existing ipsets
|
|
9
|
+
iptables -F
|
|
10
|
+
iptables -X
|
|
11
|
+
iptables -t nat -F
|
|
12
|
+
iptables -t nat -X
|
|
13
|
+
iptables -t mangle -F
|
|
14
|
+
iptables -t mangle -X
|
|
15
|
+
ipset destroy allowed-domains 2>/dev/null || true
|
|
16
|
+
|
|
17
|
+
# 2. Selectively restore ONLY internal Docker DNS resolution
|
|
18
|
+
if [ -n "$DOCKER_DNS_RULES" ]; then
|
|
19
|
+
echo "Restoring Docker DNS rules..."
|
|
20
|
+
iptables -t nat -N DOCKER_OUTPUT 2>/dev/null || true
|
|
21
|
+
iptables -t nat -N DOCKER_POSTROUTING 2>/dev/null || true
|
|
22
|
+
echo "$DOCKER_DNS_RULES" | xargs -L 1 iptables -t nat
|
|
23
|
+
else
|
|
24
|
+
echo "No Docker DNS rules to restore"
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# First allow DNS and localhost before any restrictions
|
|
28
|
+
# Allow outbound DNS
|
|
29
|
+
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
|
|
30
|
+
# Allow inbound DNS responses
|
|
31
|
+
iptables -A INPUT -p udp --sport 53 -j ACCEPT
|
|
32
|
+
# Allow outbound SSH
|
|
33
|
+
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
|
|
34
|
+
# Allow inbound SSH responses
|
|
35
|
+
iptables -A INPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
|
|
36
|
+
# Allow localhost
|
|
37
|
+
iptables -A INPUT -i lo -j ACCEPT
|
|
38
|
+
iptables -A OUTPUT -o lo -j ACCEPT
|
|
39
|
+
|
|
40
|
+
# Create ipset with CIDR support
|
|
41
|
+
ipset create allowed-domains hash:net
|
|
42
|
+
|
|
43
|
+
# Fetch GitHub meta information and aggregate + add their IP ranges
|
|
44
|
+
echo "Fetching GitHub IP ranges..."
|
|
45
|
+
gh_ranges=$(curl -s https://api.github.com/meta)
|
|
46
|
+
if [ -z "$gh_ranges" ]; then
|
|
47
|
+
echo "ERROR: Failed to fetch GitHub IP ranges"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if ! echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null; then
|
|
52
|
+
echo "ERROR: GitHub API response missing required fields"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
echo "Processing GitHub IPs..."
|
|
57
|
+
while read -r cidr; do
|
|
58
|
+
if [[ ! "$cidr" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
|
|
59
|
+
echo "ERROR: Invalid CIDR range from GitHub meta: $cidr"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
echo "Adding GitHub range $cidr"
|
|
63
|
+
ipset add allowed-domains "$cidr"
|
|
64
|
+
done < <(echo "$gh_ranges" | jq -r '(.web + .api + .git)[]' | aggregate -q)
|
|
65
|
+
|
|
66
|
+
# Resolve and add other allowed domains
|
|
67
|
+
for domain in \
|
|
68
|
+
"registry.npmjs.org" \
|
|
69
|
+
"sentry.io" \
|
|
70
|
+
"statsig.com" \
|
|
71
|
+
"api.anthropic.com" \
|
|
72
|
+
"statsig.anthropic.com" \
|
|
73
|
+
"code.claude.com" \
|
|
74
|
+
"api.openai.com" \
|
|
75
|
+
"auth.openai.com" \
|
|
76
|
+
"platform.openai.com" \
|
|
77
|
+
"chatgpt.com" \
|
|
78
|
+
"www.googleapis.com" \
|
|
79
|
+
"oauth2.googleapis.com" \
|
|
80
|
+
"marketplace.visualstudio.com" \
|
|
81
|
+
"vscode.blob.core.windows.net" \
|
|
82
|
+
"update.code.visualstudio.com"; do
|
|
83
|
+
echo "Resolving $domain..."
|
|
84
|
+
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
|
|
85
|
+
if [ -z "$ips" ]; then
|
|
86
|
+
echo "ERROR: Failed to resolve $domain"
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
while read -r ip; do
|
|
91
|
+
if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
|
92
|
+
echo "ERROR: Invalid IP from DNS for $domain: $ip"
|
|
93
|
+
exit 1
|
|
94
|
+
fi
|
|
95
|
+
echo "Adding $ip for $domain"
|
|
96
|
+
ipset add allowed-domains "$ip"
|
|
97
|
+
done < <(echo "$ips")
|
|
98
|
+
done
|
|
99
|
+
|
|
100
|
+
# Get host IP from default route
|
|
101
|
+
HOST_IP=$(ip route | grep default | cut -d" " -f3)
|
|
102
|
+
if [ -z "$HOST_IP" ]; then
|
|
103
|
+
echo "ERROR: Failed to detect host IP"
|
|
104
|
+
exit 1
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
HOST_NETWORK=$(echo "$HOST_IP" | sed "s/\.[0-9]*$/.0\/24/")
|
|
108
|
+
echo "Host network detected as: $HOST_NETWORK"
|
|
109
|
+
|
|
110
|
+
# Set up remaining iptables rules
|
|
111
|
+
iptables -A INPUT -s "$HOST_NETWORK" -j ACCEPT
|
|
112
|
+
iptables -A OUTPUT -d "$HOST_NETWORK" -j ACCEPT
|
|
113
|
+
|
|
114
|
+
# Set default policies to DROP first
|
|
115
|
+
iptables -P INPUT DROP
|
|
116
|
+
iptables -P FORWARD DROP
|
|
117
|
+
iptables -P OUTPUT DROP
|
|
118
|
+
|
|
119
|
+
# First allow established connections for already approved traffic
|
|
120
|
+
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
121
|
+
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
122
|
+
|
|
123
|
+
# Then allow only specific outbound traffic to allowed domains
|
|
124
|
+
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
|
|
125
|
+
|
|
126
|
+
# Explicitly REJECT all other outbound traffic for immediate feedback
|
|
127
|
+
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
|
|
128
|
+
|
|
129
|
+
echo "Firewall configuration complete"
|
|
130
|
+
echo "Verifying firewall rules..."
|
|
131
|
+
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
|
|
132
|
+
echo "ERROR: Firewall verification failed - was able to reach https://example.com"
|
|
133
|
+
exit 1
|
|
134
|
+
else
|
|
135
|
+
echo "Firewall verification passed - unable to reach https://example.com as expected"
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# Verify GitHub API access
|
|
139
|
+
if ! curl --connect-timeout 5 https://api.github.com/zen >/dev/null 2>&1; then
|
|
140
|
+
echo "ERROR: Firewall verification failed - unable to reach https://api.github.com"
|
|
141
|
+
exit 1
|
|
142
|
+
else
|
|
143
|
+
echo "Firewall verification passed - able to reach https://api.github.com as expected"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# Verify Anthropic API access
|
|
147
|
+
if ! curl --connect-timeout 5 https://api.anthropic.com >/dev/null 2>&1; then
|
|
148
|
+
echo "ERROR: Firewall verification failed - unable to reach https://api.anthropic.com"
|
|
149
|
+
exit 1
|
|
150
|
+
else
|
|
151
|
+
echo "Firewall verification passed - able to reach https://api.anthropic.com as expected"
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# Verify OpenAI API access
|
|
155
|
+
if ! curl --connect-timeout 5 https://api.openai.com >/dev/null 2>&1; then
|
|
156
|
+
echo "ERROR: Firewall verification failed - unable to reach https://api.openai.com/"
|
|
157
|
+
exit 1
|
|
158
|
+
else
|
|
159
|
+
echo "Firewall verification passed - able to reach https://api.openai.com/ as expected"
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# Verify Gemini API access
|
|
163
|
+
if ! curl --connect-timeout 5 https://www.googleapis.com >/dev/null 2>&1; then
|
|
164
|
+
echo "ERROR: Firewall verification failed - unable to reach https://www.googleapis.com/"
|
|
165
|
+
exit 1
|
|
166
|
+
else
|
|
167
|
+
echo "Firewall verification passed - able to reach https://www.googleapis.com/ as expected"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# Cloudflare reachability probe
|
|
171
|
+
if ! curl --connect-timeout 5 https://www.cloudflare.com/cdn-cgi/trace >/dev/null 2>&1; then
|
|
172
|
+
echo "WARN: Could not reach Cloudflare trace endpoint; check ranges and DNS."
|
|
173
|
+
else
|
|
174
|
+
echo "Cloudflare verification passed."
|
|
175
|
+
fi
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Casey Haralson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Orrery
|
|
2
|
+
|
|
3
|
+
**Workflow planning and orchestration CLI for AI agents**
|
|
4
|
+
|
|
5
|
+
Orrery is a CLI tool designed to transform high-level development goals into executable, traceable, and engineered workflows. It turns high-level goals ("Add a user login system") into executable, step-by-step plans that agents follow autonomously, ensuring consistent and high-quality results.
|
|
6
|
+
|
|
7
|
+
## When to Use Orrery
|
|
8
|
+
|
|
9
|
+
**Good fit:**
|
|
10
|
+
|
|
11
|
+
- Multi-step features requiring coordinated changes across many files
|
|
12
|
+
- You want to review a plan before letting it run autonomously
|
|
13
|
+
- Tasks with clear dependencies between implementation steps
|
|
14
|
+
|
|
15
|
+
**Use your AI agent directly when:**
|
|
16
|
+
|
|
17
|
+
- Quick fixes or small changes
|
|
18
|
+
- Exploratory development where you're discovering as you go
|
|
19
|
+
- You want to stay interactive with every decision
|
|
20
|
+
|
|
21
|
+
See [Comparison](docs/COMPARISON.md) for a detailed analysis.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Prerequisites:
|
|
26
|
+
|
|
27
|
+
- Node.js
|
|
28
|
+
- Git
|
|
29
|
+
- Initialized Git repository (your project where you want work done)
|
|
30
|
+
- Access to LLM agent tools (Claude Code, Codex cli, or Gemini cli)
|
|
31
|
+
|
|
32
|
+
### Global Installation
|
|
33
|
+
|
|
34
|
+
To install Orrery globally on your system:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install -g @caseyharalson/orrery
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
Follow this workflow to go from a high-level goal to finished code.
|
|
43
|
+
|
|
44
|
+
### 1. Initialize Orrery
|
|
45
|
+
|
|
46
|
+
Install the necessary "Skills" into your global agent configuration directories (e.g., `~/.claude/skills`). Orrery will auto-detect which agents you have installed.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
orrery init
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Create a Plan
|
|
53
|
+
|
|
54
|
+
Navigate to your project directory and use your AI agent (now equipped with the `discovery` skill) to generate a plan.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Using the skill shorthand
|
|
58
|
+
/discovery I want to [goal]
|
|
59
|
+
|
|
60
|
+
# Or prompt your agent
|
|
61
|
+
"I want to [goal]. Please activate the discovery skill and create a plan."
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. Execute
|
|
65
|
+
|
|
66
|
+
Back in the terminal, run the orrery orchestrator to execute the plan steps. Orrery will create a dedicated work branch and manage agent interactions.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
orrery exec
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Important: Autonomous Execution
|
|
73
|
+
|
|
74
|
+
When you run `orrery exec`, agents execute plan steps **autonomously without step-by-step confirmation**. This enables fully automated workflows but means agents can modify files and run commands without asking.
|
|
75
|
+
|
|
76
|
+
**Built-in safeguards:**
|
|
77
|
+
|
|
78
|
+
- All work happens on an isolated branch (not your main branch)
|
|
79
|
+
|
|
80
|
+
**For additional isolation**, run Orrery inside a devcontainer. This provides a sandboxed environment where agent actions are contained. See [Devcontainer Setup](docs/advanced-workflows.md#devcontainer-setup) in Advanced Workflows.
|
|
81
|
+
|
|
82
|
+
## Advanced Workflows
|
|
83
|
+
|
|
84
|
+
For power users, Orrery offers additional capabilities:
|
|
85
|
+
|
|
86
|
+
- **Plan Refinement & Simulation** - Analyze, improve, and explore plans before execution
|
|
87
|
+
- **Devcontainer Setup** - Isolated, reproducible development environments
|
|
88
|
+
- **External Plan Creation** - Import plans from other tools or LLMs
|
|
89
|
+
- **Review Loop** - Iterative code review after each step with automatic fixes
|
|
90
|
+
- **Handling Blocked Plans** - Recovery workflows when steps cannot complete
|
|
91
|
+
|
|
92
|
+
See [Advanced Workflows](docs/advanced-workflows.md) for details.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Core Concepts
|
|
97
|
+
|
|
98
|
+
### Skills
|
|
99
|
+
|
|
100
|
+
Skills are modular instruction sets that teach an agent how to perform specific phases of work.
|
|
101
|
+
|
|
102
|
+
- **Discovery:** Analyze requirements and generate plans.
|
|
103
|
+
- **Refine-Plan:** Analyze and improve an existing plan by fixing oversights, improving context quality, and strengthening acceptance criteria.
|
|
104
|
+
- **Simulate-Plan:** Conversational dialogue to explore plans, identify risks, and verify approaches before execution.
|
|
105
|
+
|
|
106
|
+
### Plans
|
|
107
|
+
|
|
108
|
+
Plans are YAML files that define the "contract" for the work. They break down complex goals into ordered steps with:
|
|
109
|
+
|
|
110
|
+
- **Dependencies:** Pre-requisites for execution.
|
|
111
|
+
- **Acceptance Criteria:** explicit conditions for success.
|
|
112
|
+
- **Context:** Instructions and file paths relevant to the step.
|
|
113
|
+
|
|
114
|
+
### The Orchestrator
|
|
115
|
+
|
|
116
|
+
The Orchestrator (`orrery exec`) is the engine that drives the process. It loads plans, resolves dependencies, invokes the appropriate agents, and manages the lifecycle of the task, including reporting and archiving.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Command Reference
|
|
121
|
+
|
|
122
|
+
| Command | Description |
|
|
123
|
+
| :------------------- | :--------------------------------------------------------------------------------- |
|
|
124
|
+
| `orrery` | Command reference. |
|
|
125
|
+
| `orrery init` | Initialize Orrery: install skills to detected agents. |
|
|
126
|
+
| `orrery orchestrate` | Executes the active plan. Use `--review` to enable the review loop. Alias: `exec`. |
|
|
127
|
+
| `orrery status` | Shows the progress of current plans. |
|
|
128
|
+
|
|
129
|
+
## Directory Structure
|
|
130
|
+
|
|
131
|
+
Orrery maintains its state in the `.agent-work/` directory (configurable via `ORRERY_WORK_DIR`).
|
|
132
|
+
|
|
133
|
+
- `.agent-work/plans/`: **Active Plans.** New and in-progress plan files.
|
|
134
|
+
- `.agent-work/reports/`: **Reports.** Step-level execution logs and outcomes.
|
|
135
|
+
- `.agent-work/completed/`: **Archive.** Successfully executed plans are moved here.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
_Happy Building!_ ❤️
|