Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ On a release, the maintainer moves the accumulated `[Unreleased]` entries into a

## [Unreleased]

- **chore(license-apache-2.0)** — Add the Apache License 2.0, an RNT56/NilCore NOTICE attribution, and README license badge/section. _Owns:_ `LICENSE`, `NOTICE`, `README.md`, `CHANGELOG.md`. _(docs)_

- **chore(e2e-audit-remediation): full end-to-end audit → fix every finding, then adversarially review the assembled diff.** A 17-subsystem Opus audit (each MEDIUM+ finding re-verified by 1–2 refute-by-default skeptics; 7 refuted) surfaced **0 CRITICAL, 26 confirmed findings (2 HIGH)** against `main`; all are fixed here, each with a discriminating test. **HIGH:** (1) the OpenAI/OpenRouter SSE assembler silently swallowed an in-band `data:{"error":…}` frame (and an EOF-without-`[DONE]` carrying no content) as a nil-error empty/partial success, defeating retry/failover — it now surfaces a typed, retryable-vs-terminal-classified `*model.APIError` like the Anthropic path; (2) an unvalidated SKILL.md frontmatter `name` became the `skill_<name>` API tool name, so one malformed installed skill 400'd EVERY model call of every run — the name is now sanitized/validated at load, the `Defs()` boundary skips+warns any tool violating `^[a-zA-Z0-9_-]{1,64}$` (legit builtins unaffected), and `registry.InstallSkill` validates at install. **Confirmed clusters fixed:** *silent-failure bugs* — `scheduler.Submit` deadlock on >1024 tasks submitted pre-Start (→ unbounded cond-queue, FIFO/bounded-concurrency preserved); a swallowed `wt.Commit` fault stranding a verified green shard as a false-green (→ surfaced not-done); `resilience.Stream` double-paint across a retry (→ concat(forwarded)==returned invariant preserved); the MCP `Manager` single-flight binding the shared connect to one caller's ctx and poisoning a concurrent peer (→ detached connect ctx). *Dead-as-advertised closed-loop features* — trusted-preset Deploy auto-approval unreachable; chat `/apply` trust recorded under the source branch but gated on the target (→ same scope); `exp_config_standing` never written; `experience -class` keyed under `class=""` (→ real class, warm==log); `selfimprove.Scope` advisory-only (→ execution-time fail-closed scope screen at the gate + the flywheel path); `super` MaxFanout counting cumulative-not-concurrent (→ outstanding decremented/folded); `-blast-radius` wall fence unenforced on the DEFAULT Linux namespace backend (→ wired via a build-tagged helper). *Invariant edges* — the read-path final-component symlink TOCTOU across read/edit/editchecked/format/patch (→ `worktreefs.ReadConfined` O_NOFOLLOW, false hardening comment corrected); `maint.RotateLog` overwriting a hash-chained generation (→ lossless multi-generation, I5); macOS keychain `Set` leaking the secret on argv (→ off-argv); MCP `Headers` promising host-side secret resolution no code performed (→ `{{secret:NAME}}`/`{{env:NAME}}` resolved via the SecretStore, unresolved = hard error; descriptors relocated out of the operator's checkout). *Perf* — `vcache` O(n²) full-log re-verify + append-on-hit (→ memoized, side-effect-free hits, still chain-sound); `graapprove` trust rebuild rescanning the whole log per gate (→ incremental). *Code-intel* — the graph bare-name node collision (Run/New/Close clobbering across files) → a full qualified-id migration (`NodeID`/`SplitID`/`DisplayName` + a name→qualified resolution layer, every consumer — retrieve/impact/repomap/live/navutil/readsymbol — updated, with a same-name-no-clobber regression test); the embedder hardwired to api.openai.com (→ `NILCORE_EMBED_BASE_URL`); the semantic index mixing vectors across embedding models (→ model+dimension-keyed cache). **Contract/infra/docs:** `make verify` now runs golangci-lint (the dogfooded gate matches CLAUDE.md §4 + CI); the `-race` lane gained model/meter/mcp/trace/trust/graapprove (their `*Race*` tests stop being tautological); a new CI job runs the CONTAINER-sandbox I4 confinement+egress tests under `NILCORE_SANDBOX_MUST_RUN` (the primary sandbox boundary had zero regression protection); `tui-verify` now covers the swarm-board + trace tui code; releases publish per-binary SHA-256 + a SHA256SUMS and the installer verifies before installing (fail-closed); a hermetic model-free native-loop convergence smoke test proves the core loop in CI; doc drift fixed (the non-existent `nilcore run` in SELFACC/ARCHITECTURE/CLAUDE, the vestigial `nullclaw` `docs/.gitignore`). **Then a 12-slice adversarial review of the ASSEMBLED diff caught 8 confirmed second-order regressions the tests missed** — all fixed: a `mkdirAllNoFollow` boundary fallback that could still FOLLOW an attacker-swapped in-worktree symlink out of the tree (I4 escape — reproduced, then closed by canonicalizing root AND target in one symlink-space); the graded auto-approval `$` meter denying everything under the default `-blast-radius off` because it charged cumulative run spend as one action's cost (→ per-day metering against `MaxDollarsDay` seeded from the durable log, `min(clause, blast dayCeil)` when a budget is present, structural main/prod/release denials intact); repomap PageRank dropping ALL call edges post-migration (raw `Edges` vs resolved `CallEdges`); the macOS `ConfigDir` move orphaning an existing secrets vault on upgrade (→ reverted to the stable Application Support home, mint-a-fresh-key data loss averted); `route.Race` loser-cancel making the winner nondeterministic (→ index-aware: a passer cancels only strictly-higher indices, so the lowest-index passer always wins); a chat stdin close-on-ctx racing `os.ErrClosed` into `fatal()` on a clean Ctrl-C (→ mapped to a clean end). A ninth (lowering the high-entropy redaction floor to mask bare hex) was applied then REVERTED when it proved to also mask the audit log's own content/chain/cache-key hashes — breaking the verify cache (a cached-green test surfaced it); the belt's comment now documents why context-free hex is deliberately not masked (keyed hex secrets are still caught by the prefix rules). `make verify` (119 pkgs, lint-inclusive) + Linux cross-build + the expanded `-race` lane + a fully-uncached `go test ./...` all green. _Owns:_ repo-wide — `internal/*`, `cmd/nilcore/*`, `.github/workflows/*`, `Makefile`, `scripts/install.sh`, `docs/*`. _(audit remediation)_

- **feat(upgrade-program): execute the judge-ranked upgrade program — 17 items across 5 waves (dormant loops · context lifecycle · verification latency · swarm DAG completion · delivery loop + gate evidence + sandbox hardening).** A 9-lens, 3-judge analysis over the whole tree (58 scored proposals) found the recurring shape "the system records what it never consumes and builds what it never wires"; this executes the top-ranked program. **Wave 1 — wire the dormant loops:** the Anthropic adapter now emits the **3 prompt-cache breakpoints** (system block-array, last tool, moving last-message marker; Complete+Stream shared; ≤4-bound respected) whose 0.25x read pricing the meter always accounted for — and activating it exposed a REAL dormant bug: Anthropic reports *disjoint* usage tallies while the pricer assumes totals, so a live cache would have massively under-billed; `toModelUsage` now folds `input+cache_read+cache_creation` (test-pinned). The **lessons last mile** is closed — `memory.TaskContext` merges ScopeProject + ScopeGlobal (where the distiller writes) under one newest-first budget, so the agent finally sees its own scars; **race escalation** threads the failed attempt's fail-class + fenced verifier tail into each candidate's `Constraints` (the most expensive escalation no longer starts blind); **`final_verify` is class-tagged and folded into the trust ledger** alongside `race_outcome` (skip-not-panic guards; pre-upgrade logs replay byte-identical) so per-class routing warms on single-backend deployments; **`read` gains {offset,limit} paging + a 48KB cap** with a recovery-teaching notice and the mcp result is capped at the shared fence seam. **Wave 2/3 — context lifecycle + verification latency:** the native loop bounds shell/registry output (head 2KB + tail 6KB backstop; self-bounded tools exempt), records structured edits in the advisor trail, handles `max_tokens` (16384 default cap, `textBlocks()` salvage + harness re-emit turn + `json.Valid` belt — a truncated tool call no longer spins the nudge), injects a one-shot budget wrap-up signal, prepends a **fenced repo map** (new bounded `repoMap` walker behind the `RepoContext` seam) and **compacts in-run** (`CtxWindow` from the meter's window table; `msgs[0]` kept byte-identical to preserve the cache prefix; pairs never split; tool bodies excluded from summaries — I7; context-overflow 400 ⇒ compact-once-retry instead of losing the worktree; events `truncated_turn`/`budget_wrapup`/`loop_compact`). **`NILCORE_VCACHE` flips default-on** (kernel-cutover pattern, `=0` hatch) killing the pure-waste 2x verify on every success; a **FlakeProbe** decorator (test-class red + identical content hash ⇒ ONE real-verifier re-run; `verify_flaky` event) stops a coin-flip test from triggering an N-worktree race; a **TieredVerifier** (**opt-in**, `NILCORE_TIERED_VERIFY=1`) short-circuits in-loop RED via scoped `go vet`+`go test` of touched packages — armed ONLY for a full-module `go test ./...` command whose flags it replicates, short-circuiting ONLY a *provable* subset red (a package-load error falls through to Full); only the FULL verifier can PASS — I2 by construction; order `tiered(flakeprobe(vcache(base)))`. The `vcache→flake→tiered` chain is wired on every orchestrator path (run/serve/chat/resume), not just build/swarm, so a green run pays ONE full verify (not two) and a flaky final verify is re-probed once before any N-worktree race. **Wave 4 — swarm DAG completion (extends #94):** `Shard.BaseRef` + dependency-aware base resolution (single dep ⇒ its verified branch; multi ⇒ integrated TipSHA, `super.depTip` pattern) with a bounded fenced claim-status+summary handoff — DAG edges now buy the dep's CODE, not just ordering; **merged-set tracking** stops the every-pass re-merge spam and a **conflict requeue** rebuilds a conflicted-but-green shard on the integrated tip under the requeue Ledger; **termination honesty**: `Outcome.Unmerged` folds into `Remaining` so a silently-dropped green can never exit 0; **evidence-carrying focused requeue** (red keeps its branch; retry continues from it with red claim ids + verifier detail in the goal); fixed a latent blocker (attempt-branch name collisions made ANY shard retry fail at the worktree cut — now uniquely suffixed) and armed the always-zero requeue budget via `--retries` (default 2). **Wave 5 — delivery + gates + sandbox:** verified chat/run drives **keep their branch** (the front door no longer verifies work then deletes it) with `/diff` preview and `/apply` merging through the EXACT structured PromoteToBase gate (maint caps kept branches; WorkState survives restarts); **every attended gate shows evidence** — `policy.GateEvidence` (diffstat + bounded head-biased excerpt + verify tail with verdict line + spend, redacted at construction) rides `GateAction.Evidence` through the existing StructuredApprover seam, mirrored to `emit.GatePrompt`, rendered on console/plain-writer/styled-REPL/TUI/Slack/Telegram, with legacy flat approvers byte-identical (pinned) and the graapprove fall-through forwarding the FULL action (11 sites; previously every graded fall-through flattened to one line); the **namespace sandbox masks operator credentials** before Landlock — vault dir + `~/.ssh`/`.aws`/`.gnupg`/`.netrc`/`.config/gh`/`.docker/config.json`/`.codex`/`.claude*` (ro tmpfs over dirs, `/dev/null` over files, fail-closed 126, worktree-shadow exclusion) — closing the in-box vault-decryption I3 hole. New Native seams are all nil-safe (unset ⇒ byte-identical); ARCHITECTURE records the vcache default flip, the verify-decorator composition, and the masking rationale. An adversarial pre-PR review (7 risk-targeted lenses × refute-by-default verification, 36 agents) then found and fixed **25 confirmed defects (4 HIGH)** — a mid-tool_use stream EOF that poisoned the request history and killed the run (now sanitized before the turn is recorded); `finish_reason:"length"` never mapping to the max_tokens salvage on OpenAI-family providers; the tiered scoped-red shipping false reds as the verdict (⇒ made opt-in + provable-subset-only, above); a no-op green shard (nothing to commit) misclassified as a merge conflict and burning the run to a false exit-1 (⇒ integrate treats an already-contained branch as an idempotent merge); an **I7 break** where model-authored claim ids/fields rode UNFENCED into a dependent shard's goal (⇒ sanitized + fenced); a skipped DAG dependent silently dropped while the run reported Done=true (⇒ skipped dependents are tracked, re-run when their dep greens, and a termination-honesty backstop forbids a false green); `/apply`'s graded gate scoping the source branch so the never-auto-approve-main floor never saw `main` (⇒ scope is the merge target); `/diff`+`/apply` silently dead on the TUI/serve front doors (⇒ real handlers / explicit replies); an EACCES stat on a root-owned `~/.docker` bricking the whole namespace sandbox (⇒ skip-not-fail, since the command shares the uid); and `~/.git-credentials` missing from the credential mask. Each fix carries a discriminating test; `make verify` + `tui` + `golangci-lint` + `-race` re-green after remediation. `make verify` (119 pkgs) + `tui` build + `golangci-lint` + `-race` green. _Owns:_ `internal/{provider,memory,agent,trust,tools,verify,sandbox,swarm,backend,policy,emit,session,channel,termui,graapprove,maint,worktree}`, `cmd/nilcore/*`, `docs/ARCHITECTURE.md`. _(upgrade program)_
Expand Down
Loading
Loading