What this is: a capability comparison between Powernode's autonomous-loop / campaign substrate and the external "Loop Engineering" framework popularised by Codez (@0xCodez, 9 Jun 2026 — "Loop engineering: the 14-step roadmap from prompter to loop designer").
Why: the article codifies the industry shift "from typing prompts to designing the loop
that prompts." Powernode is, in effect, a productised version of exactly that thesis
(Ai::RalphLoop, Ai::Campaign, the /dev-loop + /improve + /campaign harness). This
doc maps the framework point-by-point onto what actually ships in this repo, so we can see
where we are ahead, at parity, or have a real gap — and drive the gaps as a
campaign.
Audit-only artifact. No code changed to produce it. Findings are tracked for closure by the Loop Engineering Parity campaign (see Driving the gaps).
Date: 2026-06-29. Branch: develop. All file references verified against the working tree.
Related platform knowledge: "Loop-engineering pattern catalog (2026)" (019eb378-a423-740f-855f-dc2f5f7c1268)
already maps the external loop canon (Ralph / evaluator-optimizer / plan-execute-verify / ReAct)
onto Powernode primitives; this doc is the gap-focused companion to it.
Powernode has built nearly the entire framework, and in places exceeds it (DB-backed state
beats flat JSON; ~540+ MCP tools; skill evolution/composition; per-campaign worktrees with
isolated test DBs). The systemic weakness is the same one the framework warns about hardest and
that our own learning 019ed4db already names: the verification gate is opt-in and off by
default, so the default loop path fabricates checks_passed: true — the live "Ralph Wiggum"
failure mode. Beyond that, a whole cluster of gate/safety controls are off-by-default, inert, or
absent: the true-north metric (cost-per-accepted-change, never computed), the security
scan gate (scanners exist but aren't enforced on the autonomous land path), scope guardrails
(the risk-tier infra never blocks), runtime secret-scrubbing (loop output isn't scrubbed for
keys/tokens), lessons→loop feedback (write-only on the campaign path), and a readiness
preflight + gate-rot canary (both absent). The pattern is consistent and verified: Powernode
scores high on building blocks, low on gates — exactly the article's thesis that the harness
and its verification gates, not agent cleverness, are the bottleneck (see the
maturity scorecard).
| # | Framework idea | Powernode status | Gap |
|---|---|---|---|
| Block 1 | Automations (cadence + goal-driven heartbeat) | Cadence strong; goal-driven weak | G5 |
| Block 2 | Worktrees (isolated, auto-removed) | Ahead | — |
| Block 3 | Skills (write once, read every run) | Ahead (versioned/evolve/compose) | provenance G6 |
| Block 4 | Connectors (MCP) | Ahead (~540+ tools) | tracker/error connectors G8 |
| Block 5 | Sub-agents (maker/checker) | Built but off + not in loop | G3 |
| MVL | Automation → Skill → State → Gate | 3 of 4 strong; gate weak | G1 |
| State | Durable state files | Ahead (DB-backed) | — |
| State | Lessons fed back each iteration | Write-only on campaign path; promoted only at completion | G12 |
| Failure | Ralph Wiggum (fabricated completion) | Live by default | G1 |
| Failure | Goal drift (re-read base files each run) | Mostly absent (loaded once/session; decisions never re-injected) | G12 |
| Failure | Agentic laziness | Partial (no separate completion judge) | G3,G5 |
| Failure | Comprehension debt / cognitive surrender | Conditional — safe under default trusted; autonomous/core-mode auto-approves |
— |
| Failure | Gate rot (gates silently stop catching) | Absent | G11 |
| Safety | Scope guardrails (never touch payments/auth/arch) | Inert (RiskContract never blocks; hooks CLI-only) | G10 |
| Security | SAST + CVE + secret gate before merge | Tools exist, not enforced in loop | G4 |
| Security | Credential leaks in logs | Refuted — runtime loop output unscrubbed for keys/tokens | G15 |
| Security | 30-day token-scope audit | Missing | G7 |
| Governance | Loop-readiness preflight (4-condition pre-run gate) | Absent | G13 |
| Metric | Cost per accepted change (≥50% floor) | Missing (cost & lands never joined) | G2 |
The framework's cost machinery (Condition 3, the dollar true-north metric, token/cost caps)
assumes a metered plan. Powernode runs loops on two distinct runtimes, split by who
calls the LLM and who pays for tokens — the claude_code vs platform_* driver routing
(server/app/models/ai/ralph_loop.rb:18-22 DRIVER_KINDS;
server/app/services/ai/dev_loop/campaign_driver.rb apply_driver_routing! / delegate).
| Flat-rate CLI-executor loop | Metered platform-executor loop | |
|---|---|---|
| Driver kind | claude_code (see note) |
platform_agent / platform_team / platform_mission |
| Who calls the LLM | An external agentic CLI drains the dev-loop pull queue (dev_next_task/dev_complete_task); the platform calls no LLM |
The platform executor, on the account's provider keys |
| Examples | Claude Code, Grok CLI, OpenAI/Codex CLI, Gemini CLI — any MCP-capable agent CLI on a flat-rate plan | Platform-driven agents / teams / missions |
| Cost model | Flat-rate — marginal token cost ≈ 0 | Metered — real $ per token |
| Posture | Aggressive: more sub-agents, more verification passes, higher effort, parallel fan-out | Frugal: cost-aware, capped |
| Condition-3 (token budget) | Does not apply | Applies |
| True-north metric | Acceptance rate (anti-churn / human-review bandwidth) | Cost per accepted change (dollars) |
| Right hard-stops | Iteration limit + wall-clock timeout | + token/cost budget cap |
Note — the distinction is the cost model, not the vendor. The pull-queue bridge (
dev_next_task/dev_complete_task) is MCP-client-agnostic, so any flat-rate agent CLI (Claude Code, Grok, Codex, Gemini, …) is a flat-rate executor. The code currently labels this driverclaude_code, a misnomer once non-Claude CLIs drive loops — see G9.
Therefore: the verification gate (G1) applies to both runtimes and matters more
on aggressive flat-rate executor loops — when you take liberties with tokens, the gate is the
safety, not the budget. The dollar parts of G2 and the token/cost caps in G5 are
metered-platform concerns; flat-rate executor loops instead need an acceptance-rate floor and
iteration/wall-clock stops. (This runtime split refines the raw configuration.gaps titles on the
campaign — treat this doc as canonical.)
| Condition | Powernode |
|---|---|
| Task recurrence (weekly+) | ✅ Campaigns exist precisely for open-ended, self-refilling work (docs/contributing/conventions/autonomous-campaigns.md). |
| Automated verification (objective gate) | |
| Token-budget absorption | Runtime-specific (see Two runtimes). Irrelevant for flat-rate CLI-executor loops; for metered platform_* loops cost/tokens are recorded per iteration (iteration_execution.rb:173-177) but no hard cap stops a loop on spend (G5). |
| Agent senior tooling (logs, repro env, runtime exec) | ✅ Container logs, sandboxed test execution, instances, docker exec — strong. |
- Cadence loops — strong.
Ai::RalphLoopscheduling_mode ∈ manual|scheduled|continuous|event_triggered|autonomous(server/app/models/ai/ralph_loop.rb:16); cron / fixed-interval / duty-cycle viaschedule_config(server/app/models/concerns/ai/ralph_loop_concerns/scheduling.rb). Harness/loopmirrors it. - Goal-driven loops — weak. The only automatic terminator is "task queue drained" (
all_tasks_completed?,.../ralph_loop_concerns/task_and_learning.rb:18-22).completion_assessment(dev_loop_tool.rb:483-498) evaluatesconfiguration.completioncriteria but is report-only — no explicit goal predicate, and no separate model judges "done." → G5.
scripts/prepare-worktree.sh (isolated worktree + offline submodules + per-worktree test DB via TEST_ENV_NUMBER), models Ai::Worktree / Ai::WorktreeSession, git ops server/app/services/ai/git/worktree_manager.rb, branch-per-campaign (campaign/<id>), and auto-cleanup worker jobs (ai_worktree_cleanup_job.rb, …_timeout_job.rb). Exceeds the framework's baseline (isolated DB per tree).
Ai::Skill is versioned + DB-persisted (server/app/models/ai/skill.rb): system_prompt + commands + declarative recipe + attached KB/MCP servers. Create / evolve / auto-evolve / compose / mutate / health / attach all exist (server/app/services/ai/skill_graph/*, …/self_improvement/skill_mutation_service.rb, …/missions/skill_composition_service.rb). Real SKILL.md dirs exist in the harness (.claude/skills/*/SKILL.md).
- Gap — provenance / injection audit. No
provenance/trust_level/signaturecolumn onai_skills;SkillService#create_skill|update_skill|assign_to_agentpersist/attachsystem_promptverbatim with no content scan.trust_tier_at_proposalonly auto-approves internal proposals (ai/skill_proposal.rb:77); communityverifiedis a manual flag on agents, not skill content. → G6.
Genuinely MCP-native: full stack under server/app/services/mcp/*; ~540–561 tools (docs/reference/auto/mcp-tools.md, server/app/services/ai/tools/platform_api_tool_registry.rb). External connectors: Gitea (16 tools), chat/notify (Slack/Discord/Mattermost/Telegram/WhatsApp adapters), databases/APIs (data_source_*, 29 tools, incl. data_source_provenance).
- Gaps vs named set: no Linear/Jira issue-tracker connector; no Sentry/error-tracker connector (GitHub → we are Gitea-native instead). → G8.
The pattern exists in real code: server/app/services/ai/reasoning/output_evaluator_service.rb (separate, independently-modeled evaluator → pass|revise|reject), the revise loop in agent_tool_bridge_service.rb:342-366, reviewer-as-different-agent with an explicit self-review ban (ai/team_authority_service.rb:187-200), and per-agent model tiers (ai/agent_model_selector.rb:38-46).
- Gap: it is opt-in (default off) and, per the loop audit, not wired into the Ralph/dev-loop/campaign completion path —
Ai::Learning::LlmJudgeServicejudges knowledge quality, not task completion. Maker-checker survives in the loop only as advisory prompt text ("don't trust green alone",campaign_driver.rb:13-14). → G3.
| Part | Powernode | Status |
|---|---|---|
| Scheduled automation | Ai::RalphLoop scheduling |
✅ |
| Targeted skill | Ai::Skill / harness SKILL.md |
✅ |
| Durable state file | Ai::ProgressEntry + Ai::CampaignDecision + Ai::ParkedQuestion (DB-backed; replace the old ~/.claude markdown) |
✅ ahead |
| Automated gate | Ai::Ralph::TestVerificationService + sandbox AiTestExecutionJob |
State models (the framework's last_run / counters / in_progress / lessons_learned):
progress_entry.rb (snapshot counters + per_loop_summary/improvement_metrics),
campaign_decision.rb (typed decision log + rationale), parked_question.rb
(open→answered, reopens blocked tasks). DB-backed > flat JSON.
Caveat (G12): the lessons_learned half of the framework's state file is write-only on the
campaign path — per-iteration learnings land in a JSON column that dev_next_task never re-reads,
and they reach the embedded/searchable store only at loop completion (state_machine.rb:59),
which for a 500-iteration campaign effectively never fires mid-run. So the state counters are
ahead, but the lessons feed back into the loop is broken.
This is the central finding. The default loop path fabricates the verification flag:
server/app/services/ai/ralph/task_executor.rb:561&:189—checks_passed: truehardcoded on any successful agent run.server/app/services/ai/tools/dev_loop_tool.rb:300-306—record_outcometakes pass/fail from the agent's ownoutcomeparam and setschecks_passed: true.- The loop then trusts it:
iteration_execution.rb:183-189→task.pass!.
The real gate exists — Ai::Ralph::TestVerificationService (its header literally calls itself "the replacement for the autonomous loop's fabricated checks_passed: true") runs the suite in a sandbox (worker/app/jobs/ai_test_execution_job.rb) and resolves the task from the real exit code (internal/ai/ralph_loops_controller.rb:97-138). But it only fires when ralph_loop.real_test_execution? is true, which requires configuration["real_test_execution"]==true and a configuration["test_command"] (ralph_loop.rb:103-109) — off for every loop by default, including all campaign and /dev-loop loops.
Our own learning 019ed4db already records this verbatim: "never from the loop's self-reported checks_passed (trusted verbatim, thus gameable)" — mitigated so far only by the RalphTask.improvement_scoreboard revert-rate signal, not a real test gate. → G1.
The framework's mitigation is re-reading base structural files every iteration. Verified: on the campaign path the executor payload (dev_loop_tool.rb:446-465) carries only task details + branch/guardrails — it never re-injects CLAUDE.md/conventions or Ai::CampaignDecisions, and CLAUDE.md is loaded once at CC session start, not per /dev-loop iteration. (The platform-driven path re-injects recent_learnings via iteration_execution.rb:121 but also not base files/decisions.) My earlier "partial — SessionStart digest" was too generous. → G12.
No batch-approve surface exists (zero *_approve_all; every approval is single-id) and the land queue is serial (landing_queue.rb:14 MAX_ACTIVE_PER_TARGET = 1), so auto-discovered changes cannot be bulk-waved-through — and under the default trusted authority each land stays pending_approval for one-at-a-time human review (land/approval_binding.rb:45). But the comprehension gate vanishes in three cases: autonomous authority auto-approves each land (approval_binding.rb:82-88), mission lands always auto-approve, core-mode (no governance extension) auto-proceeds (approval_workflow_service.rb:35), and the branch-protection merge is self-approved by the land (land_service.rb:53-54). So: holds by default, absent in the autonomous/core-mode path.
| Defense | Powernode | Status |
|---|---|---|
| Blocking SAST + dep-CVE + secret scan before merge | Scanners exist — gitleaks (optional local pre-commit, scripts/install-git-hooks.sh), Brakeman (GitHub-only server/.github/workflows/ci.yml:24), supply-chain CVE/SBOM/sign/policy-gate step handlers (worker/app/services/devops/step_handlers/*, prod copies in optional extensions/supply-chain/) — but none run in the campaign land/merge path. Ai::Land::LandService leans on "post-merge CI + auto-rollback" (land_service.rb:12-13), and the Gitea land workflows run no security scans. |
|
| Audit external skills | No skill content/provenance audit | |
| Prevent credential leaks in logs | Refuted at runtime (on re-verification). CLAUDE.md crypto-safety stops the human/CLI emitting keys, but the autonomous loop's own output is unscrubbed: the runtime sanitizer (data_management/sanitizer.rb:8-75) matches only PCI card data (no API-key/token/secret/env regex), the global log formatter calls sanitize_string not sanitize_hash (pci_compliance.rb:54), agent/loop output is persisted raw (iteration_execution.rb:162, campaign_driver.rb:218), and the worker that runs the loop has no sanitizer at all. |
|
| Audit API-token scope every 30 days | Only expiry/reaper jobs (worker/config/sidekiq.yml); ai_provider_credentials.access_scopes stored but never reviewed for over-provisioning |
The framework's single most important metric. Powernode tracks both halves but never joins them:
- Cost lives at the agent-execution grain (
ai_agent_executions.cost_usd/tokens_used) and rolls intoAi::RoiMetricascost_per_task_usd— but that divides by completed tasks, not accepted ones (server/app/services/ai/analytics/cost_analysis_service/roi_analytics.rb:65). - Acceptance lives separately on
Ai::CampaignLand(landed | rejected | rolled_back,server/app/models/ai/campaign_land.rb) — and that table has no cost/token column, so a human-approved merge is never tied to the spend that produced it. Ai::Campaigncounters aretotal/completed/failed/blocked_tasksonly — no cost, no accepted count, no acceptance rate, no net-loss guard.
→ G2.
Ordered by priority. Each is STAGE-only, test-first, individually approved.
G1 — Make the real verification gate the default (kill Ralph Wiggum). [High]
Stop hardcoding checks_passed: true; default real_test_execution on (or required) for campaign/dev-loop loops with framework auto-detection (TestVerificationService already detects rspec/pytest/jest/go/cargo), and fail-closed when no objective gate can run. This is the framework's #1 mitigation and our own flagged weakness (019ed4db).
G2 — Acceptance-rate floor (both runtimes) + cost-per-accepted-change (metered loops). [High]
Compute an acceptance rate from accepted Ai::CampaignLand records vs attempts and add a stop_conditions.min_acceptance_pct (default 50%) net-loss guard — this applies to both
runtimes (anti-churn). Separately, for metered platform_* loops only, join token/$ cost to
accepted lands and surface "cost per accepted change." For flat-rate CLI-executor loops the dollar
figure is not the optimisation target — acceptance rate is.
G3 — Wire maker/checker into the loop. [Medium]
Apply the existing OutputEvaluatorService / review_workflow_service (separate verifier model, self-review ban) to the Ralph/dev-loop task-completion path, not just general agent execution; add a first-class "cheap-explore / strong-verify" preset.
G4 — Security gate on the autonomous land path. [Medium-High] Wire secret-scan (gitleaks) + SAST (Brakeman) + dep-CVE (supply-chain handlers, via a generic seam — core must not depend on the extension) as a blocking gate before campaign land/merge.
G5 — Goal-driven completion + runtime-aware hard caps. [Medium]
Promote completion_assessment from report-only to an actual goal terminator. Enforce **iteration
- wall-clock timeout** stop-conditions on both runtimes. Enforce token/cost hard-caps on
metered
platform_*loops only (currently recorded but never gating) — leave flat-rate CLI-executor loops uncapped on tokens by design (be aggressive).
G6 — Skill provenance / injection auditing. [Low-Medium]
Add provenance/trust_level to ai_skills and an injection/content scan on create/update/attach, especially for any external/community import path. (Mirror the existing data_source_provenance.)
G7 — Periodic token-scope / permission-creep audit. [Low]
Scheduled job that reviews access_scopes on ai_provider_credentials (and API tokens) for over-provisioning on a 30-day cadence.
G8 — Connector breadth. [Low]
Add Linear/Jira issue-tracker and Sentry/error-tracker MCP connectors (the loop already has internal analogs via report_issue/escalate).
G9 — Generalise the executor-driver taxonomy (vendor-neutral). [Low]
The flat-rate executor driver is hardcoded as claude_code (server/app/models/ai/ralph_loop.rb:21 DRIVER_KINDS, claude_code_driven? at :90), but the dev-loop pull-queue is MCP-client-agnostic — Grok CLI, OpenAI/Codex CLI, Gemini CLI, etc. are equally valid flat-rate executors. Generalise to an external_cli / flat_rate_executor concept (with claude_code as a labelled instance) so non-Claude CLIs are first-class and per-vendor attribution/telemetry is possible. The mechanism already works; this is naming + telemetry, not unblocking.
The following were either under-weighted in round 1 or are corrections to claims I had marked "covered." All are code-verified.
G10 — Enforce loop scope guardrails (never touch payments/auth/crypto/architecture). [Medium-High]
The article's "Never touch src/payments/,src/billing/" control has no enforced equivalent. The
infra half-exists but is inert: Ai::CodeFactory::RiskContract tiers files (low…critical) but
PreflightGateService#evaluate returns passed: true for every tier including critical
(preflight_gate_service.rb:52-60); the loop-side hooks code_factory_preflight_check /
code_factory_evidence_satisfied? (ralph/execution_service.rb:28-62) have zero callers;
campaign "guardrails" are prompt text only (campaign_driver.rb:10-16 → dev_loop_tool.rb:459);
and core-purity/crypto checks run only as edit-time CLI hooks that don't fire on the
platform-executed path. Reuse-first fix: wire the already-built RiskContract/preflight to actually
block denylisted paths and critical-tier changes on the autonomous path (don't build new).
G11 — Gate-integrity canary ("gates rot over time"). [Medium]
No mutation testing / deliberate failure-injection exists (mutant/stryker/mutmut absent;
"canary" is deploy-only; "chaos" is an unused enum value). Add a periodic check that injects a
known-bad change to confirm the verification gate still fails closed — otherwise a silently-broken
gate (G1) reads as green forever.
G12 — Close the lessons→loop feedback (and re-inject base context each iteration). [High]
On the campaign path, per-iteration learnings are write-only to a JSON column dev_next_task
never re-reads, and reach the embedded/searchable store only at loop completion
(state_machine.rb:59) — so a long campaign never learns from itself mid-run. Also neither path
re-injects Ai::CampaignDecisions or CLAUDE.md/conventions per iteration (the goal-drift mitigation).
Fix: re-inject recent learnings + open decisions + base structural files into each iteration's
payload (dev_loop_tool.rb:446-465), and promote learnings to the compound/embedded store mid-run,
not only at completion. (This is the code-level root of the "stalled knowledge-feedback pipeline".)
G13 — Loop-readiness preflight (operationalise the 4 conditions as a pre-run gate). [Medium]
Loop/campaign start does no readiness validation — loop_lifecycle.rb:11-12 checks only
status + non-empty queue; the CodeFactory "preflight" is PR-risk and runs after execution. Add a
true pre-run gate that refuses/warns when the target has no automated gate, no runnable env, or
G1 verification is off. See Operating doctrine.
G14 — Codify the good-first-loop allowlist / keep-manual denylist as policy. [Low] The article is prescriptive: loop on CI-triage / dependency bumps / lint-fix; keep auth, crypto, payments, architecture, and subjective "done" manual. Codify this as a policy catalog that feeds G10's enforcement and G13's preflight, rather than leaving it to prompt text.
G15 — Runtime credential/secret scrubbing of loop & agent output. [Medium-High]
Correction to a "covered" claim. Extend DataManagement::Sanitizer with API-key/bearer-token/secret/env
patterns (today it's PCI-card-only), make the log formatter scrub structured output (sanitize_hash,
not just sanitize_string), sanitize agent/loop output before it's persisted
(iteration_execution.rb:162, campaign_driver.rb:218), and add a worker-side log formatter (the
worker that runs the loop currently has none).
(Framing chosen in addition to the engineering gaps: treat the article as operating policy, not just a feature checklist.)
The 4 conditions + 30-second checklist are only worth anything if a loop cannot start without
them. Today nothing enforces them at start (G13). Adopt them as a governance preflight
every campaign/loop must pass before it activates — fail → park_question!, don't run:
- Objective gate present — an automated test/lint/build is discoverable for the target, and real verification is enabled (G1). No gate → no loop.
- Hard-stops set — iteration + wall-clock for every loop; token/cost cap for metered loops (G5); flat-rate CLI loops stay token-uncapped by design.
- Scope in bounds — target is on the good-first allowlist and clear of the keep-manual denylist (G10,G14).
- Runnable env — the executor can run and observe the code (logs, repro).
- Approval posture explicit — for non-
autonomousauthority a human land-gate precedes merge; forautonomous, G15 scrubbing + G4 security gate are mandatory compensating controls.
This converts the article from a checklist we read into a gate the platform enforces — and it's the natural home for G13.
(Second chosen framing: a rubric to track over time, not a one-shot comparison.) Score per dimension: 0 absent · 1 built-but-off / inert · 2 partial / conditional · 3 enforced by default. Current state (2026-06-29):
| Dimension | Score | Note |
|---|---|---|
| Worktrees | 3 | isolated + auto-cleanup + per-tree test DB |
| Connectors (MCP) | 3 | ~540+ tools, real external connectors; G8 added an outbound issue/error-tracker seam (TrackerRegistry) with real native Linear (GraphQL) / Jira (REST) / Sentry clients (follow-up replaced the webhook scaffolding) |
| Durable state (counters) | 3 | DB-backed ProgressEntry/Decision/ParkedQuestion |
| Automations (cadence+goal) | 3 | G5 closed — completion_assessment is now a real goal_met terminator (cadence already strong) |
| Skills | 3 | G6 closed — provenance + trust_level on ai_skills; injection/content scan on create/update gates external content; untrusted skills blocked on attach |
| Comprehension/approval | 2 | conditional — default-safe, autonomous auto-approves |
| Hard-stops | 3 | G5 closed — iteration + wall-clock (both runtimes) + metered token/cost caps enforced via shared halt_reason/runtime_cap_reason; flat-rate stays token-uncapped by design |
| Sub-agents (maker/checker in loop) | 2 | G3 (wired) — OutputEvaluatorService composes into the loop completion path (opt-in maker_checker + preset + self-review ban); follow-up: now reviews the REAL scrubbed unified diff, not just output text |
| Verification gate (Ralph Wiggum) | 3 | G1 closed — real gate now default-on (opt-out), fail-closed, worker auto-detects framework |
| Lessons→loop feedback | 3 | G12 closed — recent learnings re-injected per iteration + each learning embedded mid-run (not only at completion) |
| Goal-drift mitigation | 2 | G12 (partial) — open decisions + base-context files re-injected into each dev_next_task payload; per-iteration base-file contents still a follow-up |
| Security scan gate | 3 | G4 closed + follow-up — server land gate (secret-scan on metadata) PLUS a worker-side deep secret-scan on the REAL staged diff (+ best-effort Brakeman) that parks autonomous lands; dep-CVE/SBOM via the SecurityScannerRegistry seam remains a follow-up |
| Runtime secret-scrubbing | 3 | G15 closed + follow-up — loop output scrubbed at server persistence, worker-posted output scrubbed on receipt, and the global log formatter now secret-scrubs (not just PCI) |
| Scope guardrails | 3 | G10 closed + follow-up — denylist + RiskContract critical-tier now BLOCK on ALL three paths (dev-loop completion, platform executor, land approval), sourced from the unified PolicyCatalog |
| Gate-integrity canary | 3 | G11 closed — daily GateCanaryService feeds known-good/bad through the G1 gate and alerts if it stops failing closed |
| Readiness preflight | 3 | G13 closed — pre-run gate blocks a loop with no objective gate; surfaces caps/env warnings |
| True-north metric | 2 | G2 closed — acceptance rate computed + floor enforced by default (both runtimes); cost-per-accepted surfaced (metered only). Report-only on the $ side keeps it at 2, not 3 |
Read of the scorecard (original 2026-06-29): building blocks averaged ~2.6/3; gates/safety averaged ~0.7/3. That spread was the finding — Powernode had the richest substrate and the weakest gates, precisely the failure mode the article warns about ("harness engineering > agent cleverness"). The campaign's job was to raise the bottom of this table.
Read after the campaign drain + follow-ups (2026-06-30): all 15 gaps closed, plus four follow-up increments (worker-side deep scan, platform/land-path enforcement, real-diff review, native tracker clients). Gates/safety now average ~2.7/3 (from ~0.7) — only Comprehension/approval, Sub-agents (opt-in by design), Goal-drift (per-iteration base-file contents), and True-north (cost-side gating) remain at 2, each for a deliberate-scope or low-value reason rather than a missing foundation. The substrate↔gates spread that was the finding is closed.
Progress (2026-06-30): ALL 15 gaps closed on the campaign branch (STAGE-only, not pushed), one commit per gap, each test-first with its own specs:
| Gap | Commit | Gap | Commit |
|---|---|---|---|
| G1 | 18abb8bf |
G9 | 56ba57aa |
| G2 | 13cdd0ce |
G10 | ff740702 |
| G3 | a4cc245b |
G11 | 77d522bb |
| G4 | 2ea67b90 |
G12 | 47470e01 |
| G5 | fb942d26 |
G13 | c1b8af6a |
| G6 | 6d4bfeb8 |
G14 | 741c9c69 |
| G7 | 2dfa2594 |
G15 | 6cf50f91 |
| G8 | 8b72f77a |
Deployed: the 15-gap branch was ff-merged to develop (83aa8a75) and deployed to the live
backend (G6 migration applied, restarted, health + functional smoke verified).
Follow-ups DONE (on feature/le-parity-followups, STAGE-only, off develop@83aa8a75):
cb180a62— G10 scope-guardrail extended to the platform-executor + land-approval paths; G15 global log formatter now secret-scrubs.b0c32777— worker-side deep secret-scan on the REAL staged land diff (+ best-effort Brakeman) parks lands; worker-posted output scrubbed on receipt. (dep-CVE/SBOM still a follow-up — needs the supply-chain extension; core must not hard-depend on it.)7195a804— G3 maker/checker now reviews the REAL unified diff (scrubbed, 256 KB cap, fallback).0644888e— native Linear (GraphQL) / Jira (REST) / Sentry tracker clients replace the webhook scaffolding.
Still open: dep-CVE/SBOM worker scanners (extension-gated); per-iteration base-file contents re-injection (Goal-drift); cost-side gating for True-north; one design call — the worker land-scan falls through to CI on a scan-infra error (findings still park; G4 server gate is the fail-closed backstop) — flip to fail-closed if preferred.
Increment ledger entries still pending — platform MCP was disconnected for the implementing
session, and a premature-finalization hazard (completion_pct:100 stop on a 0-seeded-task loop) would
auto-finalize the live campaign on the first recorded increment; record via MCP once reconnected, after
seeding/fixing the campaign. Pre-existing, unrelated test-double gaps (task_executor_spec ~3 and
ai_provisioning_compose_plan_job_spec ~4 — neither file touched by this work) are flagged separately.
These gaps are tracked by the Loop Engineering Parity campaign
(platform.campaign_*, decision authority trusted, STAGE-only). It drains G1→G15 in priority
order, one improvement per run, each individually approved. (The on-platform configuration.gaps
enumerates the round-1 subset G1–G8; this doc is canonical and supersedes it with G9–G15.)
Two leverage clusters:
- Make the loop trustworthy — G1 (real gate) + G2 (acceptance/cost-per-accepted): converts the loop from "trusts a fabricated flag, optimises throughput" to "gated on a real test run, optimises the right metric per runtime."
- Make it safe to walk away from — G10 (scope guardrails) + G12 (lessons + base-context feedback) + G15 (secret-scrubbing) + G13 (readiness preflight): the controls that matter most precisely because flat-rate CLI loops are meant to run aggressively and unattended. Per the scorecard, this is the cluster scoring lowest.