lab ʻIKEOS FIELD NOTES
← all posts

Week of August 21 — the Decision Council closes the loop

A Decision Council pipeline ships end to end, a component model surfaces years of quiet drift, and a whole-branch review earns its keep twice in one week.


What We Built

The big one: a Decision Council pipeline, shipped from vault schema to live dashboard widget in about three days. The problem it fixes has been visible for a while — the weekly platform review would surface recommendations, and they’d just sit there. Not rejected, not actioned, just unread, sometimes for weeks running. So now every recommendation becomes a real vault entry with its own lifecycle (pending-review → in-discussion → approved/declined/actioned), a “Discuss” button spawns a moderator session that voices the right two or three Decision Council personas for that specific item, and “Approve” kicks off an actual implementation in an isolated worktree. /platform-review — the old itemized-triage skill this replaces — got retired the same week.

Alongside that, we finally wrote down what IkeOS is. docs/COMPONENT_MODEL.md names the five pieces — Interface, Vault, Harness, Adapters, Self-Improvement — in one canonical place. Writing it surfaced something we hadn’t been tracking: the portable adapter reference (adapters/claude-code/) and the actual deployed harness (claude-config) had quietly diverged. A diff of one skill file turned up a missing fallback in the deployed copy that the adapter had and nobody had ported over.

That finding turned into its own project — a drift-consolidation pass with a real mechanism behind it, not just a one-time fix. adapters/claude-code/ is now the single source of truth; sync.sh generate regenerates the deployed copies with a “do not edit here” header, and check-drift.sh auto-heals both boundaries on every session start. Two passes landed this week (skills, then session-manager), and Pass 2 turned up an entire unmerged branch from three weeks earlier that had already done most of the work — recovered via a real three-way merge after a first fast-forward attempt correctly failed.

Smaller but real: PATCH /entries gained the ability to relocate a vault entry to a different project, closing a gap where 18+ entries had the wrong project name baked into their frontmatter with no sanctioned way to fix it.

What We Considered (and Said No)

We looked hard at Beads, a dependency-graph task tracker built specifically for AI agents — atomic claiming, blocking relationships, the works. Genuinely well-built for what it does. We’re not adopting it. The vault is deliberately human-owned; agents write through one gated door (the capture API), and Beads would mean standing up a second, agent-only source of truth right next to it. If multiple IkeOS agents ever need to coordinate on real interdependent work without collisions, this is worth revisiting. Right now that need doesn’t exist.

Inside the Council design itself, we killed an earlier idea that docs and config changes could auto-push without the same approval gate code changes get. It didn’t survive being argued out loud. Push to remote is now one universal boundary, no carve-outs by change type — every council-driven action, however small, waits for an explicit human click.

Challenges & How We Solved Them

The most interesting failure this week wasn’t a bug — it was where the bug hid from review. Every task-scoped review of the Council pipeline passed clean. Then the final whole-branch review caught two Critical issues that no individual review had: the new entry-relocation endpoint would have silently deleted entries under exactly the case-correction scenario its own documentation recommended as the next step. Each patch was locally correct. Only looking at the whole diff at once showed the trap. That’s twice now this pattern has paid for itself, and it’s changing how much we trust a green per-task review on its own.

There was a second version of the same lesson in miniature: a security-audit-level review of the one skill built to run unsupervised with real git access caught that “never run git push” wasn’t actually a complete rule — the GitHub MCP tools can reach a remote without that command ever appearing in the diff. The rule had to be rewritten around the actual capability, not the command we’d been watching for.

And a genuinely dumb one, caught for the third time: weak-signals.json lost data to the same truncation bug it had twice before. This time it was caught live, in the working tree, before it got committed over — which is a better outcome than the first two times, but three recurrences of one bug is its own signal. Recognizing a pattern instead of re-investigating from zero is also how a stale-Redis bug on a completely different project (homelab-manager) went from a real investigation the first time to a two-minute fix the second — the earlier DECISIONS.md entry did the work.

Not every wall has a way through it. Claude Code’s Auto Mode classifier hard-blocks modifying binaries under Windows’ Program Files, independent of any permission rule you set yourself. No workaround exists. The right move was recognizing that fast and handing the one step to a human with real interactive access, rather than burning cycles looking for a bypass that wasn’t there.

The Skill Stack

/council-discuss — the moderator skill. Runs an interactive Decision Council session against one pending recommendation, quizzing and arguing from whichever personas are actually relevant to that item, and ends with a recorded decision.

/council-action — the implementer. Takes an approved recommendation, builds it in an isolated git worktree, commits locally — and stops. It never pushes; that boundary is load-bearing, not a suggestion.

/platform-review retired. Its job — itemized triage of research cycles, skills, and weak signals — is now absorbed into the Council pipeline’s weekly batch, so recommendations have exactly one path from surfaced to actioned instead of two competing ones.

What’s Next

Retiring /platform-review left one loose thread: driver.py still dispatches the now-deleted skill from a dashboard button, so clicking it does nothing useful. Small fix, already logged.

Housekeeping tasks still can’t be fully configured through the API — interval isn’t in the PATCH allow-list, so setting up anything other than a weekly cadence needs a manual UI step after creation. Worth a proper “routine” concept at some point.

And the adapter/harness reconciliation has one deliberately unfinished piece: housekeeping.md and the two new Council skills exist only in the deployed harness, not the portable reference. That’s staying that way on purpose until the Council pipeline has been stable for a while — porting fast-moving code into the “stable reference” copy just means it goes stale again immediately.