UPDATE THIS FILE when making architectural changes, adding patterns, or changing conventions.
Operational rules and references for automated agents working on this repo. Install:
npm i -g @the-open-engine/zeroshot or npm link (dev).
- Never spawn without permission. Do not run
zeroshot run <id>unless the user explicitly asks to run it. - Never use git in validator prompts. Validate files directly.
- Never ask questions. Agents run non-interactively; make autonomous decisions.
- Never edit
CLAUDE.mdunless explicitly asked to update docs. - Detached (
-d) runs must forward allzeroshot runoptions viaZEROSHOT_RUN_OPTIONS(seebuildDaemonEnv+buildStartOptions) so PR/worktree config cannot be dropped.
Worker git operations are allowed only with isolation (--worktree, --docker, --pr, --ship). They are forbidden without isolation.
Read-only safe commands: zeroshot list, zeroshot status, zeroshot logs
Destructive commands (need permission): zeroshot kill, zeroshot clear, zeroshot purge
| Concept | File |
|---|---|
| Conductor classification | src/conductor-bootstrap.js |
| Base templates | cluster-templates/base-templates/ |
| Message bus | src/message-bus.js |
| Ledger (SQLite) | src/ledger.js |
| Guidance topics | src/guidance-topics.js |
| Guidance mailbox helper | src/ledger.js |
| Guidance live injection | src/orchestrator.js |
| Trigger evaluation | src/logic-engine.js |
| Agent wrapper | src/agent-wrapper.js |
| Providers registry | src/providers/index.js |
| Provider implementations | src/providers/ |
| Provider engine registry | src/agent-cli-provider/provider-registry.ts |
| Gateway runner | src/agent-cli-provider/gateway-runner.ts |
| Gateway tools/policy | src/agent-cli-provider/gateway-tools.ts |
| Provider detection | lib/provider-detection.js |
| Provider capabilities | src/providers/capabilities.js |
| Start-cluster helper | lib/start-cluster.js |
| Legacy worker facade | lib/cluster-worker/ |
| Legacy worker executable | bin/zeroshot-cluster-worker.js |
| Docker mounts/env | lib/docker-config.js |
| Container lifecycle | src/isolation-manager.js |
| Settings | lib/settings.js |
| Cluster wire/domain types | crates/openengine-cluster-protocol/ |
| Admission wire semantics | crates/openengine-cluster-protocol/src/admission.rs |
| Graph AST/bindings/guards | crates/openengine-cluster-protocol/src/graph.rs |
| Closed payload algebra | crates/openengine-cluster-protocol/src/payload.rs |
| Closed payload validation | crates/openengine-cluster-protocol/src/payload_value.rs |
| Compiled IR/identity | crates/openengine-cluster-protocol/src/canonical.rs |
| Artifact receipts | crates/openengine-cluster-protocol/src/artifact.rs |
| Graph diagnostics/bounds | crates/openengine-cluster-protocol/src/diagnostic.rs |
| Shared wire-value bounds | crates/openengine-cluster-protocol/src/value.rs |
| Cluster dispatch/stdio | crates/openengine-cluster-server/ |
| Graph verifier facade | crates/openengine-cluster-server/src/graph_verifier.rs |
| Graph verifier analysis | crates/openengine-cluster-server/src/graph_verifier/ |
| Native product construction | zeroshot-rust/ |
| Artifact store port/fake | zeroshot-rust/src/artifact_store.rs, artifact_store/fake.rs |
| Product-local artifact CAS | zeroshot-rust/src/artifact_store/local_cas.rs, local_cas/ |
| Issue provider contracts | zeroshot-rust/src/issue_provider.rs, issue_provider/ |
| Source provider contracts | zeroshot-rust/src/source_code_provider.rs, source_code_provider/ |
| Provider value bounds | zeroshot-rust/src/provider_value.rs, provider_value/ |
| Native safe faults | zeroshot-rust/src/fault.rs |
| Native fault taxonomy | zeroshot-rust/src/fault/taxonomy.rs |
| Native diagnostic redaction | zeroshot-rust/src/fault/redaction.rs |
| Native observability | zeroshot-rust/src/observability.rs |
| Admission coordinator | crates/openengine-cluster-server/src/admission.rs |
| Admission durable ports | crates/openengine-cluster-server/src/admission/ports.rs |
| Admission snapshot folding | crates/openengine-cluster-server/src/admission/snapshot.rs |
| Lifecycle state machine | crates/openengine-cluster-server/src/lifecycle.rs |
| Lifecycle durable ports | crates/openengine-cluster-server/src/lifecycle/ports.rs |
| Cluster typed transports | crates/openengine-cluster-client/ |
| Cluster fixtures/artifacts | crates/openengine-cluster-testkit/ |
| Scripted admission fixtures | crates/openengine-cluster-testkit/src/admission.rs |
| Fixture inspection controls | crates/openengine-cluster-testkit/src/admission/inspection.rs |
| Scripted lifecycle helpers | crates/openengine-cluster-testkit/src/lifecycle.rs |
| Lifecycle fixture params | crates/openengine-cluster-testkit/src/lifecycle/params.rs |
| Admission transcript output | crates/openengine-cluster-testkit/src/admission_artifacts.rs |
| Negative graph vectors | crates/openengine-cluster-testkit/src/negative_graph_fixtures.rs |
| Verifier vectors | crates/openengine-cluster-testkit/src/graph_verifier_artifacts.rs |
| Graph contract prose | docs/openengine-cluster-protocol/v1/graph-contract.md |
| Admission contract prose | docs/openengine-cluster-protocol/v1/admission.md |
| Lifecycle contract prose | docs/openengine-cluster-protocol/v1/lifecycle.md |
| Generated graph fixtures | protocol/openengine-cluster/v1/fixtures/graph/ |
Cluster Protocol Rust types are the source of truth. Files under
protocol/openengine-cluster/v1/ are generated projections; update them with
cargo run -p openengine-cluster-testkit --bin generate-cluster-protocol -- --write and
verify byte-for-byte drift with npm run protocol:check. These generator-formatted artifacts
are excluded from Prettier; never format them independently.
The protocol and server crates own wire contracts, backend traits, the dispatcher, and transports.
zeroshot-rust/ owns the concrete NativeBackend, product-local NativeBackendFactory
construction root, product-private artifact byte-store port/local CAS, and product-private,
secret-free issue/source provider contracts. Artifact stages, bytes, roots, filesystem paths,
locks, and manifests remain product-private; only verified protocol ArtifactRef receipts cross
the engine boundary. LocalCasArtifactStore takes an explicit root, is a single-writer local
filesystem store, and must preserve ref-first release plus synchronized blob-then-ref publication.
Issue and source registries and identifiers remain independent; neither is a worker/model provider.
Keep protocol, transport, daemon, compatibility, adapter, credential resolution, ledger, and
workspace behavior outside it.
Native engine faults must be constructed only by FaultFactory from closed ModuleEvidence.
Decoded faults must match the canonical semantics derived from their required primary source frame.
Raw diagnostic values are replaced wholesale with typed markers and remain ephemeral; never put
them in EngineFault, observations, protocol responses, persistence, or exports. Observability is
injected through ObservationSink and uses only the fixed metrics and closed dimensions in
observability.rs; retry disposition is descriptive data, not retry authorization. Do not install
global telemetry state or caller-defined labels.
Graph syntax, payload subtyping, compiled IR, diagnostics, and artifact receipt Rust types remain
authoritative protocol contracts. ProductionGraphVerifier is the one reusable production
semantic verifier for openengine.graph.full/v1; it resolves workers through WorkerRegistry and
adds proven StructuralBounds without replacing the authoritative AST/IR. It does not admit,
store, schedule, or execute graphs. ScriptedVerifier remains a test-only admission fixture.
Full-v1 ceilings are fixed public constants beside ProductionGraphVerifier, not product
configuration. Node timeouts use the wire PositiveInteger range and have no 24-hour verifier
ceiling.
Full-v1 finite control enumeration couples each executable's signals and error as mutually
exclusive outcomes, including per-item map aggregates. Choice residual assignments govern output
channel availability; terminal alternatives do not flow into later nodes. Mapped control flow
preserves per-item execution correlation: guaranteed sequential, full-completion parallel, and
do-while descendants emit an outcome, while conditional descendants emit one exactly on their
selected residual route. An otherwise node is illegal when earlier branches exhaust the legal
control space and is excluded from flow analysis.
k_of_n and k_of_map labels never widen their selectors' closed domains. Executable writes
remain success-conditional until residual control excludes every runtime error; state reads and
promotions preserve that outcome provenance. Definition flow carries exact path/type guarantees
from required initial input through nested groups. A successful output/diagnostic binding defines
only its required selected path and required descendants, never optional producer paths.
V1 has no whole-payload binding: executable inputs and succeed outputs must be null or records.
Scalar, enum, and array payloads remain valid in other algebra positions and as nested record
fields. A map body write to a promoted array<T> path writes one T at the current input index;
the result is input-ordered and total, with empty input defining [], while mapped executable
success/error provenance remains until control excludes every mapped runtime error.
Parallel continuation requires all branches for all, one for any/first, and count for
quorum; quorum flow and promotions are guaranteed only when present in every jointly satisfiable
size-count completion set. Shared guard correlations can make independently possible branch
completions mutually exclusive and must be preserved during that analysis. Correlate
joined=reached|quorum_unreachable for all/any/quorum with the required branch-completion
predicate; mapped join controls retain that correlation with branch controls per item before their
counts are aggregated. Impossible status/control combinations are excluded from guard analysis. Parallel failure labels
quorum_unreachable and no_satisfier restore the incoming pre-par definitions and expose no
winner or branch-promotion data. Unguarded continuation cannot consume success-only parallel
writes. Preserve target-granular conditional ownership through nested parallels, choice merges,
and later sequential writers; descendant writes must invalidate stale ancestor type facts.
For first, only a completing branch that guarantees the controls read by when and satisfies the
predicate is a winner; correlate raced=satisfied|no_satisfier with those winner assignments.
The admission coordinator provides stateful plan/apply/get semantics through injected ports.
Testkit scripted approval and running phase mean admitted state, not native verification or a
production full-graph executor.
Authoritative admission snapshots fail closed: empty has no durable fields, running has the
complete matching control/seed tuple, and transient admitting preserves one of those two shapes.
Operational suspend is a dispatch gate: existing leases may land verified I/O, but successors wait
for resume. Drain waits without inventing graph hooks; force cancels and voids leases without
fabricating output. Each stopped run has one final finished event. Stop acknowledgements never
claim rollback or absence of external side effects. These are deterministic scripted-backend
semantics, not a native graph scheduler or worker executor.
The TUI is not included in this release. Use zeroshot list, zeroshot status <id>,
and zeroshot logs <id> -f or zeroshot logs <id> -w for monitoring.
| Concept | File |
|---|---|
| Worker descriptors | crates/openengine-cluster-protocol/src/worker.rs |
| Normalized worker outcomes | crates/openengine-cluster-protocol/src/worker/outcome.rs |
| Worker registry boundary | crates/openengine-cluster-server/src/worker_registry.rs |
| Mock worker profiles | crates/openengine-cluster-testkit/src/worker_profiles.rs |
Worker descriptors and registry compatibility checks are contract/pre-admission ports only.
ACP/A2A modules in the testkit are mock conformance profiles, never production transports.
Descriptors must declare all four closed runtime errors (timeout, crash, malformed, refusal).
The reserved legacy descriptor is valid only with its canonical request/result payload types, while
mock verifier completions must validate output, signals, diagnostics, and artifacts before emission.
Worker JSON Schema must mirror descriptor cross-field/uniqueness validation and the closed
error-code/reason matrix; registry compatibility must reject verifier contracts on step nodes.
The legacy cluster worker is the bounded Node implementation of legacy.zeroshot.ship@1.
Its public facade is exactly start, status, events, stop, and result; do not add
guidance, permission callbacks, writable attach, raw output, credential fields, or caller launch
flags. Registry resolution must produce a frozen worktree/docker plan before engine allocation.
Lifecycle and terminal truth comes from cluster records plus durable ledger topics; PID state is
diagnostic only. Explicit stop is bounded by the registry shutdown deadline and never claims that
provider or tool side effects were rolled back.
Completion events require a canonical result or explicit bounded summary, and failure events require
a valid closed code/reason pair; missing or corrupt terminal data fails as malformed. Engine status
observation is synchronous and fails closed when durable truth cannot be read.
Profile resolution, artifact staging, engine start, and receipt collection remain cancellable under
the registry execution bound; stop may win before engine allocation. A caller shutdown deadline
bounds stop acknowledgement, not cleanup ownership: the engine adapter must still stop a cluster
that allocates late while start remains pending, then release its orchestrator exactly once so
process EOF cannot retain engine handles. The executable may wait for that cleanup only until its
own shutdown deadline; at the deadline it invokes the internal release port and exits.
Artifact input has no echo-only default resolver. The current engine allocates isolation first,
then runs the injected resolver before agents start; the resolver must materialize read-only content
inside that workspace. Cancelled profile, staging, and receipt operations retain late cleanup
ownership through their injected release/cleanup hooks. Late operation and cleanup failures must
reach the cleanup-failure reporter (default: process warning); never detach them with an empty catch.
# Flag cascade: --ship -> --pr -> --worktree
zeroshot run 123 # Local, no isolation
zeroshot run 123 --worktree # Git worktree isolation
zeroshot run 123 --pr # Worktree + create PR
zeroshot run 123 --pr --pr-base dev # PR base: dev, worktree base: origin/dev (incl. -d)
zeroshot run 123 --ship # Worktree + PR + auto-merge
zeroshot run 123 --docker # Docker container isolation
zeroshot run 123 -d # Background (daemon) mode
# Management
zeroshot list # All clusters (--json)
zeroshot status <id> # Cluster details
zeroshot logs <id> [-f|-w] # Stream logs
zeroshot resume <id> [prompt] # Resume failed cluster
zeroshot stop <id> # Graceful stop
zeroshot kill <id> # Force kill
# Utilities
zeroshot export <id> # Export conversation
zeroshot agents list # Available agents
zeroshot settings # View/modify settings
zeroshot providers # Provider status and defaultsUX modes:
- Foreground (
zeroshot run): streams logs, Ctrl+C stops cluster. - Daemon (
-d): background, Ctrl+C detaches. - Attach (
zeroshot attach): connect to daemon, Ctrl+C detaches only.
Settings: defaultProvider, providerSettings (claude/codex/gateway/gemini/opencode/pi/copilot), legacy maxModel, defaultConfig, logLevel, robustness (maxRetries, backoffBaseMs, backoffMaxMs, jitterFactor, maxRestartAttempts, maxTotalRestarts, staleWarningsBeforeKill).
Provider engines are registry-owned: adding an engine means one entry in src/agent-cli-provider/provider-registry.ts, plus the provider-specific adapter and tests. Docker credential mount/env presets, CLI aliases, visible preset lists, and any nontrivial availability probe rules must derive from that registry entry; do not add new provider identity lists or provider preset lists elsewhere.
Model gateways stay behind the single bundled gateway engine. Do not add openrouter, ollama, vllm, hermes, or similar model-only targets as standalone provider ids.
ACP-native engines use one shared stdio adapter lane. New ACP engines must be added with registry metadata plus helper fixtures only; do not add engine-specific ACP parsers or invoke runners.
ACP fixtures must use protocol-shaped chunk payloads: agent_message_chunk.content is a single ContentBlock object, and thought deltas are covered with agent_thought_chunk fixtures so parser tests catch spec drift.
Pub/sub message bus + SQLite ledger. Agents subscribe to topics, execute on trigger match, publish results.
Agent A -> publish() -> SQLite Ledger -> LogicEngine -> trigger match -> Agent B executes
| Primitive | Purpose |
|---|---|
| Topic | Named message channel (ISSUE_OPENED, VALIDATION_RESULT) |
| Trigger | Condition to wake agent ({ topic, action, logic }) |
| Logic Script | JS predicate for complex conditions |
| Hook | Post-task action (publish message, execute command) |
Restart persistence: orchestrator publishes AGENT_RESTART_ATTEMPT to the ledger so restart limits survive orchestrator restarts.
Provider task ownership: task watchers persist an owned termination boundary with each active task.
POSIX providers run in a dedicated process group; Windows providers use the exact root PID with
taskkill /T. Recovery must terminate that recorded boundary before retrying work.
- Topics:
USER_GUIDANCE_CLUSTER,USER_GUIDANCE_AGENT(seesrc/guidance-topics.js). - Mailbox helper:
ledger.queryGuidanceMailbox()withmessageBus.queryGuidanceMailbox()passthrough. - Live injection:
Orchestrator.sendGuidanceToAgent()usesagent.injectInput()to attempt PTY stdin; always persistsUSER_GUIDANCE_AGENTwithmetadata.delivery(status: injected|unsupported,method: pty,taskId,reason). - Safe-point queue fallback:
AgentWrapper._buildContext()pulls queued guidance viacollectQueuedGuidance()and injects a delimited block inagent-context-builderbetween Instructions and Output Schema. Cursor:agent.lastGuidanceAppliedAt.
{
"id": "worker",
"role": "implementation",
"modelLevel": "level2",
"triggers": [{ "topic": "ISSUE_OPENED", "action": "execute_task" }],
"prompt": "Implement the requested feature...",
"hooks": {
"onComplete": {
"action": "publish_message",
"config": { "topic": "IMPLEMENTATION_READY" }
}
}
}- Use
modelLevel(level1/level2/level3) for provider-agnostic configs. - Set
providerper agent ordefaultProvider/forceProviderat cluster level. - Provider names use CLI identifiers:
claude,codex,gemini,opencode,pi,copilot(legacyanthropic/openai/googlemap to these). modelremains a provider-specific escape hatch.- Claude/Codex/Opencode only:
reasoningEffort(low|medium|high|xhigh|max).
// Ledger (auto-scoped to cluster)
ledger.query({ topic, sender, since, limit });
ledger.findLast({ topic });
ledger.count({ topic });
// Cluster
cluster.getAgents();
cluster.getAgentsByRole('validator');
// Helpers
helpers.allResponded(agents, topic, since);
helpers.hasConsensus(topic, since);Context strategies now support since: 'last_agent_start' to scope history to the most recent
iteration start for the executing agent. Acceptable values: cluster_start, last_task_end,
last_agent_start, or an ISO timestamp string.
Classifies tasks on Complexity x TaskType, routes to parameterized templates.
| Complexity | Description | Validators |
|---|---|---|
| TRIVIAL | 1 file, mechanical | 0 |
| SIMPLE | 1 concern | 1 |
| STANDARD | Multi-file | 3 |
| CRITICAL | Auth/payments/security | 5 |
| TaskType | Action |
|---|---|
| INQUIRY | Read-only exploration |
| TASK | Implement new feature |
| DEBUG | Fix broken code |
Base templates: single-worker, worker-validator, debug-workflow, full-workflow.
| Mode | Flag | Use When |
|---|---|---|
| Worktree | --worktree |
Quick isolated work, PR workflows |
| Docker | --docker |
Full isolation, risky experiments, parallel agents |
Worktree: lightweight git branch isolation (<1s setup). Docker: fresh git clone in container, credentials mounted, auto-cleanup.
Configurable credential mounts for --docker mode. See lib/docker-config.js.
| Setting | Type | Default | Description |
| ---------------------- | ------------- | -------- | ----------------------------------------------------- | ---------------------------------------- |
| dockerMounts | Array<string | object> | ['gh','git','ssh'] | Presets or {host, container, readonly} |
| dockerEnvPassthrough | string[] | [] | Extra env vars (supports VAR, VAR_*, VAR=value) |
| dockerContainerHome | string | /root | Container home for $HOME expansion |
Mount presets: infrastructure presets plus provider ids from src/agent-cli-provider/provider-registry.ts.
Provider CLIs in Docker require credential mounts; Zeroshot warns when missing.
Env var syntax:
VAR-> pass if set in host envVAR_*-> pass all matching (e.g.,TF_VAR_*)VAR=value-> always set to valueVAR=-> always set to empty string
Config priority: CLI flags > ZEROSHOT_DOCKER_MOUNTS env > settings > defaults.
# Persistent config
zeroshot settings set dockerMounts '["gh","git","ssh","aws"]'
# Per-run override
zeroshot run 123 --docker --mount ~/.custom:/root/.custom:ro
# Disable all mounts
zeroshot run 123 --docker --no-mountsCore principle: tests passing != implementation works. The ONLY verification is: USE IT YOURSELF.
- Read issue -> understand requirements
- Look at code -> figure out how to invoke
- Run it -> did it work?
- Try to break it -> edge cases
- Verify each requirement -> evidence (command + output)
| File | Content |
|---|---|
~/.zeroshot/clusters.json |
Cluster metadata |
~/.zeroshot/<id>.db |
SQLite message ledger |
Clusters survive crashes. Resume: zeroshot resume <id>.
Bash subprocess output not streamed: Claude CLI returns tool_result after subprocess completes.
Long scripts show no output until done.
Zeroshot’s message ledger is SQLite (~/.zeroshot/<id>.db). On Kubernetes, putting this on a
network filesystem (EFS/NFS/CephFS) can cause severe latency and lock contention.
Mitigations (env vars):
ZEROSHOT_SQLITE_JOURNAL_MODE=DELETE(orTRUNCATE) for network filesystems that don’t like WALZEROSHOT_SQLITE_WAL_AUTOCHECKPOINT_PAGES=1000(default) to avoid per-write checkpoint stormsZEROSHOT_SQLITE_BUSY_TIMEOUT_MS=5000(default) to reduceSQLITE_BUSYflakiness under contention
Operational rule: don’t run multiple pods against the same ~/.zeroshot volume unless you
really know what you’re doing—SQLite is not a multi-writer, multi-node database.
Bug: --ship mode created worktree but template agents (planning, implementation, validator)
ran in main directory instead, polluting it with uncommitted changes.
Root cause: _opAddAgents() didn't inject cluster's worktree cwd into dynamically spawned
template agents. Initial agents got cwd via startCluster(), but template agents loaded
later via conductor classification missed it.
Fix: added cwd injection to _opAddAgents() and resume path in orchestrator.js.
Test: tests/worktree-cwd-injection.test.js.
Bug: PR-mode clusters stayed running after PR creation/merge because no
CLUSTER_COMPLETE was ever published.
Root cause: git-pusher relied on output.publishAfter without an onComplete
hook, so the orchestrator never received the completion signal.
Fix: added onComplete publish of CLUSTER_COMPLETE in
src/agents/git-pusher-agent.json.
Test: tests/integration/orchestrator-flow.test.js.
Bug: foreground zeroshot resume could print cluster completion but remain alive until a
five-second task-shutdown timer expired.
Root cause: agent shutdown raced in-flight execution against a bounded timeout without clearing the
losing timer, and the resume CLI omitted the foreground orchestrator cleanup used by run.
Fix: clear the bounded-wait timer, close non-daemon resume orchestrators in finally, and make
orchestrator close release snapshotter, message-bus, and ledger resources.
Tests: tests/unit/agent-lifecycle-stop.test.js and
tests/e2e/resume-detach-daemon.test.js.
ENFORCE > DOCUMENT. If enforceable, don't document.
Preference: Type system > ESLint > Pre-commit hook > Documentation
Error messages ARE the documentation. Write them with what + fix.
# ❌ FORBIDDEN
agent: "I'll run zeroshot on issue #123"
zeroshot run 123
# ✅ CORRECT
agent: "Would you like me to run zeroshot on issue #123?"
# Wait for user consentWHY: Multi-agent runs consume significant API credits.
# ❌ FORBIDDEN
validator_prompt: "Run git diff to verify changes..."
# ✅ CORRECT
validator_prompt: "Read src/index.js and verify function exists..."WHY: Multiple agents modify git state concurrently. Validator reads stale state.
// ❌ FORBIDDEN
await AskUserQuestion('Should I use approach A or B?');
// ✅ CORRECT
// Decision: Using approach A because requirement specifies XWHY: Zeroshot agents run non-interactively.
# ❌ FORBIDDEN
zeroshot run 123 # Pollutes main directory
# ✅ CORRECT
zeroshot run 123 --worktree # Isolated
zeroshot run 123 --pr # Worktree + PR
zeroshot run 123 --docker # Full isolationWHY: Prevents contamination, enables parallel work.
# ❌ FORBIDDEN
git stash # Hides work from other agents
# ✅ CORRECT
git add -A && git commit -m "WIP: feature implementation"
git switch other-branchWHY: WIP commits are visible, never lost, squashable.
Use WIP commits instead of stashing:
git add -A && git commit -m "WIP: save work" # Instead of git stash
git switch <branch> # Instead of git checkout
git restore <file> # Instead of git checkout --Write tests BEFORE or WITH code:
touch src/new-feature.js
touch tests/new-feature.test.js # FIRST
# Write failing tests → Implement → PassRun validation for:
- Significant changes (>50 lines)
- Refactoring across files
- When user explicitly requests
Trust pre-commit hooks for trivial changes.
npm run test:unit uses a temporary home and settings path; operator settings must not affect it.
npm run lint
npm run testMocha config: .mocharc.cjs applies defaults; passing explicit *.test.js files on the CLI skips the default tests/**/*.test.js spec.
The Mocha bootstrap isolates unit tests from live ZEROSHOT_* run options and user settings;
tests must not depend on ambient cluster state or ~/.zeroshot/settings.json.
Workers are now explicitly ordered to treat every VALIDATION_RESULT line as non-negotiable law before typing again. Failing to read and address each validator complaint before claiming completion will be rejected automatically.
Multiple CI jobs fail → Diagnose each independently.
- Get exact status:
gh api repos/the-open-engine/zeroshot/actions/runs/{RUN_ID}/jobs - Read ACTUAL error:
gh api repos/the-open-engine/zeroshot/actions/jobs/{JOB_ID}/logs - Fix ONE error → Push → Rerun → Repeat
- Dev required checks:
checkonly (merge queue). - Main required checks:
check+install-matrix(merge queue). - Cross-platform
install-matrixruns in CI for main only.
Do NOT assume single root cause.
Scope: Narrowest possible.
Content Priority:
- CRITICAL gotchas (caused real bugs)
- "Where to Look" routing tables
- Anti-patterns with WHY
- Commands/troubleshooting
DELETE: Tutorial content, directory trees, interface definitions
Format: Tables over prose, ❌/✅ examples with WHY
| Antipattern | Enforcement |
|---|---|
| Dangerous fallbacks | ESLint ERROR |
| Manual git tags | Pre-push hook |
| Git in validator prompts | Config validator |
| Multiple impl files (-v2) | Pre-commit hook |
| Spawn without permission | Runtime check |
| Git stash usage | Pre-commit hook |
| lint-staged backup stashes | Pre-commit wrapper |
| Rust formatting drift | Pre-commit hook |