Deterministic AI Engineering
The work on this repo is not "writing hooks" or "writing agents." It is implementing a methodology called Deterministic AI Engineering. The platform we ship โ engineering-standards, materialised inside bewith-docs โ is one specific implementation of that methodology. Every design decision should trace back to one of the eight principles below.
For the full strategic context, see ai-engineering-strategy.md. This page is the short version: read this if you have five minutes and want to know why the system looks the way it does.
The premiseโ
The stochastic LLM is a teammate, not a tool. Treating it as a deterministic compiler produces five individual failures (amnesia, non-determinism, test neglect, code duplication, doc drift) and four team-scale failures (claim races, state-file conflicts, governance drift, schema blast radius). The methodology's answer is not "make the model smarter." It is move every load-bearing rule out of the prompt and into tooling the AI cannot override.
This is the difference between a rule in CLAUDE.md (a suggestion at temperature > 0) and a rule enforced by a git hook (binary). When safety depends on a rule, it does not live in markdown alone.
What we build vs. what we ride onโ
A natural question: are we building an AI harness โ the engine that runs the agentic loop, executes tools, feeds results back, and manages the permission surface? No. That engine already exists โ it is Claude Code (and the Claude Agent SDK beneath it). Building our own would re-implement AutoGPT for no gain.
Three layers, and we own exactly one:
| Layer | What it is | Who provides it |
|---|---|---|
| Harness | Runs the model, holds conversation state, executes tools, feeds results back, manages the permission surface | Claude Code โ given |
| Generic agentic loop | prompt โ model picks tool calls โ run tools โ feed back โ repeat until done | Claude Code โ given |
| Domain layer | Which shape the loop takes, when it stops, what tools and context it may use, which expert is in the room | us |
The mechanism is Claude Code's; the policy is ours:
/continueis not the engine โ it is the loop body: the BeWith-specific 13-step shape (identify task โ evaluate policies โ load agents โ plan โ implement โ verify โ PR) that runs inside Claude Code's loop.- Policies, hooks, and the DoD are the stop-and-guard conditions โ not a generic "is the model done?" but "is this auth change reviewed, are the tests green, is the branch legal?"
- Agents are the targeted context injection; the allowlist is permission management as config.
And task state barely lives in this stack at all: the harness holds only the conversation plus a thin local cache. The authoritative state of the work โ the PRD, the design, the issues, the status โ lives in ClickUp and GitHub (principle 5, state is cloud-first). We don't run a big stateful loop; we keep the loop thin and let the trackers we already use hold the truth.
This is also why the methodology is portable (see The methodology name vs the implementation name): swap Claude Code for another harness and the domain layer โ the loop body, the gates, the agents โ is what survives. We do not build the agent runtime. We program it.
The eight principles below are the rules of that domain layer.
The eight principlesโ
1. Determinism via tooling, not promptingโ
A rule in CLAUDE.md is a suggestion. A rule enforced by a git hook, a CI workflow, a commit lint config, or a Policy Engine YAML is binary. Move every load-bearing rule into tooling. The AI is told the gates exist and is asked to cooperate. It is not asked to enforce them.
This is the principle behind every hook in .claude/hooks/ and every workflow in .github/workflows/.
2. Single Source of Truth with lazy loadingโ
Every rule, agent, skill, command, and policy lives in exactly one file. Consumer overlays may add to the platform but may not redefine it. Sessions load only what the current task requires โ a frontend bug fix loads the frontend agent and one or two relevant skills, not the full platform body.
Total session context overhead: ~50KB. Platform body: ~400KB. Eighty-five percent stays unloaded. This is what makes detailed expert agents (15โ25KB each) sustainable.
3. Autonomous by default, configurable gatesโ
The AI proceeds without asking unless a specific gate stops it. Three categories of action:
- Always autonomous โ branch creation, commits to feature branches, test runs, lint fixes, ClickUp "In Progress" status. Never prompts.
- Configurable gates โ default off (autonomous), per-user opt-in via
~/.claude/user-overrides.yaml. Examples: ClickUp comments, cross-repo PRs, schema migrations. - Hard Floor โ always require explicit approval. Six items, unoverridable: production deploy, force-push to shared branches, secret rotation, destructive DB ops in production, public communications, CODEOWNERS modification.
Each Hard Floor item meets all four criteria: irreversibility, blast radius beyond the current actor, no effective recovery via tooling, no reasonable disagreement about the default. The list is short and the friction is justified. See ai-engineering-strategy.md ยง10.1.1 for the criteria and the full list.
4. Manual workflows are first-classโ
A developer who never opens Claude gets the same safety floor (hooks, CI, commit lint) as one who runs /continue. AI is an accelerator on top of an organisational standard, not a replacement for it. Every hook fires on every git operation regardless of who is at the keyboard. Every CI workflow runs on every PR.
This is by design. Treating the platform as either-or โ "you must use Claude" โ would fracture the team. Treating it as a shared floor on which AI is an accelerator preserves the choice and the standard.
5. State is cloud-first, local-cachedโ
Authoritative state for an in-progress task lives in the GitHub Issue body's "AI Context" section. The local cache at .claude/session/active-context.json is a per-machine convenience. On session start, the AI reconciles: if the Issue is newer than the local cache, remote wins; if local is newer and same actor, push; if different actors disagree, stop and ask.
This makes "close laptop, resume on mobile" and "developer is sick, coworker takes over" both trivial. It also eliminates the entire class of bugs that arise from treating local files as source of truth.
6. Knowledge โ Governance (but same repo)โ
"How we work" (rules, agents, hooks, policies) and "what we know" (architecture docs, ADRs, runbooks, glossary) are separate concerns. But the operational cost of two repositories with two release cycles is higher than the benefit. We keep them logically separated through CODEOWNERS routing and docs/ vs .claude/+policies/+autonomy/ directory boundaries โ but in one repository, one semver, one release pipeline.
Two repos was operational theatre. The methodology survives just fine with logical separation inside one repo.
7. Federation from day oneโ
Even though the pilot starts with three repositories, the federated model is the only model. Every consumer follows a specific version of the platform through the plugin version it has installed plus the @ref its CI wrapper workflows pin. Upgrades are explicit. Drift is detectable. Rollback is one line.
This costs one CI workflow and one lockfile per consumer. The benefit: scaling from three repositories to forty-four requires no architectural change โ only configuration.
8. The Policy Engine decides; the AI followsโ
Policies are declarative YAML in /policies. The engine reads them at step 4 of the 13-step autonomous loop and outputs the required agents, gates, risk score, and approval conditions. The AI executes; the gates verify; the engine decides.
The AI does not pick gates from prompt context. Without an explicit Policy Engine, "what gates apply when" lives implicitly in the AI's behavior, and different sessions interpret the same situation differently. With an explicit engine, the gates are visible: a developer can read the YAML and predict the AI's behavior.
How the principles shape daily decisionsโ
When in doubt about a design choice, the principle wins. Examples from the build so far:
commit-cu-check.shis opt-in (REQUIRE_CU_ID, default off) rather than always-on โ principle 3 (autonomous by default). The PR-title gate inclickup-commit-check.ymlis the canonical place for the hard CU-id check; per-commit is a softer per-repo opt-in.branch-name-check.shis dual-mode, with placeholder CU-ids rejected in both modes โ principle 1 (determinism via tooling: no prompt-level "please use a real id"). The shared validatorscripts/checks/check-cu-id.shis used by hook and CI โ principle 2 (one rule, one file).- Hooks fire on every git operation regardless of Claude โ principle 4 (manual-friendly). A developer typing
git commitdirectly hits the sameno-master-edit.shthat Claude does. dangerous-patterns.jsonlives in one file; the hook reads it on every invocation โ principle 2 (SoT with lazy load).- 9 starter policies reference agents that don't exist yet โ the engine warns rather than blocks โ principle 8 (engine decides) plus principle 7 (federation: components ship independently).
.yanked.jsonlives at HEAD, not per-version, so a yank propagates to all consumers immediately โ principle 7 (federation drift is detectable and recoverable in one line).- DB/cache work and file reads route to dedicated tools, not raw Bash โ the sandbox infra-MCP query+write tools (bounded + audited, writes guarded) and Read/Grep/Glob, with a
prefer-infra-mcphook that asks (never blocks) on a rawmysql/mongo/redis-cliinvocation โ principle 1 (a bounded tool with guardrails beats arbitrary shell, and the preference is enforced by tooling rather than only stated). The standalone rule is.claude/rules/team/prefer-dedicated-tools-over-bash.md; the hook layering is in the permission model.
The methodology name vs the implementation nameโ
- Deterministic AI Engineering โ the philosophy. Portable to any team that has more than one engineer and more than one repository.
- BeWith engineering platform /
engineering-standardsโ the specific implementation at bewith-dev. Opinionated: Claude Code, ClickUp, GitHub, Docusaurus, MongoDB+MySQL, AWS ECS.
When discussing how to think, use the methodology name. When discussing what files to put where, use the platform name. The methodology survives a swap of the model layer; the platform's implementation choices are the current best mappings.
Where to read nextโ
- ai-engineering-strategy.md โ the full strategic doc. Sections of interest:
- ยง1 โ the problem we're solving (the failure modes this methodology addresses).
- ยง4 โ the principles in their full form.
- ยง10 โ the Hard Floor in full, with the four criteria and the seven items.
- ยง22 โ the adoption story (the "why now" + "what the CTO conversation looks like").
- /policies โ the Policy Engine's declarative YAML.
- /agents โ the 15 expert agents (planned; under construction).