Skip to content

Commit 2b35d8e

Browse files
authored
Merge pull request #91 from simplycubed/docs/audit-fixes
docs: fix what the docs claimed, and document what shipped
2 parents 3d3dcfc + b441796 commit 2b35d8e

6 files changed

Lines changed: 269 additions & 27 deletions

File tree

‎README.md‎

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
# SimplyCubed Code
22

3+
[![An agent that runs in your GitHub, not ours. Open source. Your runners, your secrets. A human merges.](docs/assets/simplycubed-code.png)](https://simplycubed.com/code?utm_source=github&utm_medium=readme&utm_campaign=code)
4+
35
An autonomous coding agent that lives inside your own GitHub. You file an issue, it opens a pull request, and a human decides whether to merge.
46

5-
> Status: beta. `v0.1.6` is the latest release; expect rough edges. Product overview: [simplycubed.com/code](https://simplycubed.com/code?utm_source=github&utm_medium=readme&utm_campaign=code). See [Status](#status).
7+
> Beta, at `v0.1.6`. Product overview: [simplycubed.com/code](https://simplycubed.com/code?utm_source=github&utm_medium=readme&utm_campaign=code). See [Status](#status).
8+
9+
### Try it without letting it write anything
10+
11+
```sh
12+
simplycubed run owner/repo#12 --dry-run
13+
```
14+
15+
That runs the whole loop, including the model and your own gate. It makes no GitHub writes and never pushes; it prints what it would have done instead.
16+
17+
`simplycubed init --workflow` also writes a self-test into your repository. Dispatch it once and it checks, in your own runner, that the App token resolves to a bot, that it can read what it needs, and that it is denied Actions administration. The install fails if that denial does not hold. Delete the workflow once it passes.
618

719
## What it is
820

@@ -22,7 +34,7 @@ The loop is issue to pull request, driven entirely through GitHub.
2234
4. A human reviews. If they request changes, a fixer role reads the feedback, makes the changes, re-runs the gate, and pushes back to the same pull request for another look. Only feedback left against the current head is addressed, so the loop never re-litigates a comment it already handled.
2335
5. A human merges. The agent does not.
2436

25-
A separate read-only reviewer role is defined in the code but is not yet wired into the loop, so today the review in step 4 is the human's. The roadmap below tracks it.
37+
An automated reviewer runs before step 4 if you turn it on (`review: true`, off by default). It comments; it never approves and never merges. Step 5 is a human either way.
2638

2739
### Label lifecycle
2840

@@ -45,10 +57,44 @@ You can also drive it by comment, addressed to the bot at the start of a line:
4557

4658
Only comments from people with write access are acted on, and only a comment that begins with the mention counts, so quoting an earlier comment never re-triggers a run. Note that a plain pull-request comment is not a review: to run the fixer from a review, submit it through **Files changed → Review changes**.
4759

60+
### What triggers a run
61+
62+
```mermaid
63+
flowchart LR
64+
L["issue labelled sc:go"] --> R["run job"]
65+
V["review submitted<br/>OWNER, MEMBER or COLLABORATOR"] --> A["address job"]
66+
C["comment starting with<br/>@simplycubed-code"] --> P{"verb?"}
67+
68+
R --> RC["simplycubed run"]
69+
A --> AC["simplycubed address"]
70+
P -->|"go"| RC
71+
P -->|"address"| AC
72+
P -->|"help"| H["prints the commands"]
73+
P -->|"anything else"| N["nothing"]
74+
75+
RC --> PR["pull request opens<br/>a human merges it"]
76+
AC --> PR
77+
```
78+
79+
A plain comment in the conversation box is not a review. To run the fixer from a review, submit it through **Files changed → Review changes**. Every path checks that the person has write access before anything else happens.
80+
4881
## Running in your own GitHub
4982

5083
The whole thing runs on GitHub Actions, event-driven, with no server and no VM for SimplyCubed to operate. When you install the app and file issues, the work executes on your runners inside your organization.
5184

85+
### What it can do to your repo, and what stops it
86+
87+
It can open a pull request against a branch. That is the strongest action available to it.
88+
89+
What stops it, roughly in order of how much you should trust each one:
90+
91+
1. **It cannot merge, by construction.** The GitHub interface it is built against has no merge method: see [`internal/forge/forge.go`](internal/forge/forge.go). The model is not being asked to follow a rule here. The capability is absent from the code.
92+
2. The App holds three permissions: contents, pull requests, issues. Not workflows, administration, environments, or secrets. Each job mints its own token, scoped to one repository.
93+
3. That scope is proved on every run rather than claimed. The workflow calls an Actions-administration endpoint and expects the denial, so your run log carries the evidence.
94+
4. **The model's shell never holds a GitHub token.** `GH_TOKEN` and `GITHUB_TOKEN` are stripped from the engine's environment before it starts.
95+
5. Neither engine's "dangerous" bypass flag is set. When a change cannot be made under those constraints, the run stops and a human finishes it. [Why](docs/faq.md).
96+
6. No deploy credentials, and no path to production. Your branch protection rules decide what happens once the pull request exists.
97+
5298
What this buys you:
5399

54100
- Your code stays in your repos. SimplyCubed never receives it.
@@ -160,7 +206,7 @@ gate: make check
160206
engine: claude
161207
```
162208

163-
The first engine adapter targets the Codex CLI running against Azure OpenAI. Today the shipped setup needs an Azure endpoint, an API key, and optionally a deployment name override if you are not using the default `gpt-5.4`. A Claude Code adapter is planned. The `Runner` interface is the seam where other engines plug in.
209+
The first engine adapter targets the Codex CLI running against Azure OpenAI. Today the shipped setup needs an Azure endpoint, an API key, and optionally a deployment name override if you are not using the default `gpt-5.4`. A Claude Code adapter ships too, behind `engine: claude`. The `Runner` interface is the seam where other engines plug in.
164210

165211
## Status
166212

@@ -173,7 +219,7 @@ Roadmap, roughly in order:
173219
- Wiring the read-only reviewer role into the loop so a diff is reviewed before it reaches a human.
174220
- The self-onboarding flow via `init` and `init --workflow`. **Done.**
175221
- The Codex on Azure OpenAI engine adapter. **Done.**
176-
- The Claude Code engine adapter.
222+
- Self-hosted models on Hugging Face.
177223

178224
If you are evaluating it now, read that as beta software rather than a polished product. The core loops work; reviewer wiring is still in progress, and self-onboarding shipped as `init` and `init --workflow`.
179225

‎STATUS.md‎

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ The Actions runtime authenticates as the `simplycubed-code[bot]` GitHub App.
2727
Each job mints its own installation token scoped to one repository with
2828
`contents`, `issues`, and `pull-requests` permissions only.
2929

30-
`v0.1.5` is the current release. `go install
31-
github.com/simplycubed/code/cmd/simplycubed@v0.1.5` works today. `v0.1.2` and
32-
`v0.1.4` are retracted in `go.mod` because those tags pointed at the wrong
30+
`v0.1.6` is the current release. `go install
31+
github.com/simplycubed/code/cmd/simplycubed@v0.1.6` works today. `v0.1.2` and `v0.1.4` are retracted in `go.mod` because those tags pointed at the wrong
3332
commits.
3433

3534
Both loops were dogfooded: the issue-to-PR loop produced the merged
@@ -40,15 +39,19 @@ dependency-upgrade PR on `charlesgreen/gsm`.
4039
```
4140
cmd/simplycubed/ CLI: version, init, preflight, run, address
4241
internal/domain/ core types (Role, Issue, RunRequest, ReviewFeedback, Verdict)
43-
internal/engine/ Runner interface + fake; codex/ adapter (Azure OpenAI)
42+
internal/engine/ Runner interface + fake; codex/ (Azure OpenAI) and claude/ adapters
4443
internal/gate/ runs the repo gate command; exit code, output tail, signature
45-
internal/config/ .github/simplycubed.yml; refuses a missing gate; attribution flag
44+
internal/config/ .github/simplycubed.yml; refuses a missing gate; engine, review,
45+
prDescription, attribution
4646
internal/state/ sc: label lifecycle with mutual exclusion
4747
internal/roles/ implementer, reviewer, fixer as data; bounds; untrusted-input delimiting
4848
internal/loop/ goal -> act -> grade -> repeat; Run (issue->PR) and Fix (fix-on-request)
4949
internal/forge/ GitHub side as an interface (no merge method); gh/ adapter + recording fake
5050
internal/vcs/git/ commit, push, and sync-to-PR-head
5151
internal/describe/ generated PR walkthrough, changes table, and sequence diagram
52+
internal/verdict/ the reviewer verdict: schema, validation, findings for the fixer
53+
internal/command/ comment commands (@simplycubed-code go | address | help)
54+
internal/forge/dryrun/ records the GitHub writes a dry run skips
5255
internal/attribution/ the SimplyCubed Code marker on generated commits and PRs
5356
internal/ledger/ append-only JSONL run events
5457
internal/worktree/ an isolated git worktree per issue
@@ -69,16 +72,11 @@ via `.github/workflows/check.yml`; the required status check on `main` is the
6972

7073
## What is next
7174

72-
- **Wire the read-only reviewer role into the loop.** The `Reviewer` role and the
73-
`Verdict` type exist, but no loop calls the reviewer yet, so today the review is
74-
the human's. Wiring it (reviewer emits a structured verdict, findings feed the
75-
fixer, comment-only, never a bot approval) is the next core-loop step. The
76-
README says so plainly rather than implying it is already done.
77-
- **Engine roadmap:** Codex on Azure (now) -> a Claude Code adapter -> Hugging
78-
Face self-hosted models. Each is another `Runner` implementation; no core
79-
rework.
75+
- **Engine roadmap:** Codex on Azure and Claude Code both ship. Self-hosted
76+
models on Hugging Face are next. Each is another `Runner` implementation; no
77+
core rework.
8078

8179
## Deliberately not done (maintainer decisions)
8280

83-
- **CI actions are pinned by tag, not commit SHA.** Pin by SHA before this goes
84-
past scaffolding.
81+
Nothing outstanding. The two items that lived here, SHA-pinned actions and a
82+
per-role bot identity, both shipped in v0.1.3 and v0.1.6.

‎docs/assets/simplycubed-code.png‎

73.1 KB
Loading

‎docs/faq.md‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@ open. Nothing in this repository sets it.
5858

5959
## Are the `sc:` labels created for me?
6060

61-
Not automatically, yet. For now the labels are created once when you onboard a
62-
repo. The planned self-onboarding flow will propose them (and the config and
63-
workflow files) as a pull request you merge, so nothing is created behind your
64-
back. Until then, creating the six state labels is a one-time setup step.
61+
Yes, once. `simplycubed init --workflow` creates the six state labels through
62+
your own `gh` auth, and writes the config, the caller workflow, and the install
63+
self-test as local files.
64+
65+
Nothing is created behind your back and nothing is merged for you. You open that
66+
setup pull request and merge it yourself, because the App holds no `workflows`
67+
permission and cannot add its own workflow files.
68+
6569

6670
## The agent won't propose anything. Why?
6771

‎docs/setup.md‎

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ simplycubed version
2626
simplycubed init --workflow
2727
```
2828

29-
That writes `.github/simplycubed.yml`, writes `.github/workflows/simplycubed.yml`,
30-
and creates the `sc:*` labels through your local `gh` auth. The files are local
29+
That writes three files and creates the `sc:*` labels through your local `gh`
30+
auth:
31+
32+
- `.github/simplycubed.yml`, the repository config
33+
- `.github/workflows/simplycubed.yml`, the caller workflow
34+
- `.github/workflows/simplycubed-selftest.yml`, an install check you run once
35+
and then delete The files are local
3136
changes in your repository; nothing is merged or installed remotely for you.
3237

3338
3. Edit `.github/simplycubed.yml` and set a real gate that is already green on
@@ -72,16 +77,64 @@ a setup pull request, and merge it yourself. Setup files are written locally by
7277
`simplycubed init` and merged by a human, because the runtime holds no
7378
`workflows` permission and cannot add its own workflow files.
7479

75-
6. File an issue that describes a small change and apply the `sc:go` label.
80+
6. Check the install before trusting it:
81+
82+
```sh
83+
gh workflow run simplycubed-selftest
84+
```
7685

77-
7. Wait for the workflow to open a pull request. Review it like any other PR:
86+
That runs in your own runner and reports whether the App token resolves to a
87+
bot, whether it is correctly denied Actions administration, whether a commit is
88+
possible, and whether the engine can start there. Delete the workflow once it
89+
passes; normal operation goes through the App and the `sc:go` label.
90+
91+
7. File an issue that describes a small change and apply the `sc:go` label.
92+
93+
8. Wait for the workflow to open a pull request. Review it like any other PR:
7894

7995
- Merge it yourself if it is good.
8096
- Or request changes; the fixer loop will address feedback on the current head
8197
and push back to the same branch.
8298

8399
That is the first end-to-end path: issue -> PR -> human merge.
84100

101+
## Where each value goes
102+
103+
The same two Azure values are needed in both places, and setting one does not
104+
set the other. A repository secret is not visible to your local shell, and a
105+
reusable workflow inherits nothing from SimplyCubed.
106+
107+
```mermaid
108+
flowchart TB
109+
cfg[".github/simplycubed.yml<br/>gate, engine, review<br/>committed, never holds a key"]
110+
111+
subgraph local["Local CLI: you are the identity"]
112+
L1["your shell<br/>AZURE_OPENAI_ENDPOINT<br/>AZURE_OPENAI_API_KEY"]
113+
L2["your gh auth"]
114+
L3["simplycubed run / address"]
115+
L4["commits and PR authored by you"]
116+
L1 --> L3
117+
L2 --> L3
118+
L3 --> L4
119+
end
120+
121+
subgraph actions["GitHub Actions: the App is the identity"]
122+
A1["repository variables<br/>AZURE_OPENAI_ENDPOINT<br/>SIMPLYCUBED_GH_APP_ID"]
123+
A2["repository secrets<br/>AZURE_OPENAI_API_KEY<br/>SIMPLYCUBED_GH_APP_PRIVATE_KEY"]
124+
A3["per-job installation token<br/>contents, issues, pull requests"]
125+
A4["simplycubed run / address"]
126+
A5["commits and PR authored by<br/>simplycubed-code[bot]"]
127+
A2 --> A3
128+
A1 --> A4
129+
A2 --> A4
130+
A3 --> A4
131+
A4 --> A5
132+
end
133+
134+
cfg --> L3
135+
cfg --> A4
136+
```
137+
85138
## Azure values
86139

87140
The shipped Codex-on-Azure setup needs these values:
@@ -145,6 +198,21 @@ passes:
145198
The reusable workflow installs the CLI, exports the endpoint and key for the job,
146199
and runs `simplycubed run` or `simplycubed address`.
147200

201+
## Watching it run before it writes
202+
203+
Two commands answer "is this configured correctly" without changing anything.
204+
205+
`simplycubed preflight` validates the repository config and the engine settings
206+
and exits. It is what the workflow runs before installing the rest of the
207+
toolchain, so a misconfigured repository finds out in seconds.
208+
209+
`simplycubed run owner/repo#N --dry-run` runs the whole loop, including the
210+
engine and your real gate, and skips the push and every GitHub write. It prints
211+
what it would have done instead, and in Actions writes that to the run summary.
212+
213+
If something goes wrong, [troubleshooting.md](troubleshooting.md) starts from
214+
the symptom.
215+
148216
## Optional model override
149217

150218
If your Azure deployment name is not `gpt-5.4`, set it explicitly.

0 commit comments

Comments
 (0)