Changelog
Current release: 2.8.4, 14 October 2026.
Deviation gate hint: it now says that config.json, profiles, settings and CLAUDE.md open from a prompt ('edit my profile') and that personal.md changes only when the user edits it, instead of implying every config file opens.
New balance rules (equal cards part by part, no dead space in a frame, one dropdown arrow, gauges are speedometers) in
modules/line-balance/GUIDE.mdandALWAYS.md;web_balance.jsreportsUNEVEN-PART,DEAD-SPACE,NATIVE-SELECT,GAUGE-RING, with fixtures and aweb_partsselftest group. Workflow: keep / merge / drop table before replacing a working generator or page set.Text check fixes: fenced code in Markdown is no longer linted as prose, and a task checkbox (
- [ ]) no longer counts as the opening word, so plans with code and checklists stop raising false REPEATED OPENER blocks.Fix: the request ledger path is pinned per session (state
ledger, first computed by the router hint or found by a lookup), so a cwd that moves into another git repo no longer makes Stop report the ledger missing or SessionStart and the router lose it; with nothing pinned, the lookup also walks up the parent folders of cwd (up to $HOME). The router hint prints the pinned absolute path and the.git/info/excludeentry follows the ledger's own repo.Fix: Adams never edits or deletes files that hold secrets: the history scrub and the automatic removal of stray .env copies are gone; cleanup skips any folder that holds a .env file.
adams clean. Frees disk safely: hourly (belowgroups.hygiene.floor_gbfree it runs the nightly set at once), nightly (moves regenerable, untouched, in-no-use items from a fixed allowlist to the Trash), weekly (a numbered list of merged worktrees and contained branches;--approve 1,4,7acts on those numbers after re-checking). No symlinks, protected globs,--dry-runeverywhere, a JSON line per item inclean.log. Moved items get anadams-Trash name and are recorded; the nightly run permanently removes recorded entries older than 7 days and the hourly run below the floor removes all of them, so the disk really recovers. Other Trash entries are never touched. The freed figure is the change in free disk space.adams hygiene. Report-only security checks on a schedule: stray.envcopies, public repositories, token scopes, secrets in shell history and unpinned package sources in tool configs. Findings show a fingerprint, never the value.Leak guard and output scanner.
hooks/adams_secrets.pydenies a command that would print a secret (PreToolUseonBash) and scans tool output for token shapes (PostToolUseon every tool), recording only fingerprints and asking you to rotate once per fingerprint. Notices print once at the next session start.adams schedule install|uninstall|status. Four user LaunchAgents (com.adams.clean-hourly,com.adams.nightly,com.adams.daily,com.adams.weekly) run clean and hygiene; install unloads the old cleanup jobs listed ingroups.hygiene.replace_jobs(files kept) and supports--dry-run.adams doctorshows one optional row for it.adams install --linkregisters the hooks that were missing from its list (leak guard, output scanner, agent time box onSubagentStartandPreToolUse, verification record on web tools); a selftest now compareshooks/hooks.jsonwith it.Docs:
modules/workflow/ references/ hygiene.md. Fix: the weekly remote report runs every
wranglercall in a temp folder created per run and removed afterwards, so.wrangler/cacheis no longer left inside a repo or inscripts/.Fix: the Trash purge never lists
~/.Trash(macOS blocks that without Full Disk Access) and only touches exact recordedadams-*paths; an entry it may not remove is logged with the reason, counted as skipped (no permission) and reported once per run with the fix (give the launcher's terminal or/bin/shFull Disk Access, or empty the Trash by hand). Not tested under launchd.Speed rule.
ALWAYS.mdcarries one line (asked-for part first, cleanup later, narrow agents of about 15 minutes, parallel); the full rule ismodules/workflow/references/speed.md: report the asked-for result the moment it is verified, run optional cleanup as a separate later job, give each agent one outcome and a time box, run independent steps in parallel, never re-run a check that passed on an unchanged file.adams syncalready mirrorsALWAYS.mdto Copilot CLI.adams stats. A read-only report from the session transcripts: calls, context size, tool and agent minutes, and corrections per session (--last N,--project DIR,--json). Compare before and after a change.Faster
adams checkon pages.--jobsruns the pages in parallel (default min(4, cpus/2); measured 2.6x on a 30-page crawl, 1:47 to 0:41).--failedrescans only the flagged url and width pairs of the last run and prints PARTIAL, never CLEAN; it is recorded as partial, so it never counts as a green verification. CAUSES groups hits by selector (for example 236 ORPHAN hits onpbecome one line).check.pykeeps the last report per target in the temp folder.Agent time box.
hooks/adams_agent_box.py(SubagentStartandPreToolUse) warns a subagent at 60% of the box and denies writes at 20 minutes; read-only Bash and one verification command stay allowed so the agent can verify once and report.ADAMS_AGENT_BOXsets the minutes, 0 turns it off.Request ledger. A multi-ask prompt (list items, two questions, several long lines or over 300 characters) gets a hint to keep
.adams/sessions/<session>.md: aGoal:line and one- [ ]line per ask, closed with[x]and evidence or[-]and a reason. The folder is excluded locally through.git/info/exclude, so it is never committed. The Stop hook blocks once on open asks (not those parked with(waiting: ...)or(next: ...)) and once when a multi-ask session changed files and left no ledger. It does not block while the last message asks the user a question (a trailing?or؟, or anAskUserQuestionturn); the block can fire on a later Stop.SessionStartreloads the goal and the open asks (30 lines at most) after a restart or compaction.ADAMS_STOP=0andADAMS_GATES=0opt out.Repeated-defect hint. A prompt with still, repeatedly or same problem or issue (or the Arabic words for still, again and again, and the same problem) adds one line per session: fix the whole class, then add a regression check under
.adams/checks/. "Again" alone and the Arabic "tani" are not matched, so "run it again" and a request to think again stay silent.Deploy then live check.
hooks/adams_verify_record.pydetects a deploy command (wrangler, vercel, netlify, firebase, fly, supabase functions, or a package script named deploy or release) and records it. Live evidence is acurl,adams check, browser navigation orWebFetchon a non-local URL after the deploy. The Stop hook blocks once per deploy until that evidence exists.ADAMS_STOP=0andADAMS_GATES=0opt out.Project regression checks. A script in
.adams/checks/exits non-zero while its defect exists;adams checks [DIR]runs them all in name order. When the folder holds a check,adams checksjoins the commands the Stop and commit gates require, like the project's tests, so a fixed defect cannot come back.Fast selftest by default.
scripts/selftest.pyskips the slow groups (web_routes,scorecard, the PDF render; the browser and LibreOffice work, about 4 of the 4.5 minutes of a full run) and finishes in about 50 seconds, printingselftest OK (fast: N browser groups skipped, run --full).--fullorADAMS_SELFTEST=fullruns everything and printsselftest OK (full);--timesprints a per-group table. Failures exit 1 in both modes. CI (selftest.yml,release.yml) andscripts/release.pyalways run--full.The verification gates know the mode.
hooks/adams_verify_record.pyrecordsfastorfullfor a selftest run, and when a session changed a file inSLOW_PATHS(hooks/adams_gates.py: the JS checkers,scripts/check.py,scripts/selftest.py,scorecard/*) a fast green no longer satisfies the Stop hook or the commit gate: they ask forpython3 scripts/selftest.py --full. Other changes are satisfied by a fast green.Config words. The self-disabling gate denied every write to the user's config (the Adams config folder, the Claude settings files, both CLAUDE.md files, a project settings file with hooks, the plugin cache) and its message said the referee words (ci, workflow, threshold, snapshot, selftest) open it, which they never did: those words only open the referee check. Now each config file has its own words, said by the user in a prompt of the session: a verb (
edit,change,update,modify,set,add,enable,turn on, or the Arabic equivalents) then within 40 charactersprofile(opens the profiles andconfig.jsonof the Adams config),settingsorsettings.json(opens the Claude settings files) orclaude.md(opens the CLAUDE.md files). The router records only the matched names in its session state (config), never the prompt. The plugin cache, the rest of the Adams config folder,ADAMS_*=0and the router state file are never opened by words; the router state file is now protected, so an agent cannot write its own permission. The denial names the right words. Selftestdeviation_gates15b covers a denied write, the English and Arabic words,workflowthat does not open a profile, one name that does not open another, a prompt that mentions the name without a verb, and the cases that never open.Ship loop:
adams ship PR [TASK [NEXT]],adams ship all(the/shipslash command in the newcommands/ship.md),adams nextandadams watchin the newscripts/ship.py, plusadams track set FILE ID STATUS --evidence TEXTand an optional- depends:task field (lint checks unknown ids, self references and cycles).shipwaits for the fast checks with onegh pr checkscall per poll (10, 20, 40, 60 second backoff, 45 minute cap), skips the checks listed inskip_checks, never merges a PR whose base is not the project base branch, never passes--adminor force, asks once whether to merge automatically (ASK auto_merge, exit 3, answered with--set), and stops for a yes on high-risk PRs (migrations, auth, payments, env files, CI config, deletions; exit 4).allcommits only the files this session wrote (by name, through the commit gate), lists the rest and never adds them, and prints exactlyShipped:andLeft:. Settings live in the optional.adams/ship.json. Newmodules/workflow/references/execution-loop.md(worktree per task, no stacking, hand-off block, CI path filters).adams installlinks the command for clone installs and skips the link when the plugin is enabled. Selftest runs the whole flow against a fakeghand a temp git repo with a bare origin, no network.Own-write attribution. Two sessions in one folder could block each other: session A's Stop hook demanded a selftest for files that session B had changed after A's own edit, because the touched state was a plain list of paths.
hooks/adams_verify_record.pynow records{path: sha1}right after each write (edit tools and write-like shell commands), and the newmine(sid)inhooks/adams_gates.pyreturns only the paths whose content still equals the recorded hash; the Stop text, verification and small-task checks use it. A file another writer changed is not this session's until it writes it again; a file this session deleted counts, one another writer deleted does not. State written by an older version (a list) still loads. Selftest covers write, external change, rewrite, the old list format and both delete cases.Co-Authored-By trailer gate, off by default. A profile with
"groups": {"forbid_coauthor": ["Claude", "noreply@anthropic.com"]}makes the commit gate inhooks/block-risky-git.pydeny agit commitwhose message (-m,--message, heredoc,-F file, orHEADon--amend --no-edit) has a matchingCo-Authored-By:line (case-insensitive substrings). Shipped profiles do not set it. Selftest uses a temp profile: a listed trailer is denied, another co-author passes, no setting orADAMS_GATES=0passes.COVERno longer flags a bar fixed to the bottom edge for sitting on the fold at scroll 0. A phone tab bar (full width, under 20% of the viewport tall, anchored at the bottom) covers whatever content happens to be at the fold on any page, and that content scrolls clear of it. The rule moved to the end of the page: after scrolling to the bottom, nothing may be left under the bar. Top bars and sticky headers keep the scroll 0 test. Selftest addscover_tab_goodandcover_tab_bad.SUBLINEskips a paragraph that sits beside its heading. A two-column row (label left in a grid or flex column, text right) was flaggedstart-offbecause the paragraph starts where the second column does; the rule is about a subline under its heading. A paragraph whose left edge is at or past the heading's right edge and that shares its vertical band is not checked. Selftest addssubline_cols_good.MARKERx-offno longer compares markers across a line. Rows laid side by side (a flex strip of logos, a nav of buttons with chevrons, a grid) were compared with the first row, so every horizontal list of 3 or more icon-plus-label items flagged (70 hits on one home page). When any two rows share a horizontal band, each row is now compared only with the first earlier row in its own column (same left edge, 2px); a pure vertical list still compares every row with the first. A row-direction flex container counts as a flow too, so a centred wrapping strip whose items land one per line on a phone is not read as a column. Selftest addsmarker_strip_goodandmarker_wrap_good.Table insets in scaled mockups.
TABLE(inset-x,inset-y) inpage_checks.jsandEDGEinweb_balance.jsmeasured a table inside a preview drawn at full size and scaled down (CSS transform or zoom) in screen pixels, so a 24px inset scaled to 0.5 read as 12px and the fix was to dodge the check with ARIA divs. Insets are now divided by the cumulative scale of the table's ancestors. Selftest addstable_scaled_good.Verification recording sees wrapped commands.
VERIFYinhooks/adams_gates.pyonly acceptedVAR=valuebefore a test, build, typecheck or lint command, sotime python3 scripts/selftest.pywas never recorded and the commit gate blocked a commit that had a green run. A command at the start of a segment (after;,&&,|,cd DIR &&) may now be preceded byVAR=value,env,time,nice,timeout N,caffeinate,nohup,command,execorxvfb-run, andbunx,pnpm exec,pnpm dlxandyarn execcount likenpx.echo pytest,grep -r test .andcommand -v pytestare still not recorded, and theADAMS_*=0deviation check is unchanged. Selftest records and refuses a list of wrapped and non-verification commands.Hooks follow
cd. The gates took their base folder from the payloadcwd(the session folder) and ignoredcd DIR &&in the command, so from a session folder that is not a repo a shell write aftercd reponever reached the touched list, a test run aftercd repowas never recorded as verification, andcd repo && git commitskipped every commit gate (confirmed with a test before the fix: exit 0 where the in-repo commit is denied). One helper,cmd_base(cmd, cwd)inhooks/adams_gates.py, moves the base by everycdandpushdbefore the relevant part of the command (quoted paths,~and$VARincluded), andgit_caddsgit -C DIR. Used bybash_targetsandbash_written(touched list, align gate, router, deviation gate),adams_verify_record.py(verification records the repo the run was in),block-risky-git.py(commit gate, commit message file,rm -ragainst the repo of each path) andadams_deviation_gate.py(deletions, the Adams-repo exemption of theADAMS_*=0check). The Stop text check also looks in the repos of the files the session wrote, not only in the session folder. Selftestcmd_baseruns these from a temp parent folder that is not a repo.The Stop figures check counts work done by subagents: the Bash commands and outputs in
<transcript>/subagents/agent-*.jsonlare evidence like the main thread's (their own words are not), so a figure quoted from a delegated run no longer blocks. Same 50 MB cap per file. Selftest has the case with and without the subagent file.web_balance.jsnow defaults--minto 0.3, the web floor in the canonical table ofmodules/line-balance/GUIDE.md(it was 0.5, which flagged web last lines of 30% to 50% that the rule allows). File checks (line_balance.py, pptx, pdf, docx) keep 0.5.Page checks: eleven new web hit types run at every width in
web_balance.js(rules in the newmodules/line-balance/scripts/page_checks.js), each with a broken fixture that must flag and a correct twin that must stay clean in selftest.PLACEHOLDER(lorem ipsum,TODO,FIXME,TBD,{{ }},undefined,NaN,null,[object Object],${in visible text),COUNT(a heading that states a count above a list with another number of items),GAPandGAP-RHYTHM(sections closer than 12px, more than two different gaps between sections),TABLE(number columns end aligned with tabular figures, text columns start aligned, header on its column, content 16px from the frame),SUBLINE(a paragraph shares its heading's start edge and is no wider than a width-limited heading),THIN(main content under 55% of a 1280px or wider viewport),A11Y(contrast against the nearest opaque background, 44x44 touch targets at 480px and narrower,imgwithoutalt, heading level skips, no visible focus style on Tab),BROKEN(same-site links answering 404, images that failed to load, console errors, uncaught page errors; file:// targets must exist),COPY(U+2014 and U+2013, exclamation marks in headings, buttons and labels, Title Case headings),COVER(a fixed or sticky element covering text or controls at scroll 0, arole=dialogwithoutaria-modal, an anchor target under a sticky header),RTL(unmirrored direction icons,text-align: leftandfloat: lefton RTL text). Hit lines carry the measured numbers.check.pyprints aHITS: TYPE n, ...line before the verdict, shows the last 6000 characters of a check instead of 1500, and serves an.htmlfile from the nearest parent folder where its/root-relativeassets exist, so a page inside a builtdist/is checked with its CSS and links instead of unstyled.Agent deviation gates, so an agent cannot reach green by weakening the referee. New
hooks/adams_deviation_gate.py(PreToolUseonBash|Edit|Write|MultiEdit|NotebookEdit, 5 second timeout, registered inhooks/hooks.jsonandbin/adams): test tampering (skip and only markers, deleting or emptying a test file, net removal of assertions), silencing errors (@ts-ignore,@ts-nocheck, bare@ts-expect-error,eslint-disable,# type: ignore,# noqa,//nolint, newany, configs that loosen strictness), gaming checks (CI workflows, thresholds, snapshots,.adams/config.json,scripts/selftest.pyoutside the Adams repo; open after a prompt naming ci, workflow, threshold, snapshot or selftest, which the router records as words only), self-disabling (ADAMS_*=0in a command, writes to the user's Claude and Adams config, CLAUDE.md and the plugin cache), and scope (adams decide --scope "glob,glob").hooks/block-risky-git.py: deniesgit commit --no-verifyand-n,--force-with-leasetomainormaster,rm -ron the repo root or a tracked folder, SQLDROPandTRUNCATEthrough a database client,supabase db resetandprisma migrate reset; the commit gate also denies staged files outside the recorded scope and leftovers in added source lines (console.log(,debugger;,print(, newTODO,FIXME,XXX, mock data in production paths), each with file and line.hooks/adams_stop.py: blocks once when a--smallsession grows past 3 source files or 80 changed lines, and once when the final message carries figures (percentages,10x,5 ms,N tests,all tests pass,CLEAN,score N) that no command output of the session shows.adams decidenow writes- YYYY-MM-DD HH:MM:SS: ...bullets (the time lets the gates tell this session's decisions from older ones) and takes--scope "glob,glob". Link installs made earlier needadams uninstallandadams installto register the new hook.Selftest
deviation_gateshas a denied case and an allowed twin for every gate, including the router word store, the scope session rule, the destructive command list, the leftover allowances, and the figures check with a fake transcript.ORPHANcounts inline-block chips: an inline-block inside a text block (a code span styled as a chip) is part of its line, so a last line made of a wide chip and a full stop is no longer read as the stub.. Selftest has the case (chip_good.html).Web balance catches broken diagrams that passed with only STRESS hits. New hit type
DIAGRAM: in a container with 3+ absolutely positioned text nodes or a large inline SVG, text boxes, positioned boxes and SVG shapes (including marker arrowheads) closer than 8px, overlapping, or outside the container's box are flagged (a label in its own card, the background ring and shapes of one SVG are exempt). New hit typeMARKER: in 3+ repeated rows with a small marker or round numeral badge, marker centres must share one x (1px), sit on the first text line's centre (2px), and a connector (pseudo-element of the list or a row, or a thin element) must run through the marker centres and, at list level, start and end on the first and last one. Both count inFLAGGED.WRAPPEDroot cause fixed: an element with own text and block children (a flex node holding a numeral and a bare label) was never measured, because the text was in no text block; its own text is measured now. A short label in a flex row or an absolutely positioned node was also never treated as short (only tags, lists, buttons and pills were), so a label such as "The person opens one" wrapping to two lines passed or showed as ORPHAN; up to 12 words with no sentence punctuation now count as WRAPPED there.UNEVENalso compares sibling diagram nodes (same container and class, absolutely positioned or flex) that differ in line count, even when their tops differ.Selftest has an old (must flag) and a fixed (must not flag) fixture for each: arrows touching cards around an SVG ring, dots off a timeline and top aligned, and a wrapping numeral plus label in a flex node and in an absolute node. A full check of the Adams site (
/,/adams,/adams/installat 375, 768 and 1440,--min 0.3,--stress) stays CLEAN.Shell writes are gated like edits: the align gate (
hooks/adams_align_gate.py) is now also registered onPreToolUseBash. A write-like command (redirect,tee,sed -i,perl -pi,mv,cp, a script opening a file for writing) that names a source file in a git work tree is denied untiladams decideruns, with the same allow rules as an edit (docs,.adams,.planning, the Claude scratchpad, non-git folders). Read-only commands, tests, builds and git commands never trigger it. The router (hooks/adams_router.py) runs the same path rules (auth, UI, tests first, prose) on the files a write-like Bash command names, and a shell-written test file counts as a test edit. New helperbash_targetsinhooks/adams_gates.pyfinds the targets before the command runs. Link installs made earlier keep the old matcher untiladams uninstallandadams installare run again. Shortcut: for non-redirect writes any source path in the command counts, even one it only reads (cp src/a.js /tmp/x).Stop check sees shell edits:
hooks/adams_verify_record.pyalso adds the changed files that a write-like Bash command names (redirect,tee,sed -i,perl -pi,mv, a script that writes a file) to the session's touched list, so code changed through the shell and never verified now blocks the stop. Before, such a session had an empty list and was never checked.Scorecard fixes after the first run: the checks now count shell writes (
cat >>, a Python heredoc,perl -pi) as edits in any path form, and order an edit and a test run inside one command. Re-scored offline, the first run goes from 93.8 to 100. Newscripts/scorecard.py --rescore DATEre-runs the checks on saved results without model calls;--runkeeps each repo underscorecard/results/<date>-repos/and records hook events (--include-hook-events) in the transcripts.Stop check scoped to this session:
hooks/adams_verify_record.pynow also runs afterEdit,Write,MultiEditandNotebookEditand appends each file path toadams-touched-<session_id>in the temp folder.hooks/adams_stop.pychecks only the.mdand.txtfiles and verifies only the source files this session wrote, so a session is never blocked on files another live session edits in the same folder (foreign changes are not reported). Without a session id or a touched list the Stop hook never blocks. The align gate no longer stores a tree snapshot for the Stop check. Link installs made earlier keep the oldBashmatcher on that hook untiladams uninstallandadams installare run again.Optional modules moved out of core into a second plugin,
adams-extras(plugins/adams-extras/):innovation-builder,seo-architect(withai_search_audit.py) andobsidian-vault-memory, moved with their history. CoreSKILL.mddrops those rows (description 629 to 532 characters,adams tokensSKILL.md 1603 to 1426, typical text task 7597 to 7420) and keeps one pointer line;scripts/release.pybumps both manifests; selftest fails if core names a moved module or the two manifests disagree on the version.Context router:
hooks/adams_router.pyadds a short guidance block by context with fixed rules (no AI, no network). Triggers: a bug or error prompt or a failed test run (diagnose), "I don't understand" (plain language), an edit to an auth, session, token or secret path (security checklist), an edit that adds a dependency (cost check), a UI file edit (adams checkat three widths), the first source edit with no test yet (tests first), an edit to published copy (minimum effective edit). Each rule fires once per session, at most two blocks per call, 600 characters each. Registered onUserPromptSubmit,PostToolUse(Edit|Write|MultiEdit|Bash) andPostToolUseFailure(Bash), 5 second timeout. Opt out withADAMS_GATES=0.Commit review gate: the first
git commitof a session that stages source is denied once with a review request (correct, safe, holds under load, tested, fast, lean); the retry passes. Opt out withADAMS_REVIEW=0.Feature test gate: a commit message starting with
feat,addorimplementthat stages source must also stage a test file, like thefixrule.Selftest covers each router rule, once per session, silence, opt-out, garbage input, the review gate and the feature test gate.
Stress mode:
web_balance.js --stressmutates a copy of the live DOM (twice the words, a 40 character unbroken token, 9-digit numbers, blanked lists), reloads between passes, and reports layout breakage only as hit typeSTRESSwith the mutation kind and a reason (page overflow, child past its parent, text past its own box, clipped text, overlapping sibling text). Breakage that exists before any mutation is reported once as kindas-is. Stress runs at widths 375 and 1440, at most 30 elements per pass, and is skipped above 20 pages unless--stress-all.adams checkpasses--stressfor.htmlfiles and URLs;-- --no-stressskips it. Selftest has a nowrap chip that must flag and a wrapping page that must not.Real-task scorecard:
adams scorecardandscripts/scorecard.pywith 8 programming tasks underscorecard/tasks/(asks before building, bugfix with a regression test, tests first, no scope creep, secret guard, verify before done, layout overflow under stress, dependency restraint). Each has a fixture project, a prompt and a hidden deterministic check.--dry-run(part of selftest, no model calls) proves each check fails on the untouched fixture and passes on its golden solution;--run [--tasks] [--runs] [--max-cost]runsclaude -pwith the user's real configuration, prints a table and a score out of 100, and writesscorecard/results/<date>.json(git-ignored). A run costs about $0.15 to $0.70 per case.Adams stands alone: no content file names another skill, plugin or third-party project. The routing table to outside skills and the paragraph about installing them are removed, that doc is now
docs/PIPELINES.md, and third-party license notices live only inNOTICE.adams selftestfails if a tracked file other thanNOTICEnames one.Hard gates as hooks, so the rules hold when the prompt is ignored. Align gate: the first code edit of a session is denied until
adams deciderecords the decisions (oradams decide --smallthe one assumption). Verify gate: test, build, typecheck and lint runs are recorded with a working tree fingerprint, and the Stop hook blocks once when code changed since the last green run. Commit gate:git commitis denied for a staged secret or.envfile, afixcommit without a test, and source changed since the last green run.New
adams decide [--small] TEXTcommand appends a dated bullet to.adams/decisions.md. New shared helperhooks/adams_gates.py.Opt-outs:
ADAMS_GATES=0(all gates),ADAMS_VERIFY=0(verification only). Every deny message ends with its override.The git guardrail hook timeout is 20 seconds (was 5) because the commit gate reads the staged diff.
ALWAYS.mdno longer says to ask only for money and irreversible actions: open decisions, taste and access are asked first.Selftest runs each gate as a hook against a temp git repo.
Web balance classifies short text by rendered role, not class name. The
[class*=badge|chip|pill|tag]match is gone (astagecardholding a paragraph was flagged WRAPPED, and agents renamed classes to hide it). Short means a short-text tag, a list, button, label, table header, nav or tab role, or a chip by rendering (inline-block, inline-flex, inline-grid, or a painted pill) with 6 words or fewer. A paragraph is never short.New hit type
SHRUNK: an element whose inlinefont-sizea script changed after load. Scripts that shrink type until copy fits one line hid too-long copy and broke one type scale. It counts in FLAGGED like the other types.Guidance: renaming a class or selector to dodge a check is a defect, and wrapping is fixed by shorter copy or a deliberate responsive type step in CSS (line-balance guide, visual QA guide).
Selftest covers a paragraph in a
stagecard, a non-chip-named inline-block pill, and a page that shrinks type.Web balance scans every view of a hash-routed page. Routes (
#/x,#!/x,[data-route]values) were stripped to one URL, so a 47-view single-page app was checked as one page and reported CLEAN. Views of one document now share one page per width and switch with the hash, instead of a new browser context per route.The check verdict states its coverage:
ADAMS CHECK: CLEAN (2 files, 3 pages x 3 widths).web_balance.jsprintsPAGES n WIDTHS ... ROUTES n, and aWARNINGline when in-page routes were not scanned or the crawl stopped at--max.check.pyprints each warning before the verdict and repeats it inside the parentheses. Warnings never change the exit code.The same defect on many views (a shared drawer or footer) prints once, then
also on N more routes.FLAGGEDcounts unique defects andROUTE-HITSthe raw count; the--outJSON keeps every hit.Guidance: a page with in-page views is CLEAN only when every view was scanned, and delegated agents quote the page count, never only the verdict (line-balance guide, visual QA guide,
ALWAYS.md).Selftest builds a two-route page with a defect on one route and checks the crawl, the plain anchor case and the verdict coverage.
Progressive disclosure:
modules/workflow/GUIDE.mdkeeps align, verify and complete output, and diagnose, handoff and retro moved verbatim toreferences/diagnose.md,handoff.mdandretro.md.modules/humanize-writing/GUIDE.mdkeeps sections 1 to 5, and the LinkedIn post method and the English tells moved verbatim toreferences/linkedin-post.mdandreferences/english-tells.md. Each guide ends with a router line. Workflow guide 1388 est tokens (was 2172), humanize guide 2695 (was 4650), typical text task 7640 (was 10324). Selftest caps the two guides at 1530 and 3000 est tokens and checks the new reference files exist.Token cost: the reminder hook prints once per session (about 450 characters, was 790 on every prompt),
ALWAYS.mdis about 25% smaller with every rule kept, andSKILL.mdis 44 lines (was 84) with the pipelines and the input-to-checks table moved verbatim todocs/PIPELINES.md.adams tokensprints the estimated token cost (chars/4) of every always-on file,SKILL.mdand each module. Selftest caps the reminder at 450 characters,SKILL.mdat 65 lines and 1750 est tokens,ALWAYS.mdat 950 est tokens.Evals:
stop-gatechecks that flagged text triggers a check before the agent finishes (with Adams 1.00, without 0.25);plan-breaksandtiny-typo-fixare taggedregression-guardbecause they pass either way on purpose.The workflow guide no longer points at a setting that Adams does not own.
The skill description is 629 characters (was 883) and
SKILL.mdis 84 lines (was 138), cutting the always-on and on-invoke token cost without touching the routing table.Install, profiles, hooks, maintenance and the repo layout moved verbatim to
docs/OPERATIONS.md, with one pointer line left in the router.Selftest caps
SKILL.mdat 105 lines (was 160).Web balance now checks pages whose content sits under
display: contentswrappers or fades in on scroll (reduced motion is forced), splits grid rows by vertical overlap, and ignores screen-reader-only table headers.adams uninstallremoves hook events it emptied instead of leaving empty lists.README lists what runs automatically.
adams install --linklinks the skill and registers the hooks even when the plugin is enabled, for apps that do not load plugins.Evals: graders now score the delivered work (deterministic checks where possible), turn budgets fit Adams' reviewer passes, and the drift case tests scope growth. Measured with and without the plugin: auto-ask,
adams checkuse and humanize rules show a clear gain; the drift and typo cases pass either way (they guard against regressions).evals/holds six cases forclaude plugin eval(ask-first on a vague request, no questions on a tiny task, humanize andadams checkon a post, stop on a broken plan, Arabic rules, web balance on a page), graded with and without the plugin. Run deliberately, it spends API usage.Plugin option
profile(userConfig):hzlint.pyandcheck.pyuse it as the last fallback beforedefault. Claude Code passes it to hooks asCLAUDE_PLUGIN_OPTION_PROFILE.New AI-search audit:
modules/seo-architect/scripts/ai_search_audit.py URL_OR_FOLDER(llms.txt, AI-bot rules in robots.txt, sitemap, titles, descriptions, canonicals, JSON-LD, brand spelling), a section in the seo-architect guide,references/ai-search.md, and a router row.New humanize regression corpus (
modules/humanize-writing/tests/corpus/, English and Arabic, stock-AI and plain samples) checked by the selftest.README: "Scheduled audits" with a copy-paste prompt for
/scheduleandloop.New Stop hook (
hooks/adams_stop.py): checks the.mdand.txtfiles changed in the working repo when the agent finishes, and sends it back to fix BLOCK hits. Files that passed are not re-checked until they change.New SessionStart hook (
hooks/adams_context.py): reloads.adams/decisions.md(settled decisions) after a start, restart or compaction. The workflow guide records decisions there.Budget guards in the selftest: reminder at most 900 characters,
SKILL.mdat most 160 lines, and no network imports in the hooks (telemetry-free).SECURITY.mdstates it.New: Adams asks on its own. At the start of any non-trivial task, and again whenever the work drifts, it reads the project docs, then asks the open decisions in one round (max 4), each with a recommended best practice and the reason, records the answers, and checks the work against them at checkpoints. No "ask me" needed. Loop in
modules/workflow/GUIDE.mdsection 1; wired intoALWAYS.md, the router and the prompt reminder.mainand the release tags are protected: no force pushes or deletions, and release tags can no longer be moved, so an update always gets the code that was released.The reminder and
ALWAYS.mdname the plugin form of the skill (adams:adams), and use neutral wording for the owner.adams doctorprints the installed version; the README explains how to verify a plugin install.Plugin installs and clone installs no longer double up: with the plugin enabled,
adams installskips the skill link and the hooks, andadams doctorcounts the plugin as the source of both.Release tags are annotated, so
git push --follow-tagspublishes them.Coming from 0.1.0? That release had no updater, so run
git -C <your clone> pullonce (or update the plugin). From 2.0 on, updates are automatic.Updates that reach you by themselves.
adams updatemoves a clone to the newest release tag, and a new SessionStart hook checks once a day and updates a clean clone quietly (opt out withADAMS_AUTO_UPDATE=0). Plugin users enable auto-update in/pluginor in settings (see the README).Versioned releases. One
VERSIONfile, this changelog, and a release workflow that publishes a release when avX.Y.Ztag is pushed.scripts/release.pycuts a release.Checks on what you changed.
adams check --changedand--since REFskip untouched files, for pull requests and CI.One profile per project.
adams initwrites.adams/config.jsonso everyone shares the same rules.Visible versions. A release badge on the repository page,
adams version, and an Updates section in the README.Fixed: HTML tag lines no longer count as repeated openers, and a file named README is no longer treated as a direct message.
First public release: the Adams skill with ten modules, profiles (
default,strict-ar), theadamsCLI, hooks, plugin manifests and CI.