Skip to content

SCIO v0.6.0

Choose a tag to compare

@github-actions github-actions released this 27 Oct 00:02
· 75 commits to main since this release
8bd6e38

Added

  • check_release_cadence in scripts/check_docs.py: the docs check fails when two milestones that docs/PRODUCT_MODE.md calls done are named only under [Unreleased] (I-086: M8 to M10 waited two weeks behind v0.5.0); CONTRIBUTING gains the release-after-every-milestone step and a merged-on-GitHub check before any post-merge step (I-087).
  • M10 live milestone on the Claude Code backend: notes_service (TypeScript, node:http plus zod) bootstrapped by scio new (the planner chose node-ts from the stack menu) and built through M1 (three features, one advisor escalation, npm install through the install phase, eslint, tsc typecheck and build, npm audit and black-box acceptance all green, merged locally), $4.61 estimated, nothing billed; the done criterion of issue #51 holds on the Fake and live. Open: the install phase leaves package.json and package-lock.json changes uncommitted (I-085).
  • M10 Second stack (issue #51, ADR 0014): a node-ts toolchain profile (configs/profiles/node-ts.yaml, TAP parsers in scio/toolchain/node_ts.py): Node 22 runs TypeScript directly, node --test is the runner, tsc, eslint and npm audit the quality bar (skipped while absent), npm install the install phase; one data-driven ProfileToolchain loaded from yaml with a StackParsers set per stack; protocol members for the product path (acceptance_dir, skeleton_command, command_words, app_target, syntax_check_argv, health_probe_argv, detect); Runtime generalised (env_dir, env_marker, optional create step and interpreter); profile detection from marker files (Settings.toolchain=auto is the default, RunContext.adopt_toolchain on the clone, the product load and the bootstrap); a node-ts scaffold (TypeScript walking skeleton with node:test smoke and acceptance tests, eslint flat config, CI with setup-node); the normaliser, acceptance runner, run_app, tool descriptions and Claude Code allow-rules speak the profile's language; the toolbox context's toolchain reaches edit_file and run_tests, and edit_file runs the profile's syntax check (module.stripTypeScriptTypes for TypeScript, I-083); planner prompt v2 lists the available stacks; resolve_command finds npm's .cmd shims on Windows (I-081). The Fake todo_api spec builds its first milestone in Python and in TypeScript (test_same_spec_builds_in_both_stacks); CI installs Node 22 for the Node-dependent tests.
  • M9 (issue #49), first slices: delete_file tool on every sandbox backend (Sandbox.delete; the coder and debugger have it; a new file rejected by the edit lint gate is now removed instead of left empty); the python profile declares a quality bar (checks: coverage with an 80% floor, wheel build, dependency audit) that integrate runs after the suite and lint, reporting a check whose tool is absent as skipped and failing the milestone on a real failure; coverage artifacts added to the profile's cache excludes; the Claude Code worker backend now refuses a non-local sandbox.
  • M9 runtime (ADR 0013): a per-product environment (.scio/sandbox/venv, a plain venv with SCIO's own environment linked through a .pth file on a local sandbox, the profile's test_tools installed on any other, I-074) created by the install phase with the network open for that call only (Sandbox.exec(network=True)) and the approved dependencies from PRODUCT.md installed; install_deps worker tool gated by that list (an unapproved package is refused with the escalation hint; context-aware tools via ToolDef.needs_context / ToolBox.context); run_app starts python -m <module>, waits for a local health URL or the exit, and stops it (local sandbox only); the python profile's runtime: block.
  • M9 live milestone on the Claude Code backend: bookmarks_api (http.server plus pyyaml) bootstrapped by scio new and built through M1 (four features, one advisor escalation, black-box acceptance against the started server, coverage passed, merged locally), $5.38 estimated, nothing billed; the done criterion of issue #49 holds on the Fake and live.
  • M9 Docker default (ADR 0013 decision 10): scio build runs in Docker when a daemon answers and the docker/sandbox.Dockerfile image (Python plus git) is there, and in the local sandbox otherwise or on the Claude Code worker backend, with the first ledger line saying which and what a local sandbox does not enforce (SCIO_PRODUCT_SANDBOX_BACKEND=auto|local|docker). DockerSandbox is one persistent container per sandbox on an internal network (no route out), python rewritten to the product environment, a timeout inside the container keeping it; exec(network=True) attaches an egress-proxy sidecar (scio/aci/sandbox/egress_proxy.py, CONNECT-only, Limits.network_allowlist) for the duration of the call, so the install phase reaches the registry hosts and nothing else. run_acceptance starts an http product inside a non-local sandbox and probes it from inside. CI gains the docker-live job that exercises all of it on the runner's daemon.
  • M9 acceptance (ADR 0013): PRODUCT.md gains a ## Runtime section (kind: cli|http, module, start arguments with {port}, health path) that the product planner fills and the normaliser checks; the scaffold ships tests/acceptance/ (black-box: a subprocess for a CLI, the health endpoint for an http product, which the scaffold now serves with serve --port); integrate starts an http product on a free port, runs the acceptance tests with APP_URL, stops it, and reports [acceptance] beside the other checks. The scripted Fake product todo_api (an http server with pyyaml on its approved list) runs through the whole milestone loop offline: install phase, two features, server started for the black-box tests, merge. The scaffold's test directories are packages, so unit and acceptance tests may share basenames (I-073).
  • Claude Code backend (ADR 0012, issue #47): SCIO's model work can run through the unmodified claude binary on the owner's Claude subscription instead of the Messages API. SCIO_PROVIDER_OVERRIDE=claude_code sends every tool-less role through ClaudeCodeProvider (one restricted, tool-less claude -p per call, --json-schema for structured outputs); SCIO_WORKER_BACKEND=claude_code sends every tool-using turn through ClaudeCodeWorker (one stream-json session in the sandbox root with per-role --allowedTools, then a typed summary on --resume), with the transcript rendered in the shape scio report reads and the usage folded into the ledger and budget by Harness.account. Verify, commits and the gate are unchanged. scio/loop/backends.make_worker chooses the backend at every worker call site; SCIO_CLAUDE_CODE_BIN names the binary.
  • On the claude_code backend every tier cap in budgets.yaml is scaled by SCIO_CLAUDE_CODE_BUDGET_FACTOR (default 4.0, the measured ratio of Claude Code's estimate to the API price, I-069); the binary's own budget stop is SCIO's graceful budget exit; a claude -p run that fails without a message is retried (I-068); over-long prose fields in a typed summary are trimmed rather than failing the turn (I-070). scripts/nightly_live.py --provider claude_code runs the nightly suites on the subscription, one trial at a time.
  • scio build --product DIR [--gh owner/name] [--decision "<text>"] and scio status --product DIR (Product Mode M8, ADR 0011): the milestone loop. The orchestrator takes the first open feature of PRODUCT.md; an Opus milestone_planner groups up to four into a milestone with a tier each (normalised to a consecutive prefix); a GitHub milestone and one issue per feature are created idempotently by title (offline: files under .scio/product/issues/); each feature runs through the task graph as a subgraph on its own checkpoint thread (build-<product>-<pk>-a<attempt>) on branch milestone/<n> with the tier pinned and its own budget; the profile's full suite and lint run on the branch; an Opus milestone_gate verdict that any failing check overrides; one milestone PR (cost, escalations, plan versus done, Closes #n) stops for the human merge; progress.json and NOTES.md are updated on main and the loop continues. A crash between features or after the PR resumes with no duplicated issue, commit or PR; a feature that halts stops for one decision (retry, skip, stop). merge and stop records the merged milestone and ends the thread; build threads are named per starting milestone (build-<product>-m<n>) and scio build starts a fresh one once the previous ended. New state ProductBuildState, FeatureRun, MilestonePlan; GitHubClient.ensure_milestone, ensure_issue, find_issue, pr_merged; Harness.child; scio report renders a product view for build-* threads; the product graphs are registered diagrams in ARCHITECTURE.md.

Changed

  • After scio new every feature in progress.json is todo, the walking skeleton included: the scaffold proves the toolchain and P1 is verified by its own feature run (ADR 0011 decision 1, the M7 open question).

Fixed

  • The local sandbox no longer sets RLIMIT_AS on POSIX: it capped virtual address space, which V8 reserves by the tens of gigabytes, and Node's TypeScript stripper died with "Cannot allocate Wasm memory" on CI (I-084); the CPU-time and wall-clock limits stay, and Limits.memory_mb is enforced by Docker.
  • On the Claude Code backend a --json-schema answer is a StructuredOutput tool call that Claude Code bounces with a schema error when it misses the schema; with --max-turns 1 the model had no turn to retry and the first live http milestone crashed error_max_turns in the explorer's summary (I-077). Schema calls (worker summary, provider structured) get three turns and a capped summary is re-asked once with the required keys named.
  • scio new --thread X --decision ... without --dir continued in a default directory instead of the one the thread was started in, so the first live http bootstrap landed under .scio/products/ (I-076); the resume now reads the recorded directory from the checkpoint and reports an ignored --dir.
  • The product environment exposed the base interpreter's packages (--system-site-packages), so CI's runner had no pytest inside it and every Fake product build stalled there while the dev machine passed (I-074); see Added. Windows Application Control blocks the venv's pytest.exe and scio.exe launchers on the dev machine: python -m scio exists now and CLAUDE.md uses the module forms (I-075).
  • scio new ran the interviewer and the product planner twice and approved a draft the human never saw: a node re-runs from its start on resume, and both nodes made their model call and interrupted in the same node (I-065, found by the first live run after M8). The stops are now their own nodes (answers, approval) reading the draft from state; a Fake test with a planner whose draft changes every call guards it.
  • Verify's "something changed since the base commit" check read git diff --stat, which ignores untracked files, so a feature delivered only by new files stalled as "no changes" (I-063); diff_stat lists untracked files and the full diff stages them with git add -N.
  • uv.lock recorded the project at 0.3.0 after two releases (I-062); relocked, and test_version.py now checks the lock.