Repository navigation
build: SimplyCubed Code foundation (gate-first Go core) - #2
Merged
Merged
Conversation
Gate-first scaffolding for the Go core. - Makefile `check` = gofmt + go vet + build + test. This is the gate. - .github/workflows/check.yml runs it in CI (not a required check yet; that is a maintainer decision, see STATUS.md). - cmd/simplycubed: minimal CLI (`version`), the local-run entry point. - internal/buildinfo: build-time version, with a test so the gate has teeth. - loop/goal.json: the machine-readable goal, invariants, and milestones for this build, dated 2026-07-30. - STATUS.md: honest handoff — what exists, what is deferred to a maintainer, and what is blocked on Azure access. - docs/spec/architecture.md: the system shape. Engine-independent by design; engine-dependent decisions are documented, not coded, pending the Azure replay spike.
The engine-independent core. - internal/domain: plain types (Issue, RunRequest, RunResult, Verdict, Finding) with no model or GitHub dependency, plus Verdict.HasBlocker so the loop never trusts a "pass" that carries a blocker finding. - internal/engine: the Runner interface, the single seam to a model. The loop depends only on this. - internal/engine/fake: a deterministic scripted Runner. No network, no spend. This is what makes the whole loop, including its failure paths, testable. Tests cover the fake's ordering, no-op-past-end, and engine-error paths.
- internal/gate: runs the repo's gate command, captures exit code and a bounded output tail, and computes a normalized signature so the loop can distinguish a stall (same failure again) from progress (a different failure). Signature strips ANSI, durations, hex, and bare numbers. - internal/config: loads .github/simplycubed.yml and refuses a config with no `gate:` (an ungated loop is not built). Stdlib-only flat-key parser for now, documented as a bootstrap to be swapped for a real YAML parser. - internal/state: the sc: label lifecycle with mutual-exclusion transitions. Go is the only human-applied state; Blocked and Done are terminal. All green; tests cover pass/fail/signature, the missing-gate refusal, and the legal/illegal transition sets.
The centerpiece: goal -> act -> grade -> repeat, ending exactly two ways. - internal/forge: the GitHub side as an interface (OpenPR, SetState, Comment). Note the absence of a Merge method: the loop cannot merge, by construction. - internal/forge/fake: a recording forge for tests. - internal/loop: the engine. It grades each round against an injected gate, feeds a red gate back into another round, and stops when the gate passes (open a PR) or when it stalls (two reds with the same signature -> escalate, open NO PR). MaxRounds is a backstop. Prompt assembly is left as a placeholder with a pointer to the ADR, per the code-vs-docs boundary. Tests: success on round 1, fix on round 2, engine error -> blocked/no-PR, and the honesty test -- an engine that never fixes the gate ends Blocked and opens zero pull requests. A loop only ever seen to succeed is no loop at all.
Six ADRs capturing the decisions from design, with the engine-dependent ones marked pending the S3 replay spike so they are recorded but not coded against a guess: - 0001 engine-independent core (implemented) - 0002 no merge path in the binary (implemented, structural) - 0003 Codex on Azure as the first engine adapter (adapter pending S3) - 0004 role prompts and the reviewer verdict (pending S3) - 0005 budgets and stall thresholds (pending S3; numbers come from real runs) - 0006 runtime on GitHub Actions, and identity (one-App-vs-two open)
- internal/ledger: append-only JSON-line events (a line per round with the gate result, a terminal line per run with the outcome). Clock is injectable for deterministic tests. This is the audit trail and the basis for later cost and status reporting; it is engine-independent. - loop: optionally records a round line each iteration and a run_end line at the terminal outcome. Nil ledger is a no-op, so it stays out of the way in tests that do not need it. Tests cover the JSONL shape (one line per event, zero fields omitted) and the loop emitting fail/pass round lines plus a pr_opened run_end.
- internal/worktree: create, list, and remove a git worktree per issue so concurrent loops never share a checkout. Add is idempotent -- an existing worktree for a branch is detected and reused rather than erroring, since git refuses to check the same branch out twice. Tested end to end against a temporary git repo (init, commit, add, list, re-add, remove). - STATUS: record it.
1 of 3 tasks
charlesgreen
added a commit
that referenced
this pull request
Sep 19, 2026
* fix(gemini): trust workspace for headless gemini-cli gemini-cli 0.60+ exits 55 (FatalUntrustedWorkspaceError) when folder trust is on and the Actions checkout is not in trustedFolders.json. -y auto-approves tools but does not bypass that gate. Set GEMINI_CLI_TRUST_WORKSPACE=true by default (ExtraEnv can override) and include a short CLI output tail in engine errors so bot comments show the real failure next time. Unblocks Sync #1/#2 and code#147 dogfood after Vertex preflight. * test(gemini): cover silent CLI failure error path Codecov patch flagged the empty-output branch of the exit-55 error formatting. Exercise a non-zero exit with no stdout/stderr.
Merged
2 of 3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overnight foundation pass for SimplyCubed Code. Built engine-first so the whole loop is testable with zero LLM spend. Eight commits, each keeping
make checkgreen (verified per-commit in an isolated worktree), meant to be reviewed commit by commit.What's here (M1–M7, all green)
Makefile check(gofmt + vet + build + test), run by.github/workflows/check.yml.internal/domain— core types, no model/GitHub dependency.internal/engine— theRunnerinterface (the one seam to a model) + a deterministic fake that drives every test.internal/gate— runs the repo's gate command; captures exit, output tail, and a normalized stall signature.internal/config— loads.github/simplycubed.yml; refuses a config with nogate:.internal/state— thesc:label lifecycle with mutual-exclusion transitions.internal/loop—goal -> act -> grade -> repeat; opens a PR on success, escalates (Blocked, no PR) on a stall. Includes the honesty test.internal/forge— GitHub side as an interface with no merge method, plus a recording fake.internal/ledger— append-only JSONL run events, wired into the loop.internal/worktree— idempotent per-issue git worktree isolation.docs/spec/architecture.md+ six ADRs indocs/decisions/.The code-vs-docs line (deliberate)
Engine-dependent design (role prompts, verdict schema, budget/stall numbers, Action packaging) is written as ADRs, not coded, because the blocked S3 Azure replay is what validates those assumptions. See
STATUS.mdandloop/goal.json.Left for you (in
STATUS.md)make checkis not a required status check yet (avoids a solo self-approval deadlock).Blocked on you (not faked)
The Phase 0 spikes (S1 Azure auth, S3 replay) need the Azure resource name + gpt-5.4 / gpt-5.4-mini deployment names and
AZURE_OPENAI_API_KEY.codexCLI is installed (0.146.0); an isolatedCODEX_HOMEtemplate is staged in scratch so your~/.codexis untouched.No secrets or private material in the diff (grepped before every push, and the full diff re-checked).