Repository navigation
Releases: marcelocantos/doit
Release list
v0.9.0
doit v0.9.0
Postmortem-tooling release. The audit log now captures every signal an
operator (or agent) needs to reconstruct why doit made a decision — not
just what decision it made — and the new doit_audit_query MCP tool
makes those signals reachable by filter rather than tail-by-count.
Added
-
🎯T37 — L3 chain-of-evidence in the audit log. Every L3 invocation now
records a structuredl3_fastblock (andl3_deepwhen the cascade
fires both tiers) containing the model name, rendered prompt, model
response, latency, decision, and reason. Configurable size cap via
audit.l3_max_chars(default 16384 per block) with explicit truncation
marker. The single biggest postmortem black hole — "why did L3 allow
that?" — is now answerable. -
🎯T36 — Elicitation outcomes and L2 promotions in the audit chain.
Phase 1 elicitation (Allow once / Allow always / Deny once / Deny always)
and Phase 2 promotion (rule proposed, accepted, or declined) each
produce their own audit-chain entry, linked to the originating command
via the newparent_seqfield. New fields:parent_seq,
elicitation_prompt,elicitation_choice,elicitation_latency_ms,
proposed_rule_source,proposed_rule_generality,proposed_rule_id.
Reflexive-vs-deliberated approvals are now visible as latency
outliers; rule provenance is no longer lost. -
🎯T39 — stdout/stderr excerpts for failure-mode commands. When a
command's audit entry would recordexit_code != 0,policy_result == deny, ortimed_out == true, doit now captures up to 4096 bytes of
stdout and stderr into newstdout_excerpt/stderr_excerptfields.
Configurable viaaudit.capture_output(always/on_failure/
never, defaulton_failure) andaudit.output_excerpt_bytes. UTF-8-
safe truncation with[…truncated, total N bytes]marker. New
RedactOutput() boolmethod oncap.Capabilityis forward-compatible
scaffolding for sensitive-command exclusion (no capability sets it
today). -
🎯T38 —
doit_audit_queryMCP tool. Filter-based postmortem lookup
replaces tail-by-count as the primary primitive. Filters:policy_result,
policy_level,rule_id,cwd_substring,project_root,since
(RFC3339 or relative duration like1h),until,exit_code(number
or"nonzero"),cap,command_substring,parent_seq,limit
(default 20, max 200).latest=truereturns the single most-recent
match — the primary postmortem path.include(l3/excerpts/
elicitation) opts into the heavy fields; default response strips
them to keep result size sane.
Documentation
agents-guide.mdandREADME.mddescribe the newdoit_audit_query
workflow with concrete usage examples ("the last thing doit refused",
"all L3 escalations in the last hour with prompt + response", "the
elicitation chain that created rule X").STABILITY.mdsnapshot bumped to v0.9.0; the postmortem-tooling batch
is recorded as a closed pre-1.0 gap. Field-level annotations on the
new audit fields and config knobs remainNeeds reviewuntil the
schema settles through real-world use.
v0.8.0
doit v0.8.0
Threat-model-driven safety improvements — three pre-1.0 follow-ons to the
v0.7.0 threat model land in this release, plus per-project anomaly calibration
and a recoverability-aware rm tier.
Added
-
🎯T33 —
doit_check_configreports the full safety contract. The tool
now surfaces all seven load-bearing settings the threat model names, with
stable §N markers tying each result back to
docs/threat-model.md.[FAIL]for missing Bash
deny-list / doit registration;[INFO]/[WARN]for sibling MCP servers,
dangerous-tier state, policy-store permissions, L3 model overrides, and
per-project config presence. Settings weakened from defaults are now
visually distinct from informational items. -
🎯T34 — Startup warning for sibling MCP servers with execution-adjacent
primitives. doit emits a warning at MCP-server startup when other
registered servers expose shell execution, file-write+chmod, language
runtimes, or HTTP-to-localhost patterns that bypass doit's policy engine.
Suppressible per-server via the new
policy.acknowledged_sibling_servers: [...]config field. Backed by a
classification heuristic in the newinternal/mcpinventorypackage. -
🎯T35 — L3 prompt-injection surface enumerated, hardened, and tested.
Newdocs/l3-injection.mddocument enumerates
every untrusted input flowing into the L3 prompt with per-input trust
level, position, mitigation, and gap classification. The L3 prompt
template now wraps every agent-supplied field (command, cwd,
justification, safety argument, session scope, session description) in
XML data tags with full XML character escaping, and instructs the model
to treat tag contents as data only. A 10-payload prompt-injection
regression corpus lives ininternal/llm/testdata/injection_corpus.yaml
and is exercised by the renderer test on every CI run.
Changed
-
🎯T29 — Learned duration statistics keyed per-project. Duration
aggregation now keys on(cap, subcmd, project_id)rather than the
global(cap, subcmd), so a small repo'smake testpercentiles no
longer pool with a monorepo's.project_idderives from the project
root path; commands without a project context fall back to a shared
bucket. Eliminates a class of false-positive anomaly flags in both
directions. -
🎯T30 —
rmtier reflects reversibility via git-tracked status. A
non-recursivermagainst a git-tracked file is now evaluated as
write-tier (recoverable viagit checkout HEAD -- <path>) rather than
dangerous-tier. Untracked files, recursive removes, and paths outside any
git repo remain dangerous. Hardcoded catastrophic rules
(deny-rm-catastrophic) still fire regardless of tier.
Documentation
docs/threat-model.mdupdated to reflect the runtime affordances landed
in T33–T35; the §3 "user's responsibility" framing now points at the
reporting/warning thatdoit_check_configand the startup warning
provide.STABILITY.mdsnapshot bumped to v0.8.0 with the new
acknowledged_sibling_serversconfig field, the per-targetrmtier
table, the project-keyed duration aggregator, and a new pre-1.0 gap
noting the missing NOTICES / third-party attribution file.
v0.7.0
Added
-
doit --help-agent(🎯T28) — prints the CLI reference followed
by the full embeddedagents-guide.md. Closes the pre-existing gap
noted in the v0.6.0 deferred list so coding agents can pull both
the CLI reference and the domain guide in a single call without
having the repo checked out.Embedding is compile-time via
go:embedfrom a new top-leveldoit
package at the module root — a deliberate workaround for
go:embed's no-parent-directories rule that avoids a pre-build copy
step.
Upgrade
Additive; no breaking changes. Safe to upgrade in place.
brew update
brew upgrade marcelocantos/tap/doitv0.6.0
Highlights
🎯T27 — Shell-script content-hash approval gate
doit now asks for explicit user approval the first time it sees a
bash foo.sh, sh foo.sh, zsh foo.sh, or ./foo.sh invocation,
keyed by SHA-256 of the script's contents. Subsequent invocations of
the same content bypass the prompt; modifying the script changes the
hash and forces re-approval. Approvals live at
~/.config/doit/script-approvals.yaml.
- Tier-0 gate: runs before L1/L2/L3.
- MCP elicitation shows the path, size, hash, and a content preview.
- Audit log carries
script_hash/script_pathon every matched run. - New MCP tools:
doit_approvals_list,doit_approvals_revoke. - Scope is deliberately narrow — pipelines, compound commands, and
bash -c "…"fall through to normal policy.
🎯T26.1 — Time expectations + timeout enforcement
doit_execute and doit_dry_run accept two optional fields:
timeout_seconds— hard ceiling. doit kills the entire process
group on expiry (SIGKILL, exit code 137).expected_duration_seconds— soft estimate, recorded alongside the
actual duration in the audit log.
New audit fields: expected_duration_ms, timed_out.
🎯T26.2 — L1 rules can inspect time expectations
Starlark rules may opt into request metadata by declaring a third
meta parameter on check. Existing two-parameter rules are
unaffected. The new built-in rule flag-duration-mismatch flags
sleep N commands where N exceeds 2× expected_duration_seconds.
🎯T26.3 — L2 learns per-pattern durations
doit aggregates p50/p95 durations per (cap, subcmd) from the audit
log and persists them at ~/.config/doit/duration-stats.yaml. Two
new bypassable L2 rules use the learned distribution:
duration-anomaly—expected_duration_secondsbelow p50/5 or
above p95×5 for a pattern with ≥5 samples.timeout-too-short—timeout_secondsbelow learned p50.
Both are skipped under --retry. Inspect with the new
doit_durations_list MCP tool.
Also in this release
- 🎯T17 — Engine now treats commands as opaque strings (segments/tiers
audit fields deprecated, retained for reader compatibility). - 🎯T20 — Dead tier code removed.
- 🎯T22 — Sessions can start when L3 is disabled.
- 🎯T25 —
deny-rm-catastrophiccovers system dirs and globs.
Upgrade notes
No breaking changes to the MCP tool surface, engine API, config
schema, or audit log format. Additive only. Safe to upgrade from
v0.5.0 in place.
brew update
brew upgrade marcelocantos/tap/doitDocumentation
- STABILITY.md — full v0.6.0 interaction surface snapshot
- agents-guide.md — updated with script-hash trust model, time expectations, and duration learning
v0.5.0
Major architectural simplification and feature expansion for doit's MCP server.
Added
- Work sessions —
doit_session_start/_end/_statuslet an agent declare the scope of a chunk of work. L3 evaluations inside the session reuse the scope for faster, more contextual decisions. Sessions auto-expire. - Two-tier L3 cascade — fast triage on sonnet with fall-through to opus for genuinely ambiguous cases. Most commands resolve at the fast tier; opus is reserved for the hard ones. Configured via
policy.level3_fast_modelandpolicy.level3_model. - L2 policy management —
doit_policy_list,doit_policy_delete,doit_policy_reviewfor inspecting and curating learned policy entries. doit_self_audit— detects L1/L2 contradictions, stale entries (90+ days), orphaned Starlark rule IDs, and duplicate L2 coverage.doit_repo_read— allowlisted read-only access to project metadata files (go.mod,Makefile,CLAUDE.md, etc.) for L3 claim verification.doit_check_config— verifies the MCP-first deployment (Bash denied, doit registered) so misconfigurations surface immediately.- L3 enabled by default — new installs get the live LLM policy tier out of the box.
Changed
- Pipeline parser removed — doit no longer tokenises commands into segments at the engine level. The shell handles all composition (
&&,|,;, redirects); commands pass throughsh -cunchanged. Segment analysis, where it still happens, is an internal detail of individual policy layers. EvalResult—SegmentsandTiersfields removed. The dry-run output no longer displays them.Engine.RecordDecision— signature simplified to(command, decision); cap/subcmd match criteria are derived from the command string directly.- L3 rebuilt on
claude -p— the persistent claudia Session integration is gone. Every L3 call is now a stateless one-shotclaude -pinvocation, fixing a hang caused by Claude Code's/clearrolling the session ID. - Stderr logging suppressed — doit discards its own log output so MCP clients don't interpret informational messages as errors.
Fixed
- L3 init race: the engine now constructs L3 synchronously in
New, sodoit_session_startcan no longer fire before L3 is ready. claude -pno longer leaves PTY wrappers or JSONL tailers lying around after a broken session.
Docs
STABILITY.mdrefreshed to a v0.5.0 snapshot covering all 16 MCP tools, session APIs, and the L3 cascade.CLAUDE.mdarchitecture map updated (removedinternal/pipeline/, addedinternal/context/).- README and
agents-guide.mdtool tables completed.
v0.4.0
Changed
- Error messages updated: Config rule denials now say "(config rule, bypassable)" instead of referencing the removed
doit --retryCLI flag - agents-guide.md rewritten: Now documents MCP tools (
doit_execute,doit_dry_run, etc.) instead of the legacy CLI interface - README.md rewritten: Documents MCP server architecture,
claude mcp addquick start, MCP tool reference, and elicitation-based policy decisions
Removed
- All references to legacy CLI syntax (pipelines, unicode operators,
--retry,--list,--auditsubcommands) from user-facing documentation
v0.3.0
Changed
- Single binary:
doit-mcpanddoitconsolidated into a singledoitMCP server binary. The legacy CLI (internal/cli/) has been removed — all functionality is now MCP tools.
Added
- MCP elicitation for policy decisions: When the policy engine escalates or hits a bypassable rule, doit presents an interactive dialog to the user with four options: Allow once, Allow always, Deny, Deny always. Replaces the old
--retryflag mechanism. - Two-phase rule promotion: "Always" choices trigger a follow-up elicitation proposing Starlark rules at narrow/moderate/broad generality levels. Users pick a rule to create or decline.
- L2 learned policy recording: "Allow always" and "Deny always" decisions are immediately recorded in the L2 policy store for future automatic matching.
- Admin MCP tools:
doit_list_capabilities(with optional tier filter),doit_audit_verify(hash chain integrity check),doit_audit_tail(recent entries) Bypassablefield on policy results — propagated from L1 Go rules and Starlark rules through toEvalResult
Removed
- Legacy CLI binary (
cmd/doit/old entry point) internal/cli/package (subcommand handlers)--help-agent,--list,--audit,--policyCLI subcommands (replaced by MCP tools)
Dependencies
mcp-goupdated from v0.44.1 to v0.47.0 (elicitation support)
v0.2.0
Added
- MCP server (
doit-mcp): stdio-transport MCP server as primary agent interface with 4 tools (execute,dry_run,policy_status,approve) - Three-level policy engine: L1 deterministic rules → L2 learned patterns → L3 live LLM evaluation
- Starlark L1 rules: sandboxed, deterministic rule language with embedded test cases and L3→L1 promotion (
internal/starlark/) - Per-project policy:
.doit/config.yamlwith tighten-only merge semantics — projects can add rules and restrict tiers but not loosen global policy sh -cexecution model: commands execute via shell instead of per-capability runners- CI workflow: automated build, vet, and test on push/PR to master
- Comprehensive test coverage: all core packages tested (
internal/cap/,internal/cap/builtin/,internal/cli/,internal/config/,cmd/doit/)
Changed
engine/package is now the primary public API for command evaluation and execution- Audit logger enforces
max_size_mbconfig limit (warns and stops writing when exceeded) doit-mcpbinary now included in release artifacts alongsidedoithasAnyFlagdeduplicated (exported frominternal/rules/, shared by policy engine)- Malformed audit log entries now produce warnings in
Tailinstead of being silently dropped - Token store purges expired tokens on each
Validate()call - SPDX Apache-2.0 license headers added to all Go source files
Removed
- Legacy daemon/client/IPC code (~2,454 lines):
internal/daemon/,internal/client/,internal/ipc/ - Pipeline execution engine (
internal/pipeline/executor.go); parser retained for policy evaluation DaemonConfigand--daemonCLI subcommand- Dead
resolveErrorfunction and--approvedCLI documentation (approval handled by MCP server)
v0.1.0
Added
- Capability broker mediating all command execution through safety tiers (read, build, write, dangerous)
- 19 built-in capabilities: cat, chmod, cp, find, git, go, grep, head, ls, make, mkdir, mv, rm, sort, tail, tee, tr, uniq, wc
- Pipeline syntax with Unicode operators (
¦,›,‹) that survive unquoted in all shells - Compound command operators (
&&,‖,;) for conditional chaining - Per-subcommand tier mapping for git and go
- Argument-level safety rules (hardcoded and configurable) with
--retrybypass - SHA-256 hash-chained audit log with integrity verification
- YAML configuration for tiers, audit path, and custom rules
- Agent integration guide (
doit --help-agent)