@akinet/akidevrule 3.6.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +53 -16
- package/claude/CLAUDE.md +1 -1
- package/claude/agents/aki-conduct.md +3 -1
- package/claude/agents/aki-hands.md +1 -1
- package/claude/agents/aki-judge.md +1 -1
- package/claude/agents/aki-maker.md +2 -1
- package/claude/hooks/aki-compact-reread.mjs +16 -0
- package/claude/hooks/aki-route-guard.mjs +101 -41
- package/install.mjs +291 -22
- package/package.json +1 -1
- package/payload/GEMINI.md +4 -4
- package/payload/METHOD-audit-subtraction.md +1 -0
- package/payload/METHOD-audit-zero-trust.md +1 -1
- package/payload/RULE-agent-behavior.md +41 -18
- package/payload/RULE-coding.md +5 -2
- package/payload/RULE-pattern-core.md +2 -2
- package/payload/RULE-release.md +3 -3
- package/payload/RULE-stack-akiNuxtCf.md +1 -1
- package/payload/RULE-test.md +53 -0
- package/payload/route-map.json +14 -0
- package/skills/akiflow/SKILL.md +1 -1
- package/skills/akiflow/scripts/scythe.py +1 -1
- package/skills/akiflow/scripts/suite_lint.py +168 -0
- package/skills/akihelp/SKILL.md +1 -0
- package/skills/akilint/SKILL.md +1 -1
- package/skills/akirule/SKILL.md +4 -2
- package/skills/akiship/SKILL.md +3 -3
- package/skills/akithink/SKILL.md +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.8.0] - 2026-10-20
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **The installer offers an accuracy-first config for rtk, opt-in: a terminal prompt defaulting to no, `--rtk` to say yes without one, and one summary line either way** (`install.mjs`, `README.md` § Optional: rtk, `coding.B3` one bullet). Evidence: on the dev box rtk 0.50.0, hooked into Claude Code's Bash tool, merged two `ls` listings and cut `jq` lines at 120 characters while an agent was reading them as evidence; the research (`docs/research/rtk-output-loss-oct19.md`) measured the rest raw against filtered — `ls` drops names ending in `.` with no marker, `grep` 211 of 480 lines, `git diff` 610 of 7,541, `git log` 10 commits with no "more" line — and found the recall hints followed 3 times in 480 elisions; upstream has no lossless mode (#1313 open since 2026-04) and counts dropped bytes as savings. Root cause: rtk's built-in Rust filters run before any `filters.toml`, so the only lossless control is `[hooks] exclude_commands` in its `config.toml`, which nobody sets by hand. Mechanism: `rtkDetect()` runs `rtk config` and takes the path from its `Config:` line (macOS keeps the file under `~/Library/Application Support/rtk/`, Linux under `~/.config/rtk/`, verified on both), the question is asked before "Installing..." so the run has no mid-install prompt, and `rtkConfigure()` makes the smallest change — no file → write, no `[hooks]` → append, `[hooks]` without the key → insert it, the user's own `exclude_commands` → keep and list what is missing, a `# akidevrule: rtk off` line → skip; the file is backed up like `settings.json` and the backup dropped on success. The `coding.B3` bullet covers what stays compressed: output carrying an elision marker is a sample, rerun raw before a count, quote, failure list or absence claim is taken from it. Rejected: writing the config on every install (shared third-party config and the repo's Non-goals on personal settings — the owner's ruling is ask, default no); a `[retriever]` table in the managed content (the Mac runs rtk 0.47.0 with no sqlite store; left as a README line for 0.50+); lossless `filters.toml` overrides (unreachable for the Rust filters, and any edit silently cancels `rtk trust`); recommending against rtk (the noise class saves real context at no cost to evidence). Verified: sandbox-`HOME` fixture with a fake `rtk` on `PATH` (absent → hint; present without `--rtk` → untouched; `--rtk` → written; re-run → byte-identical, no backup left; other table → appended; `[hooks]` without key → inserted; user list → kept with missing names; opt-out → skipped), then real rtk 0.50.0 reading the generated file through `XDG_CONFIG_HOME` with the hook JSON: `ls`, `grep -rn`, `git -C … diff`, `jq`, `cd … && ls | head` pass raw and `git status` is still rewritten; the same cases run in `install-smoke.yml` on all three OSes; the exclusion is honoured from rtk 0.47.0 (changelog, and the same hook test on the Mac) through 1.0.1 (the dev box upgraded and re-tested the same day: `sh -c 'ls -la'` still raw, `RTK_DISABLED=1` still honoured), with the Windows path (`%APPDATA%\rtk`) taken from rtk's `user_dirs.rs` rather than observed. Updated together: `README.md` (TOC, install step 7, § Optional: rtk, uninstall), `docs/arch/rule-delivery-architecture.md` installer paragraph, `docs/arch/corpus-map.md` "what a passing check proves" lens, `docs/index.md`, `docs/plan/rtk-accuracy-first.md` (executed, P4 scheduled), `docs/plan/full-file-reads.md` F5/V3, the research doc's `## Amendments` (macOS path, Mac version).
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- **`agent.B1` names pull requests, deploys and tags beside commits and pushes, and adds "the request is the whole scope": a step the request did not name — the PR after a commit, the push after a fix, the deploy after a build, the usual next step of a workflow — is not taken because it is customary or looks helpful; finish what was named, then stop and report (`A3`).** Evidence: on 2026-10-08 the owner asked an agent for one added comment line in a repository and the agent also opened a pull request (PR #1) nobody had asked for; the owner's correction was that his instruction outranks both harness instructions and the model's trained habits. Root cause: `B1` listed commits and pushes but not PRs or deploys, and nothing said that a workflow's customary next step is still an unrequested step — `B7` covered harness text only, so a habit learned in training read as neither an instruction nor a violation. Mechanism: one widened bullet and one new bullet in `B1`, plus one sentence in `B6` ranking the model's trained defaults (the workflow it usually follows, the next step it usually takes, a convention from other projects) below every instruction, since they are not instructions at all. Rejected: a new `B8` section (restates `B1`/`A3`; the gap was two missing nouns and one missing concept); a `B7` table row (`B7` quotes harness text, and a trained habit has no quotable source). Updated together: this entry only; no address, route or signal changed.
|
|
10
|
+
- **`agent.C5` reduced to two rules plus the existing `scripts/` line: no file the task can do without and none outside the scratchpad, one session folder only where the harness gives none; `agent.B1`'s "what you create, you remove" now covers anything the agent or a command it ran created outside the harness scratchpad and says nothing about the scratchpad itself.** Evidence: across 516 of the owner's Claude Code transcripts (2026-10-20), 528 `rm` commands in 131 transcripts mostly deleted the agent's own throwaway files (scratchpad 288, `/tmp` 97), and a machine-local command gate spent 143 of its 212 permission prompts on `rm -rf` confirmations that stalled unattended runs; the owner's standing order (one session scratch folder, no `.bak` copies or `verify`/`shots` folders) had no home in the corpus. Root cause: the corpus itself ordered the deletion — `B1` listed temp files among what the agent must remove and the previous `C5` said to delete the session folder before reporting — while the harness already discards its scratchpad, so every run paid a create-then-`rm` cycle and, under a command gate, a prompt. Mechanism: subtraction first — `B1` trades its file-type list for a scope — anything the agent or a command it ran created outside the harness scratchpad — so a throwaway written in the project tree, `/tmp` or the home directory, or a tool's own output (`npm pack`'s `.tgz`, a screenshot), is still removed by the agent while the scratchpad is left to the harness, `C5` shrinks from six bullets to two rules plus the `scripts/` line, and the scratchpad's lifetime is the harness's default; the prompt itself was removed where it is raised, by teaching the machine-local gate that an `rm` confined to temp locations is not a danger. Rejected: a new hook that denies scratchpad `rm` (a second gate layered on the one that prompts — the fix belongs in the gate that asks); dropping files from `B1` entirely (prevention only: a throwaway written outside the scratchpad in breach of `C5` then had no removal duty, and `test.B3`, which applies `B1` to a suite's temp dirs, outgrew its own root); a closing `git status` step or an end-of-session untracked-file hook (one more ritual or layer, blind to ignored files, and a hook cannot tell the agent's files from the owner's work in progress — reopen only if `/akiopen` keeps finding untracked side copies); a fixed absolute scratch path (each harness and machine differs); a rule forbidding hand-cleaning of the scratchpad (a layer over the harness default; once the command gate stopped prompting on temp `rm`, the cleanup costs one call and no prompt). Updated together: `claude/agents/aki-maker.md` and `claude/agents/aki-hands.md` (`C5` gloss), `docs/research/agent-churn-temp-rerun-oct20.md`.
|
|
11
|
+
- **`coding.B3`: one run per change state.** Evidence: in the same 516 transcripts, 507 of 2,522 verification runs (20%) repeated the same check type with no edit by any tool in between; 396 of those (78%) followed a run whose output had been piped through `grep`/`head`/`tail`, a subagent ran in between in only 8 (1%), and a byte-identical rerun happened once — the waste is output thrown away by a filter, not distrust of a worker. Root cause: `B3` said which check fits which moment but nothing about keeping a run's output, so the filter discarded evidence and the only way back was another run. Mechanism: a long check runs once with its output kept in the scratchpad and later questions grep that file; a rerun needs an intervening change or a written reason (flakiness probe, baseline, raw output after an elision marker) — the one case `agent.C5` names for writing a file. Rejected: a transcript lint (a count cannot tell a legitimate flake probe from waste); banning output filters (they keep the context small). Updated together: `docs/research/agent-churn-temp-rerun-oct20.md`.
|
|
12
|
+
- **The path → rule map is one data file, `payload/route-map.json` (installed to `~/.aki/akidevrule/route-map.json`), read by `aki-route-guard.mjs`, `scripts/second_hop_audit.py` and `skills/akiflow/scripts/suite_lint.py` instead of three copies in code.** Evidence: the map lived only as code in the hook (`CODE_EXT`, `FRONTEND_EXT`, `TEST_NAME`, `TEST_DIR`, `routesFor`, `isUngatedPath`, `isNuxtProject`, nothing exported), and the audit's hand copy had already drifted from it — no `ui` for `.tsx`/`.jsx`/`.svelte`, `docs` only under `docs/`, no `content` route, `stack` on every `.vue` with no Nuxt condition, no `stack` for `.ts`, a shorter code-extension list — so the read rates the audit printed described a different set of edits than the gate denied; `suite_lint.py` expanded a directory with a third copy of the test signature; AkiMCP's rule gate must push the same routed rules to web AIs that have no hook and knows only `CLAUDE.md`/`AGENTS.md`. Root cause: the mapping was written as logic in the one consumer that existed first, so each later consumer copied it. Mechanism: one JSON file, `routes` (each with `rules` and any of `ext`, `name`, `nameRe`, `dirRe` + `dirSkipExt`, plus `projectHas`, file names of which any one must exist at the project root) and `ungated` (path segments, prefixes, directory names); regexes use only syntax JavaScript and Python read alike; every directory route matches the project-relative path; the hook fails open when the file is missing, the two scripts exit 2 with a message. The harness-config-dir and outside-project checks stay in the hook, a deviation from the plan's D2, which listed them as data flags: only the hook needs them, and AkiMCP's gate uses the segment/prefix/dir list alone. Rejected: exporting `routesFor` as a module (Python and AkiMCP cannot import it, and AkiMCP would execute code from `~/.claude/hooks/`, which exists only where Claude Code assets are installed); AkiMCP keeping its own copy (the audit's copy already drifted); leaving the audit on its copy (it keeps measuring something other than the gate). Verified: 17 sample paths plus 2 Nuxt cases (test files, `src/x.js`, `docs/spec/a.md`, `a.tsx`, `pages/a.vue` with and without `nuxt.config.ts`, `src-tauri/x.json`, `locales/vi.json`, `~/.aki/x.md`, `/tmp/x.js`, a path outside `cwd`) gave byte-identical deny lists before and after; with the map file removed every edit is allowed. The audit's numbers change once and are not comparable across the switch: on the Mac's transcripts, in the "before" era, sessions routed to `docs` went 94 → 128 (any `.md` now, not only under `docs/`), `stack` 41 → 40, `tauri` 6 → 8, and a `content` route appears. Updated together: `payload/route-map.json` (new), `claude/hooks/aki-route-guard.mjs`, `scripts/second_hop_audit.py`, `skills/akiflow/scripts/suite_lint.py`, `skills/akirule/SKILL.md` (delivery bullet names the file), `README.md` (gate paragraph, payload layout, hook list), `docs/arch/rule-delivery-architecture.md` (gate section), `docs/index.md`; the shipping assertion for the file in `.github/workflows/install-smoke.yml`. Plan: `docs/plan/done/route-map-json.md`; the file ships at `~/.aki/akidevrule/route-map.json` and `aki-mcp-sv` picks it up through its own plan's dependency section.
|
|
13
|
+
- **A rule file counts as read only when read whole: the route gate stops counting `limit`/`offset`/`head`/`sed`/`tail` reads, and on Claude Code a partial `Read` of a rule file is rewritten into a whole one (`agent.B7` gains a row for the `Read` tool description).** Evidence: on 2026-10-19 a Sonnet worker briefed to read `RULE-agent-behavior.md` and `skills/akirule/SKILL.md` called `Read` with `limit: 40` and `limit: 30`, then opened its reply `[RULES] agent,akirule,docs (brief)`, naming two files it had seen the first fifth of; baseline on the Mac (2026-10-20, `second_hop_audit.py`): main sessions 44 of 1,164 rule reads partial (3.8%), subagents 34 of 440 (7.7%); on the Linux dev box 64 of 1,345 (4.8%). Root cause: Claude Code's `Read` description says "When you already know which part of the file you need, only read that part" and `agent.B7` had no row for it; the gate matched a `Read` by file name alone, so a partial read marked the file read, and the audit counted the same way and could not see the gap; a read-only worker never meets an edit gate. Mechanism: F1 — `scanTranscript` counts a `Read` only when `offset` is absent or ≤ 1 and `limit` is absent or ≥ the file's line count, `cat`/`bat`/`less` in Bash/Shell keep counting, `head`/`sed`/`tail` never do, and the deny reason adds "A Read with limit/offset or a head/sed/tail print does not count — read the whole file." when only partial reads were found; F2 — the hook also runs on matcher `Read` (registered by `install.mjs`) and rewrites a partial `Read` of a rule file (`~/.aki/akidevrule/*.md` or a `SKILL.md` under `~/.claude/skills/`, judged on the resolved path, at most 60,000 bytes) into a whole `Read` through `PreToolUse` `updatedInput` with `permissionDecision: allow`, so there is no extra round trip; above 60,000 bytes the `Read` tool's ~25k-token cap makes a partial read the only possible one, so it passes; F3 — the `agent.B7` row, covering a file a brief names "in full" that is not a rule file, and harnesses without the hook; F6 — `second_hop_audit.py` prints `rule reads: N (partial K, P%)` for main and subagent and no longer counts a partial read as a read. F5 unchanged: Bash `cat` stays counted. F4 (receipts carrying line count and last line, `agent.A5`) is deferred: evidence of partial reads exists only on Claude Code, where F2 now removes them mechanically; reopen on a partial rule read observed in a worker on a harness without the hook (agy, Codex, Kiro) or a receipt naming a file the worker did not read whole. Rejected: deny instead of widen (a round trip per partial read, and a model may retry partially); denying `limit`/`offset` on every `Read` (partial reads of large code files are correct); wording only (the second hop was re-worded twice, 2026-08-06 and 2026-09-25, without moving the read rate); F4 now (no evidence outside Claude Code). Hardened after an adversarial review the same day: `permissionDecision: allow` skips the permission prompt, so widening applies only to the corpus's own files after `realpath` (a `../` path or a `SKILL.md` elsewhere passes untouched); the transcript records the model's original `Read` input, not `updatedInput`, so a widened read is recognised by the hook's own attachment for that tool-use id and counts as whole; the denial fail-open counts only attachments carrying `"permissionDecision":"deny"`, since the widen output also names the rule; a Bash `cat` counts only as the command word of its segment and not when piped onward (`cat x | head`, `git cat-file` no longer count). Cost: about 29 ms per non-rule `Read` (one `node` start), measured. Verified live on Claude Code 2.1.303 (2026-10-20): a `Read` of `METHOD-proportionality.md` with `limit: 5` returned all 63 lines. Updated together: `claude/hooks/aki-route-guard.mjs`, `install.mjs` (matcher, printed summary), `scripts/second_hop_audit.py`, `payload/RULE-agent-behavior.md` (`B7` row), `skills/akirule/SKILL.md` (delivery bullet), `claude/CLAUDE.md` (gate paragraph), `README.md`, `docs/arch/rule-delivery-architecture.md` (gate section, the read-only-reviewer sentence), `docs/index.md`. Plan: `docs/plan/done/full-file-reads.md`.
|
|
14
|
+
- **`skills/akiflow/scripts/test_lint.py` renamed `suite_lint.py`.** Evidence: the script's own name matched the `RULE-test.md` route's `^test_.*\.py$` signature, so `test_lint.py --all .` linted itself as a test file (`[EXIT]`, `[HOMEREAD]` on its own exit calls and HOME read), the route gate demanded `RULE-test.md` before any edit of it, and pytest would collect it as a test module. Root cause: the name followed the `test_*.py` convention test runners treat as a test file. Mechanism: rename inside the `<domain>_lint.py` family (`release_lint.py`) without the `test_` prefix; the installer's per-skill mirror removes the old deployed copy and the skill-script allowlist is generated from the script inventory. Rejected: narrowing the route signature (`test_*.py` is the real pytest convention and must keep routing). Updated together: `payload/RULE-test.md` (`test.D1`), `README.md` (layout), `docs/index.md`, `docs/arch/rule-delivery-architecture.md`.
|
|
15
|
+
- **The installer smoke test behaves the same on a developer machine as in CI.** Evidence: run locally on 2026-10-20 it failed twice where CI passes — `route gate did not deny an unread code edit` when the throwaway HOME sat under the session scratchpad, a path `route-map.json` ungates, and `rtk absent: hint line missing` when a real `rtk` was on `PATH`. Root cause: two fixtures inherited ambient state, the HOME location and the caller's `PATH` (`test.C2`). Mechanism: the gate probe edits a never-created project at the filesystem root instead of under HOME, and the rtk-absent case runs with every `PATH` entry holding an `rtk` binary removed. Rejected: documenting a required local setup (a hand-off the fixture itself can remove).
|
|
16
|
+
- **`agent.A3` rebuilt on one root — understand what the owner asked, act only on an order — with the turn's first state-changing call bound to naming the words that order it; an order runs to the end without asking.** Evidence: on 2026-10-20 an agent with `A3` resident turned an owner question that hid its only `?` behind a hedge ("có thể là ghi thành notes …?") into a notes edit, then answered the correction with a second unordered `git restore`; asked to classify the same messages afterwards, it classified every one correctly. Eleven corpus changes since 07-23 moved this boundary back and forth — seven limiting action, four pushing it — and 108 clauses across the corpus restate one side or the other (`docs/research/question-vs-action-oct20.md`). Root cause: recognition was never the failure; `A3` asked for a judgment at no moment, while the rules that hold (`B4`) bind a literal cue to a moment, and the corpus named no root, so each incident added a counterweight. Mechanism: the root sentence, the hedge and polite-order cues ("can you fix X?" is an order), the check before the first state-changing call (anything beyond reading and checking: no ordering words, or words that read both ways, no call), and over-asking on ordered work named as an equal failure; the reversibility bullet and the one-line-suggestion bullet are removed as duplicates of `B3` and the new `A4` `N`; on a communication turn the decision block is the answer. Rejected: a `PreToolUse` gate on question-shaped messages (a per-language heuristic beside the route gate), a turn-class marker in the receipt (self-reported), a per-turn classifier call (paid quota), moving the case lists to `METHOD-deep-think.md` or a references file (Antigravity, Codex and workers would not load it at the moment it governs).
|
|
17
|
+
- **`agent.A4` defines what an open item is — only what this turn cannot finish — and codes each by what the owner's silence does to it: `Q` (question · quyết) silence blocks, the owner must answer; `T` (taking it · tự làm) silence proceeds, a call the agent makes within the order, the `A3` decision block included; `N` (note · nhớ) silence changes nothing, a hold, a caution or an idea outside the order. Doable work is done, never listed; a release is one closing line once no `Q` is open; findings and options inside an analysis are numbered, never coded with these letters.** Evidence: 1,260 coded items in 298 open-item blocks across 254 Claude Code and 500 agy CLI sessions (2026-08-28 → 10-20), one letter carrying up to four meanings (`S` gate step, design option or task; `V` unverified or closed); 3,905 owner messages, of which an estimated 274 ask "done yet / why is it left", 222 ask for a shorter summary, 60 ask where an item is recorded and 54 ask what an item means or whether it matters. Root cause: `A4` gave three example letters by kind of work, so the owner had to read each item to learn whether it needed him. Mechanism: the owner's silence has exactly one consequence per item, so three letters partition every item and a new kind of work needs no fourth; listed `Q` → `T` → `N`, the owner stops reading once no `Q` is left; each letter reads in English and Vietnamese. Rejected: kind letters (`D`/`T`/`V`/`S`…), `D` (`D1` is Cloudflare's database), `P`/`W` (the owner's window handles), `S` (gate steps), `G` for "go" (a code would read as a run order; already labels goals in a plan), `M` (Apple `M1`), `H` as first applied (mixed an act only the owner's hands can do with a passive wait), announce-then-proceed outside the order (acts unordered, `A3`). Research: `docs/research/open-item-codes-oct20.md`.
|
|
18
|
+
- **`agent.B3` asks only for what the order did not name ("Ask before, unless the order names the step:"), and the `B7` row for "When you have enough information to act, act" adds that the sentence never turns communication into an act.** Evidence: `B3`'s list asked even when the owner's order named the step, so the already-authorized kill-test inside `A3` never reached it; the act-now sentence first appears in this machine's transcripts on 2026-09-04, when the owner reports the failure grew. The shared-standards line stays: it guards rule corpora and templates other repos consume. The documented-design line now asks only for a conflict the order did not name, so naming a change never waives the conflict it hides.
|
|
19
|
+
- Updated together: `payload/RULE-release.md` `B8` (pointer only, the over-asking restatement removed, the stale "durably authorized" clause replaced by `B3`'s new header), `payload/GEMINI.md` §8 and §12 (the "ambiguous task → stop and ask" line now names `A3`'s escalations, "can you fix X?" is a task, a correction of ordered work resumes it, CHECK 1 asks whether the user's words order the step instead of whether they literally name it; the file's deliberate repetition is kept), `skills/akiship/SKILL.md` (activation condition 2, a pointer; unverified leftovers are `N` items), `payload/RULE-coding.md` `B3` (runtime-unverified items and the hand-off ledger are `N` items, `Q` when a run waits on one), `agent.A3` (the decision block is a `T`), `skills/akithink/SKILL.md` (a decision record is proposed, not written, on a communication turn), `docs/arch/corpus-map.md`. Unchanged because still true: `coding.B3`'s kill-test pointer, `aki-challenger`, `aki-judge` and akiflow cite `A3`'s kill-tests, which stay.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **The installer left `*.akidevrule-backup-*` files beside every file it touched, two per file, after every run.** Evidence: a dev box carried five such files under `~/.gemini/antigravity-cli/`, `~/.kiro/settings/` and `~/.cursor/` from runs on 2026-09-26 and 2026-09-28, kept by design. Root cause: `backup()` treated a pre-write copy as a permanent artifact and `pruneBackups()` kept the two newest, so every successful run converted rollback material into clutter in the user's config directories. Mechanism: every backup made by a run is recorded and removed once that run reaches its summary; a failed run keeps them (they are then the rollback); `pruneBackups()` keeps only the current run's copy by default, so older leftovers drain on the next run that touches the file; the one exception is a `~/.gemini/GEMINI.md` that held lines the install did not manage, whose backup stays (with one older) because it is the user's only copy of those lines and the migration directive points at it. Rejected: dropping backups altogether (a merge bug in `settings.json` would then have no rollback during the run). Updated together: `README.md` install steps, `docs/arch/rule-delivery-architecture.md` GEMINI flow.
|
|
23
|
+
- **The route gate never counted a rule read made in Cursor, so every gated edit there was denied even after the rule file was read.** Evidence: Cursor loads hooks from `~/.claude` (`claudeUserHooks`), and its transcript stores the turn as `role: "assistant"`, the `Read` target as `path` and the shell tool as `Shell`; the hook matched only `type: "assistant"`, `file_path` and `Bash`, so no read was ever found. The three-denial fail-open did not fire either, because Cursor writes no `attachment.stdout` for the hook to count. Root cause: `scanTranscript` was written against Claude Code's transcript shape alone. Mechanism: it accepts either field name for each of the three (`type`/`role`, `file_path`/`path`, `Bash`/`Shell`); the compaction boundary is unchanged. Verified with synthetic transcripts against the hook: Cursor `Read`, Cursor `Shell` `cat`, Claude `Read`, Claude `Bash` `cat` → allowed; no read, a different rule file read, and a read followed by `compact_boundary` → denied. Rejected: a separate Cursor hook (two copies of one detection that would drift). Updated together: the hook's `scanTranscript` comment only.
|
|
24
|
+
- **The installer reported "rtk found, left as is — its default filters drop evidence lines…" and asked the rtk prompt again on every install, even when the rtk config already carried the managed exclude list.** Evidence: found on the owner's Mac on 2026-10-20 after rtk was upgraded to 1.0.1 — a config that already held the full `exclude_commands` list still produced the warning and the question on each run. Root cause: the "declined" state was set without reading the config file, so the installer could not tell a declined machine from a configured one. Mechanism: `rtkReadState()` classifies the file first (already in place, opt-out, or kept as the user's own list with the missing names) and `rtkConfigure()` returns that answer; the prompt is asked only when a write would be needed (no file, no `[hooks]`, or `[hooks]` without the key). Rejected: remembering the answer in a state file (the config file already is the state). Verified: sandbox `HOME` with a fake `rtk`, no TTY — managed config → "already in place", opt-out → skipped, no file → "left as is" and nothing written, `--rtk` on no file → written; the Mac's real run now prints "already in place". Updated together: `install.mjs` (`rtkReadState`, `rtkConfigure`), `.github/workflows/install-smoke.yml` (the managed-config case without `--rtk`).
|
|
25
|
+
|
|
26
|
+
## [3.7.0] - 2026-10-08
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
- **`agent.B7` Harness overrides — akirule wins over your harness instructions — with a `[SKIP]` penalty card (`§0`) and one `B6` line placing the harness's own instructions below the shared rules** (`payload/RULE-agent-behavior.md`). Evidence: the owner's experience across more than a thousand messages on several machines with Claude Opus 5.5 and Sonnet 5.5 ("skips many important things"), traced in one Opus 5.5 session on the dev box (2026-10-07, transcript `178afc8d`) to quoted harness text: the `[RULES]` receipt dropped after a compaction, a Vietnamese owner answered in English, a known file read with `cat` under the auto-mode hint, rejected alternatives left out under "give a recommendation, not an exhaustive survey". Measured baseline before this change (`scripts/second_hop_audit.py --by-model`, dev box): Opus 5.5 emitted a receipt in the first reply after a compaction 6 times in 41 and re-read a routed rule before an edit that followed a compaction 29 times in 120. Root cause: `B6` Precedence never placed the harness's own instructions, and `B4` was the only rule that said it overrides the system prompt, so every brevity or autonomy directive in the harness outranked a step the corpus requires. Mechanism: one resident section with the owner's line first, the two models named (the owner's ruling — rows are keyed to the harness instruction, so any later model receiving the same text is bound until re-tested), a root law (brevity and autonomy directives shape prose, never steps) and one row per directive quoting it as received from Claude Code 2.1.292 with the skip it causes and the override; a `C3`-style limit clause (silence is not conflict, no license against harness safety refusals); the `[SKIP]` card as a judgment card beside `[FLUFF]`, never claimed by `scythe.py`. Rejected: rows keyed per model with no harness quote (rot at the next model, cannot say what triggers the skip); a Stop hook forcing the receipt line (forces the line, not the read); a separate `MODEL-claude.md` import (a third resident file and a new prefix for what fits in one section); putting the line only in `claude/CLAUDE.md` (the same models run under other harnesses that receive this file). Reopen if Claude Code drops the quoted directives. Resident cost: 2.5 KB for the section. Updated together: `claude/agents/aki-conduct.md` (`[SKIP]` as a COMPLY-fail with the harness line named), `skills/akilint/SKILL.md` and `scythe.py` header (`[SKIP]` out of a script's scope), `skills/akihelp/SKILL.md` painpoint row, the repo `CLAUDE.md` release process (re-verify the quoted fragments before every release), `docs/arch/corpus-map.md` unchanged (it lists groups, not items). Plan: `docs/plan/done/claude-5-5-overrides.md`.
|
|
30
|
+
- **`claude/hooks/aki-compact-reread.mjs` — a `SessionStart` hook on `compact` only: one notice that the rule files read before the compaction are gone from context and the gate counts reads only from here.** Evidence: the same transcript, five compactions, the last rule reads 170 lines before the last boundary, and the harness's resume message ("Resume directly — do not acknowledge the summary") pushing straight on. Mechanism: emits `additionalContext` under 400 characters only when `source` is `compact` (schema read from the 2.1.292 bundle: `source` is `startup|resume|clear|compact|fork`), nothing on `startup`/`resume`, fail-silent; registered by `install.mjs` with the existing filter-then-push beside the update check. Rejected: a per-turn reminder (declined 2026-08-03, and this fires once per compaction). Whether the context survives into the post-compaction prompt is not verified (needs a live compacted session; the owner dropped that check).
|
|
31
|
+
- **Codex CLI gets the behavior floor and the router resident, as a managed block in `$CODEX_HOME/AGENTS.md`** (`install.mjs` `installCodexInstructions`). Evidence: `docs/research/codex-instruction-delivery.md` — the installer synced skills only, the router's own Delivery note left routing on Codex to a skill invocation the model must choose, and copying `~/.claude/CLAUDE.md` would deliver two `@` lines Codex never expands. Vendor facts re-read 2026-10-07: Codex hard-loads `AGENTS.override.md` (if non-empty) else `AGENTS.md` under `CODEX_HOME` (default `~/.codex`), then one project file per directory root-first, and stops adding files once global plus project together reach `project_doc_max_bytes` (32 KiB default) — the floor plus router are 35.6 KB, so the block alone would have been cut. Mechanism: a marker-delimited block (`>>> akidevrule managed` … `<<< akidevrule managed`) regenerated from the two canonical files with a short preamble (no gate on Codex, the Read of a routed file is the model's own step, do not invoke the skill too), every line outside the markers kept, backup first, only when the directory exists; `project_doc_max_bytes = 131072` written once into `config.toml` before the first table header and only when absent from the top-level keys (a same-named key inside a table does not count), an existing smaller value reported rather than raised; a non-empty `AGENTS.override.md` reported as shadowing; the project `CLAUDE.md` fallback (`project_doc_fallback_filenames`) printed as an opt-in and never set. Rejected: setting the fallback silently (a user config change nobody asked for, and a native `AGENTS.md` in the same directory shadows it anyway); a pointer-only global file (a pointer is the soft hop the research measured as inert); symlinking Claude's global file (imports unexpanded, user guidance shadowed). Verified: `install-smoke.yml` now asserts the block is written once, user text survives, re-install is idempotent, the key lands once before the first table, and no `~/.codex` is created when absent — run locally against a temp `HOME` (pass) and in CI. Unverified: that a fresh Codex session receives the block — the dev box has no Codex CLI; `scripts/codex_probe.sh` is the hand-off. Updated together: `skills/akirule/SKILL.md` Delivery (Codex resident, Kiro/Grok still a skill), `README.md` (target 4, install step 5, layout, uninstall), `docs/arch/rule-delivery-architecture.md` § Codex, `docs/ref/fact-agents-md-standard.md` Codex row with trail, the research doc's `## Amendments`. Plan: `docs/plan/done/codex-instruction-delivery.md`.
|
|
32
|
+
- **`RULE-test.md` (topic `test`, 12 items in four groups: fewest tests, side effects, verdict, suite audit; root "write as few tests as possible"), routed by meaning and gated by the test-file path, plus `skills/akiflow/scripts/test_lint.py` and one-line pointers in six rules.** Evidence: a fully green 51-test suite in a local Node server rewrote the user's live app data directory under the real `HOME` (with an empty `HOME` the same suite went 50/51); across 425 test files in 12 local repositories the same shapes recur in 2–5 repos each — bare `Array.isArray` as the sole assertion (25 lines, 15 files, 5 repos), temp dirs created and never removed (3 files, 3 repos), fixed sleeps (9 files, 2 repos), live third-party endpoints in a default suite, `process.exit` in 12 files, 41 of 42 files one linear script whose first throw hides the rest, a fixture pinning the manifest version so the next bump turns the suite red with nothing broken (`docs/plan/done/test-discipline-rules.md` § Evidence, every count measured 2026-10-07). Root cause: the corpus had no rule on what makes a test's verdict trustworthy, what a test may touch or what earns a test its place, and its two gates that consume test results (`coding.B3`, `release.B7` step 6) trusted "green" unconditionally. Mechanism: a separate gated file rather than a `coding` section because tests are a minority of code edits and the route gate makes it read on exactly those (`docs.A5` reach); the route fires on authoring, review or audit of a test and on judging a result, never on a plain `npm test` inside a code task; the gate signature is the runner conventions in the sample (`*.test.*`, `*.spec.*`, `*_test.*`, `test_*.py`, `conftest.py`, `test/`, `tests/`, `__tests__/`, `spec/` minus `.md`, matched on the path relative to the session's working directory in both the gate and `second_hop_audit.py` — the gate's `migrations/`, `locales|i18n|lang/` and `src-tauri/` routes too — so a project under a parent with one of those names is not gated whole); `test_lint.py` carries three CERTAIN tags measured on that sweep (`[TMPLIT]`, `[CLEANUP]` suppressed where a suite preload is configured, `[EXIT]`) and nine SUGGESTED review tags, exit 1 only on CERTAIN; `scythe.py` unchanged (its tags are the `agent` §0 cards). Subtraction before shipping: the plan's `test.D1` (audit scope, pointer-only) merged into the detectors item, 24 → 23; `[PRIVATE]` dropped to Parked as unmeasured and noisy; no coverage target anywhere; then, on the owner's review ("hạn chế tối đa việc viết test"), restructured 23 → 12 items with "no new test by default" as `test.A1` and a new `test.A3` against new test files, folders, helpers and test-only seams when an existing place fits, so the rule cannot be read as "write more tests". Rejected: a `coding.D` section (paid on every code edit); a separate `METHOD-audit-test.md` (each failure class written twice); per-project `CLAUDE.md` lines (the incident repo's `CLAUDE.md` is long and careful, and the gates that trust green are corpus text); mutation testing as a floor (a tool, costly on a weak machine); content-sniffing in the hook (a hook reading file bodies). Reopen if `second_hop_audit.py` shows test-edit sessions reading `RULE-test.md` less often than `RULE-coding.md`, or the file grows past 12 KB. Verified: gate fixture (a `test/x.test.js`, a `test/fixtures/a.json` denied on `RULE-test.md`; `src/x.js`, `docs/spec/a.md` not), `test_lint.py` on a positive/negative fixture per tag and on the local sweep (CERTAIN counts in the plan), the router clause rendered as the Antigravity description by a sandbox-`HOME` install, `release_lint.py --latest` exit 0. Unverified: Python/Go detector precision (no such test files in the sample); the gate's effect on read rates (not measured; the owner dropped post-release measurement). Updated together: `RULE-coding.md` `B3` (a test result is evidence only for what it exercised), `RULE-release.md` `B7` step 6 (residue check and listed skips), `METHOD-audit-subtraction.md` `B1` (Tests row), `METHOD-audit-zero-trust.md` `B1`, `RULE-agent-behavior.md` `B5` domain audits, `RULE-pattern-core.md` `A7` list and its address map (`A1-9`, stale since `A9` landed), `RULE-stack-akiNuxtCf.md` `C8` (three stale `coding.B5` ladder references → `B3`, merged in 3.6.0), `skills/akirule/SKILL.md` (route row, gate mapping), `claude/hooks/aki-route-guard.mjs`, `install.mjs` (`AG_RULE_MAP`), `scripts/second_hop_audit.py` (`test` route), `docs/arch/corpus-map.md` (topic row, three lens rows, a new "what a passing check proves" lens), `docs/arch/rule-delivery-architecture.md` (gate mapping; the "closes the worker gap" sentence now scoped to workers that edit), `README.md` (contextual list, layout incl. the missing `METHOD-audit-frozen-reference.md` line, scripts), `claude/agents/aki-maker.md`, `claude/agents/aki-judge.md`, `skills/akiflow/SKILL.md` audit row. Plan: `docs/plan/done/test-discipline-rules.md`.
|
|
33
|
+
- **`agent.A4`: every open item in a report carries a stable short code** (`payload/RULE-agent-behavior.md`). Evidence: in a long release-readiness session an agent listed pending decisions, unverified checks and blocked tasks as unnumbered prose, so the owner could not answer one without quoting it and had to ask for numbering ("anything blocked or left over must be numbered so I can mention it"). Root cause: `A4` shaped a report for re-orientation but said nothing about how the owner addresses an item in the reply. Mechanism: a kind letter plus a number, never renumbered or reused within a conversation, so a later turn's `D2` is the same `D2`. Rejected: a fixed letter vocabulary, because the kinds differ per task and the stability of the code is what the owner relies on, not its alphabet. Updated together: this entry only; no address, route or signal changed.
|
|
34
|
+
- **`agent.A4`: a report is short, plain and calm** (`payload/RULE-agent-behavior.md`). Evidence: a release-status report listed nine coded leftovers with internal terms ("release gate B7", "migration detector") and no statement of how much each mattered; the owner had to ask "what is V6, is it important?" and called the report confusing and alarming. Root cause: `A4` required density and conclusion-first but said nothing about unexplained terms or about weighing an open item. Mechanism: one bullet — everyday words, each open item carries its weight and the cost of ignoring it, items needing nothing from the reader are dropped, and the draft is read as the reader before sending.
|
|
35
|
+
- **`agent.B1`: what you create, you remove** (`payload/RULE-agent-behavior.md`). Evidence: on the owner's dev box a multi-agent council left a 93.6 GiB `cargo` target, nine stale worktrees and a 3.3 GB sibling worktree (`aiobox-wt-p4`) whose branch was already merged; free disk fell to 116 MiB and `cargo` builds died mid-link, which the owner found and cleaned by hand. Root cause: `B1` only forbade unrequested cleanup, so removing an agent's own merged worktree read as out of scope, and the AkiMCP worktree convention had a create step and no remove step. Mechanism: one `B1` bullet — an artifact the agent started (worktree, branch, build output, temp file, window, process) is removed by that agent in the same turn its work is merged or abandoned, framed as finishing rather than cleanup; another session's artifact stays under `B3`; and none is created that the task can do without — a worktree, build directory, clone or dependency install only when the work is impossible otherwise. Rejected: a per-artifact checklist (each harness and tool names them differently, the ownership test is what generalizes); "reuse a shared one" (first draft) — the council read it as license and created a shared cargo target outside the repo, which the owner called junk: a shared artifact is still one more artifact. Updated together: this entry only; no address, route or signal changed.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- **`claude/hooks/aki-route-guard.mjs` counts a rule as read only after the last compaction, and restarts its three-denial fail-open per compaction segment.** Evidence: the transcript above — the gate scanned the whole file, so a `Read` from before a compaction kept satisfying it while the model's context no longer held the rule. Mechanism: the transcript scan resets its read set and denial counts at every `system` line with `subtype: compact_boundary`; the deny reason now says "not read since the last compaction". Verified by a six-case fixture (read with no boundary → allow; read then boundary → deny; boundary then read → allow; read, boundary, read, boundary → deny; three denials then boundary → deny again; three denials, no boundary → allow). Updated together: `claude/CLAUDE.md` gate paragraph, `skills/akirule/SKILL.md` delivery bullet, `README.md`, `docs/arch/rule-delivery-architecture.md`, the installer's printed hook summary.
|
|
39
|
+
- **`scripts/second_hop_audit.py --by-model`** splits every row by the assistant `model` field and adds a compaction table: receipt in the first assistant text after a `compact_boundary`, routed rule re-read after the last boundary before an edit, and Bash `cat`/`head`/`sed -n` of one known file versus `Read`. Default output unchanged. Baseline recorded in `docs/plan/done/claude-5-5-overrides.md` so the post-release comparison has a "before".
|
|
40
|
+
|
|
3
41
|
## [3.6.0] - 2026-09-30
|
|
4
42
|
|
|
5
43
|
### Added
|
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@ This Git repository is the source of truth; `dev.akitao.com` is the presentation
|
|
|
34
34
|
- [Usage model](#usage-model)
|
|
35
35
|
- [Repository layout](#repository-layout)
|
|
36
36
|
- [What the installer does](#what-the-installer-does)
|
|
37
|
+
- [Optional: rtk](#optional-rtk)
|
|
37
38
|
- [Gemini / Antigravity model](#gemini--antigravity-model)
|
|
38
39
|
- [What is excluded](#what-is-excluded)
|
|
39
40
|
- [Why `~/.aki/akidevrule`](#why-akiakidevrule)
|
|
@@ -102,9 +103,9 @@ Loading happens on two different mechanisms.
|
|
|
102
103
|
|
|
103
104
|
**Resident — harness-embedded.** `RULE-agent-behavior.md` and the router `skills/akirule/SKILL.md` are `@`-imported by `~/.claude/CLAUDE.md`, which Claude Code reads mechanically at session start. No model decision is involved, so the behavior floor applies to every task and the routing is always present. The router joined the imports because as a skill it went uninvoked until the owner asked for it by name. `@` imports have this effect **only** inside `CLAUDE.md` — the same syntax written into a skill body looks like an import but loads nothing, because a skill body is read only after the model has already chosen to invoke the skill.
|
|
104
105
|
|
|
105
|
-
**Everything else — routed by meaning, and gated where the artifact gives it away.** Each task turn is classified by the domains it touches and the act (create, decide, audit, ship), in any language; each route carries concept signals in English and Vietnamese as evidence, never as the test, so a paraphrase routes as well as the listed word. The one model-dependent hop left is the `Read` of a routed file, and on Claude Code the `aki-route-guard` PreToolUse hook (`claude/hooks/aki-route-guard.mjs`) enforces it for every route with an artifact signature: the first Edit/Write of each artifact type in a session — a code file (`coding` + `pattern`), `.md` (`docs`), `CHANGELOG.md` (`release`), `.vue`/`.css` (`ui`, plus `stack` in a Nuxt project), `.rs` (`tauri`), `.sql` (`db`), `locales/` (`content`) — is denied until those files have been read in that transcript; a subagent is gated on its own transcript. Zero model hops in the check, at most one denial per artifact type per session, fail-open on any error, `AKI_ROUTE_GUARD=0` disables it. `RULE-coding.md` and `RULE-pattern-core.md` were resident imports from 2026-08-06 to 2026-09-30 because the router as a skill went uninvoked; importing the router restored the routing but not the read (measured: the model read a routed file unprompted in about one session in five — `docs/research/rule-delivery-second-hop-sep29.md`), so the gate now restores the guarantee by mechanism and the two files load only on code turns. Meaning-only routes (`think`, `proportion`, `biz`, `ux`, the audits) stay on the router alone, with sensitivity deliberately high (err toward loading — a false positive costs a few tokens, a false negative causes wrong behavior). The one deliberate exception is a lookup: a turn that only reads, counts, locates or explains what exists routes nothing, because no rule's act is performed — those turns are the majority for many users of this corpus, and the tiering exists so they pay for nothing beyond the two resident files.
|
|
106
|
+
**Everything else — routed by meaning, and gated where the artifact gives it away.** Each task turn is classified by the domains it touches and the act (create, decide, audit, ship), in any language; each route carries concept signals in English and Vietnamese as evidence, never as the test, so a paraphrase routes as well as the listed word. The one model-dependent hop left is the `Read` of a routed file, and on Claude Code the `aki-route-guard` PreToolUse hook (`claude/hooks/aki-route-guard.mjs`) enforces it for every route with an artifact signature: the first Edit/Write of each artifact type in a session — a code file (`coding` + `pattern`), `.md` (`docs`), `CHANGELOG.md` (`release`), `.vue`/`.css` (`ui`, plus `stack` in a Nuxt project), `.rs` (`tauri`), `.sql` (`db`), `locales/` (`content`) — is denied until those files have been read whole in that transcript (a `limit`/`offset` or `head` read does not count, and the hook widens a partial `Read` of a rule file to the whole file); the path → rule map is the data file `payload/route-map.json`, not hook code; a subagent is gated on its own transcript. Zero model hops in the check, at most one denial per artifact type per session, fail-open on any error, `AKI_ROUTE_GUARD=0` disables it. `RULE-coding.md` and `RULE-pattern-core.md` were resident imports from 2026-08-06 to 2026-09-30 because the router as a skill went uninvoked; importing the router restored the routing but not the read (measured: the model read a routed file unprompted in about one session in five — `docs/research/rule-delivery-second-hop-sep29.md`), so the gate now restores the guarantee by mechanism and the two files load only on code turns. Meaning-only routes (`think`, `proportion`, `biz`, `ux`, the audits) stay on the router alone, with sensitivity deliberately high (err toward loading — a false positive costs a few tokens, a false negative causes wrong behavior). The one deliberate exception is a lookup: a turn that only reads, counts, locates or explains what exists routes nothing, because no rule's act is performed — those turns are the majority for many users of this corpus, and the tiering exists so they pay for nothing beyond the two resident files.
|
|
106
107
|
|
|
107
|
-
- **Contextual and analytical — read on route match:** `RULE-coding.md` (code-quality floor: source of truth, changing existing code, verification and the hand-off ladder, comment budget, runtime safety), `RULE-pattern-core.md` (the 9 structural laws, decomposition, the critique gate before any abstraction), `RULE-docs.md` (structure and lifecycle, evidence-bound `ref/fact-*` fact docs, plus the docs-vs-code drift audit), `RULE-content-write.md` (UI copy and writing style, plus the content audit — canonical-term drift, density deletion test, i18n coverage, fact-check), `RULE-stack-akiNuxtCf.md`, `RULE-stack-tauri.md` (Tauri v2 + Rust: never-block-the-UI, version SSOT, target context, the macOS TCC/Gatekeeper boundary for spawned sidecars), `RULE-ui-pattern.md` (design-system layer: the subtraction pass that runs before the tier ladder, class taxonomy, tokens, variant API, and the audit playbook), `RULE-seo.md` (metadata, schema, sitemap, and URL form: relative at rest, absolute only where a consumer requires it), `RULE-release.md`, `RULE-db-design.md`, `RULE-biz.md` (market-facing decisions: positioning, pricing, audience) — plus the analytical methods (`METHOD-*`, loaded on route match like the rest): `METHOD-audit-flow.md` (refactors, multi-file bugs, fragile flows), `METHOD-audit-zero-trust.md` (strict mechanical-first audit: detectors before opinion, exact matches separated from pattern-level candidates), `METHOD-deep-think.md` (scope/architecture/value decisions, first-principles and critique-style thinking), `METHOD-ux-psych.md` (UX/user-behavior evaluation, onboarding and conversion flows), `METHOD-proportionality.md` (sizing a guard, limit or accepted risk against reach, capability, motive and blast radius — the lens that stops both over-engineering and client-side-limits-as-enforcement), `METHOD-audit-subtraction.md` (repo-wide "does this need to exist" sweep, terminating on two dry rounds), and `METHOD-audit-frozen-reference.md` (compliance audit for a clause naming a concrete external artifact as the canonical shape to match — resolve to an exact path, diff literally against it, never judge from memory of the rule's prose).
|
|
108
|
+
- **Contextual and analytical — read on route match:** `RULE-coding.md` (code-quality floor: source of truth, changing existing code, verification and the hand-off ladder, comment budget, runtime safety), `RULE-pattern-core.md` (the 9 structural laws, decomposition, the critique gate before any abstraction), `RULE-test.md` (fewest tests: no new test by default, no new test file or folder when one fits, nothing touched the test does not own, a verdict that means what it exercised — gated on test-file edits), `RULE-docs.md` (structure and lifecycle, evidence-bound `ref/fact-*` fact docs, plus the docs-vs-code drift audit), `RULE-content-write.md` (UI copy and writing style, plus the content audit — canonical-term drift, density deletion test, i18n coverage, fact-check), `RULE-stack-akiNuxtCf.md`, `RULE-stack-tauri.md` (Tauri v2 + Rust: never-block-the-UI, version SSOT, target context, the macOS TCC/Gatekeeper boundary for spawned sidecars), `RULE-ui-pattern.md` (design-system layer: the subtraction pass that runs before the tier ladder, class taxonomy, tokens, variant API, and the audit playbook), `RULE-seo.md` (metadata, schema, sitemap, and URL form: relative at rest, absolute only where a consumer requires it), `RULE-release.md`, `RULE-db-design.md`, `RULE-biz.md` (market-facing decisions: positioning, pricing, audience) — plus the analytical methods (`METHOD-*`, loaded on route match like the rest): `METHOD-audit-flow.md` (refactors, multi-file bugs, fragile flows), `METHOD-audit-zero-trust.md` (strict mechanical-first audit: detectors before opinion, exact matches separated from pattern-level candidates), `METHOD-deep-think.md` (scope/architecture/value decisions, first-principles and critique-style thinking), `METHOD-ux-psych.md` (UX/user-behavior evaluation, onboarding and conversion flows), `METHOD-proportionality.md` (sizing a guard, limit or accepted risk against reach, capability, motive and blast radius — the lens that stops both over-engineering and client-side-limits-as-enforcement), `METHOD-audit-subtraction.md` (repo-wide "does this need to exist" sweep, terminating on two dry rounds), and `METHOD-audit-frozen-reference.md` (compliance audit for a clause naming a concrete external artifact as the canonical shape to match — resolve to an exact path, diff literally against it, never judge from memory of the rule's prose).
|
|
108
109
|
- **Full load on explicit request:** asking, in any wording, to load the whole corpus reads every `RULE-*`/`METHOD-*` file at once.
|
|
109
110
|
|
|
110
111
|
No harness magic beyond the `CLAUDE.md` import: routes are instructions telling Claude to Read the file from `~/.aki/akidevrule/` when the task's domain matches; the full-load request is the escape hatch.
|
|
@@ -184,6 +185,7 @@ payload/ → installed to ~/.aki/akidevrule/
|
|
|
184
185
|
RULE-seo.md
|
|
185
186
|
RULE-release.md
|
|
186
187
|
RULE-db-design.md
|
|
188
|
+
RULE-test.md
|
|
187
189
|
RULE-biz.md
|
|
188
190
|
METHOD-audit-flow.md
|
|
189
191
|
METHOD-audit-zero-trust.md
|
|
@@ -191,6 +193,8 @@ payload/ → installed to ~/.aki/akidevrule/
|
|
|
191
193
|
METHOD-ux-psych.md
|
|
192
194
|
METHOD-proportionality.md
|
|
193
195
|
METHOD-audit-subtraction.md
|
|
196
|
+
METHOD-audit-frozen-reference.md
|
|
197
|
+
route-map.json → path → rule map read by the route gate, the audit and the lint (data, not a rule)
|
|
194
198
|
GEMINI.md → installed to ~/.gemini/GEMINI.md (NOT a rule file)
|
|
195
199
|
|
|
196
200
|
skills/ → shared Agent Skills corpus (SKILL.md open standard), deployed
|
|
@@ -203,6 +207,7 @@ skills/ → shared Agent Skills corpus (SKILL.md open
|
|
|
203
207
|
akiflow/scripts/council_verify.py (mechanical closure gate: ghost seats, missing evidence tags, unanswered REMINDs)
|
|
204
208
|
akiflow/scripts/scythe.py (penalty-card lint [WRAP]/[YAP] — shared engine of /akilint and the enforcer's evidence sweeps)
|
|
205
209
|
akiflow/scripts/release_lint.py (release-record lint: CHANGELOG section order/vocabulary/level, releases.json parity, type keys, highlight review — RULE-release.md C4, B7 step 4)
|
|
210
|
+
akiflow/scripts/suite_lint.py (test-file lint: literal /tmp, missing temp cleanup, exit calls as verdicts; sleeps, vacuous asserts, ambient ifs, HOME reads, live URLs, ports, source pins, history comments as review — RULE-test.md D1)
|
|
206
211
|
akiflow/scripts/*.sh (transitional Unix wrappers, one per script above — each execs its .py sibling)
|
|
207
212
|
akiflow/references/harness-facts.md (subagent/cost/model facts, with sources)
|
|
208
213
|
akithink/SKILL.md
|
|
@@ -217,7 +222,8 @@ skills/ → shared Agent Skills corpus (SKILL.md open
|
|
|
217
222
|
|
|
218
223
|
scripts/ → repo-only tooling, never installed
|
|
219
224
|
test-agy-bias.sh (6-trap agy/Gemini bias regression suite, runnable by anyone with agy — docs/plan/done/agy-helpful-bias-containment.md §3)
|
|
220
|
-
second_hop_audit.py (measures, per route and era, whether Claude Code sessions read the routed rule before the first edit — docs/research/rule-delivery-second-hop-sep29.md)
|
|
225
|
+
second_hop_audit.py (measures, per route and era, whether Claude Code sessions read the routed rule before the first edit — docs/research/rule-delivery-second-hop-sep29.md; `--by-model` adds the per-model compaction and shell-read table behind agent.B7)
|
|
226
|
+
codex_probe.sh (Mac hand-off: records the Codex CLI version and whether the managed AGENTS.md block reaches a fresh session — spends one Codex turn)
|
|
221
227
|
|
|
222
228
|
claude/ → Claude Code-only runtime assets, installed to ~/.claude/
|
|
223
229
|
CLAUDE.md
|
|
@@ -228,7 +234,8 @@ claude/ → Claude Code-only runtime assets, installed
|
|
|
228
234
|
agents/aki-maker.md
|
|
229
235
|
hooks/aki-update-check.mjs
|
|
230
236
|
hooks/aki_version_check.mjs (shared version-status parser, imported by both the hook and install.mjs --check)
|
|
231
|
-
hooks/aki-route-guard.mjs (PreToolUse route gate: denies the first edit of an artifact type until its routed rule was Read)
|
|
237
|
+
hooks/aki-route-guard.mjs (PreToolUse route gate: denies the first edit of an artifact type until its routed rule was Read whole after the last compaction; widens partial Reads of rule files; reads ~/.aki/akidevrule/route-map.json)
|
|
238
|
+
hooks/aki-compact-reread.mjs (SessionStart on `compact` only: one notice that the rules read earlier left context)
|
|
232
239
|
fragments/settings.akidoc.fragment.json (illustrative reference only — never apply manually)
|
|
233
240
|
|
|
234
241
|
docs/ → repo-internal records; one TCC lookup is installed
|
|
@@ -257,7 +264,7 @@ flowchart TD
|
|
|
257
264
|
CSKILLS["skills/ (11 skills, shared open standard)"]
|
|
258
265
|
CCLAUDE["claude/CLAUDE.md (template)"]
|
|
259
266
|
CAGENTS["claude/agents/ (5 agent definitions)"]
|
|
260
|
-
CHOOKS["claude/hooks/aki-update-check.mjs + aki_version_check.mjs (shared parser)"]
|
|
267
|
+
CHOOKS["claude/hooks/ aki-update-check.mjs + aki_version_check.mjs (shared parser) · aki-route-guard.mjs · aki-compact-reread.mjs"]
|
|
261
268
|
end
|
|
262
269
|
|
|
263
270
|
INSTALL["⚙️ install.mjs (via install.sh / install.ps1)"]
|
|
@@ -277,7 +284,7 @@ flowchart TD
|
|
|
277
284
|
C_LOCAL["CLAUDE.local.md (Machine local)"]
|
|
278
285
|
C_SKILLS["skills/<skill_name>/SKILL.md"]
|
|
279
286
|
C_AGENTS["agents/aki-*.md (copied per file, your own agents kept)"]
|
|
280
|
-
C_HOOKS["hooks/aki-update-check.mjs + aki_version_check.mjs"]
|
|
287
|
+
C_HOOKS["hooks/ aki-update-check.mjs + aki_version_check.mjs · aki-route-guard.mjs · aki-compact-reread.mjs"]
|
|
281
288
|
C_SET["settings.json (Permissions + Skill Overrides)"]
|
|
282
289
|
end
|
|
283
290
|
|
|
@@ -291,8 +298,9 @@ flowchart TD
|
|
|
291
298
|
end
|
|
292
299
|
|
|
293
300
|
%% TARGETS 4-6: other CLIs that natively consume the SKILL.md standard
|
|
294
|
-
subgraph T4["🧩 4. Codex CLI (~/.agents/skills/)"]
|
|
301
|
+
subgraph T4["🧩 4. Codex CLI (~/.agents/skills/ + $CODEX_HOME/)"]
|
|
295
302
|
X_SKILLS["<skill_name>/SKILL.md"]
|
|
303
|
+
X_AGENTS["AGENTS.md managed block (behavior floor + router) + config.toml project_doc_max_bytes"]
|
|
296
304
|
end
|
|
297
305
|
subgraph T5["🧩 5. Kiro CLI (~/.kiro/skills/)"]
|
|
298
306
|
K_SKILLS["<skill_name>/SKILL.md"]
|
|
@@ -309,23 +317,51 @@ flowchart TD
|
|
|
309
317
|
INSTALL -->|"sync per skill folder"| T6
|
|
310
318
|
```
|
|
311
319
|
|
|
312
|
-
Targets
|
|
320
|
+
Targets 5-6 only get the shared skill corpus (no rule corpus / no `CLAUDE.md`/`GEMINI.md`-style overrides — those CLIs have no equivalent hard-load hook this baseline plugs into yet). Target 4 also gets the behavior floor and the router as a managed block in `$CODEX_HOME/AGENTS.md` (default `~/.codex/AGENTS.md`), the one file Codex hard-loads globally — only when that directory exists, lines of your own in the file are kept, and `project_doc_max_bytes` is written to `config.toml` when absent because Codex stops loading instruction files once global plus project files pass 32 KiB (the block alone is ~36 KB). Codex expands no `@` imports and never reads Claude's global file, so copying `~/.claude/CLAUDE.md` would deliver nothing (`docs/research/codex-instruction-delivery.md`). A project's `CLAUDE.md` stays unread unless you opt in per machine with `project_doc_fallback_filenames = ["CLAUDE.md"]`; a native `AGENTS.md` in the same directory wins over it. Each sync is scoped per skill folder name via a Node `fs` copy plus a managed-names-only prune, same never-touch-the-rest guarantee as targets 2 and 3, and runs unconditionally — harmless if that CLI isn't installed on the machine, picked up the moment it is.
|
|
313
321
|
|
|
314
322
|
1. Syncs `payload/*` into `~/.aki/akidevrule/` (Node `fs` copy, excludes `ref-ECC/`), removes stale files left by renames, syncs `agskills/` for Antigravity skill inheritance, and deploys the full TCC lookup to `~/.aki/akidevrule/docs/ref/fact-macos-codesign-tcc.md`.
|
|
315
323
|
2. Deploys to **all detected Claude config directories** — `~/.claude` (default primary), all existing `~/.claude*` profile variants (e.g. `~/.claude-9rt`, `~/.claude-prx`), plus `$CLAUDE_CONFIG_DIR` or `--claude-dir <path>` if provided:
|
|
316
324
|
- Syncs every skill folder under `skills/*/` (whole directory, including any `references/` or `scripts/`) into `<target>/skills/`, one named folder at a time (copy + managed-names-only prune), removing only Aki's own old/renamed skill directories (`akidoc-*`, `akiadvise`) — any other skill you already have is never touched. `skills/` is a top-level, agent-neutral folder (siblings with `payload/`, not nested under `claude/`) because SKILL.md is a shared open standard both Claude Code and Antigravity/AGY consume identically — see [docs/ref/fact-agent-skills-standard.md](docs/ref/fact-agent-skills-standard.md).
|
|
317
325
|
- Copies `claude/agents/*.md` into `<target>/agents/` **file by file, never a directory mirror with `--delete`** — that folder is a shared namespace where your own agent definitions sit beside Aki's, exactly like `<target>/skills/`, so nothing you did not install is ever removed.
|
|
318
|
-
- Replaces `<target>/CLAUDE.md` with the packaged guidance (timestamped backup first), appending this machine's source-repo path and an `@<target>/CLAUDE.local.md` import.
|
|
326
|
+
- Replaces `<target>/CLAUDE.md` with the packaged guidance (timestamped backup first, removed once the run succeeds), appending this machine's source-repo path and an `@<target>/CLAUDE.local.md` import.
|
|
319
327
|
- Creates `<target>/CLAUDE.local.md` **only if missing** — never overwritten afterward. On profile variants (`~/.claude-*`), the template imports `@~/.claude/CLAUDE.local.md` by default so machine-wide facts are inherited. Put per-machine/per-profile rules there; they survive every reinstall.
|
|
320
|
-
- Before the confirmation prompt or any mutation, preflights every existing JSON file it may update: each detected profile's `settings.json`, `~/.gemini/config/skills.json`, `~/.gemini/antigravity-cli/settings.json`, and `~/.gemini/settings.json`. A malformed file or non-object root aborts the install with originals untouched. After preflight, updates `<target>/settings.json` with a timestamped backup: read permission for `~/.aki/akidevrule/**`, one `Bash(<launcher> <script>*)` rule per Aki skill script per rendering (absolute and `~/`-literal — Claude Code does not expand `~` before matching), `skillOverrides.akirule = "on"`, idempotent registration of the `SessionStart` update-check hook.
|
|
321
|
-
- Installs `<target>/hooks/aki-update-check.mjs` plus its shared parser `<target>/hooks/aki_version_check.mjs`,
|
|
328
|
+
- Before the confirmation prompt or any mutation, preflights every existing JSON file it may update: each detected profile's `settings.json`, `~/.gemini/config/skills.json`, `~/.gemini/antigravity-cli/settings.json`, and `~/.gemini/settings.json`. A malformed file or non-object root aborts the install with originals untouched. After preflight, updates `<target>/settings.json` with a timestamped backup (removed once the run succeeds): read permission for `~/.aki/akidevrule/**`, one `Bash(<launcher> <script>*)` rule per Aki skill script per rendering (absolute and `~/`-literal — Claude Code does not expand `~` before matching), `skillOverrides.akirule = "on"`, idempotent registration of the `SessionStart` update-check hook.
|
|
329
|
+
- Installs `<target>/hooks/aki-update-check.mjs` plus its shared parser `<target>/hooks/aki_version_check.mjs`, `<target>/hooks/aki-route-guard.mjs` registered as a `PreToolUse` hook on `Edit|MultiEdit|Write|NotebookEdit` and on `Read` (the `Read` branch widens a partial read of a rule file), and `<target>/hooks/aki-compact-reread.mjs` registered as a `SessionStart` hook with matcher `compact` (all idempotent, same filter-then-push as the update check).
|
|
322
330
|
3. Writes `~/.aki/akidevrule/.version` with `installed=`/`version=`/`commit=`/`branch=` and records the source-repo path in `~/.aki/akidevrule/.source-repo` — `version=` is the just-installed CHANGELOG's latest released semver, the same value `install.mjs --check` and the hook compare against remote.
|
|
323
331
|
4. Installs `payload/GEMINI.md` to `~/.gemini/GEMINI.md` — Antigravity global behavior overrides, stamped with a version marker (`[AKIRULE-AG-OVERRIDES-…]`) on line 1. Generates one native rule file per `RULE-*`/`METHOD-*` under `~/.gemini/config/rules/` with YAML `trigger` frontmatter — `agent` `always_on`, the stacks `glob`, the rest `model_decision` — each description generated from its `akirule` route, so both harnesses route from one table. Deploys 11 skills directly to `~/.gemini/config/skills/` for native auto-discovery (synced per skill folder, same never-touch-the-rest guarantee as step 2), configures `~/.gemini/config/skills.json` with absolute paths as secondary, and merges skill execution permissions into `~/.gemini/antigravity-cli/settings.json` and `~/.gemini/settings.json` — a `command()` prefix rule for every `skills/*/scripts/*.py` per skill root, in both the expanded and the tilde-literal rendering (agy's matcher compares command strings literally — no glob expansion, and no tilde expansion in either direction — so a directory wildcard never matches and a rule only matches a command written the same way; see [docs/ref/fact-cli-permission-allowlist-standard.md](docs/ref/fact-cli-permission-allowlist-standard.md) §1.2) plus scoped `write_file`/`read_file` rules for the council workspace and rule corpus.
|
|
324
|
-
5. Syncs the same skill folders to `~/.agents/skills/` (Codex CLI, Cursor), `~/.kiro/skills/` (Kiro CLI), and `~/.grok/skills/` (Grok CLI) — each a plain global skills root these CLIs read natively, synced per skill folder name exactly like step 2.
|
|
332
|
+
5. Syncs the same skill folders to `~/.agents/skills/` (Codex CLI, Cursor), `~/.kiro/skills/` (Kiro CLI), and `~/.grok/skills/` (Grok CLI) — each a plain global skills root these CLIs read natively, synced per skill folder name exactly like step 2. Kiro and Grok are skills-only. Codex additionally gets the managed `AGENTS.md` block and the `project_doc_max_bytes` key described above, only when `$CODEX_HOME` (default `~/.codex`) exists; the summary names the block size, the budget written or found, and a non-empty `AGENTS.override.md` that would shadow it.
|
|
325
333
|
6. Pre-allows every Aki skill script in each harness present on the machine, one adapter per rule dialect (`lib/permissions.mjs`): `~/.kiro/settings/permissions.yaml` (a marker-delimited managed block), `~/.codex/rules/akidevrule.rules` (a file akidevrule owns), `~/.cursor/cli-config.json` (`Shell(python3:<script>*)`, never a bare `Shell(python3)`), `~/.config/opencode/opencode.json` (`permission.bash`). Every rule names one exact script, in both path renderings; entries a previous install wrote are replaced, the user's own are kept. Grok CLI and Ollama have no file-based allowlist, so nothing is written for them — [docs/ref/fact-cli-permission-allowlist-standard.md](docs/ref/fact-cli-permission-allowlist-standard.md).
|
|
326
334
|
|
|
335
|
+
7. If `rtk` is on `PATH`, asks once — in a terminal only — whether to write its accuracy-first config (next section). Default, and the only answer when there is no terminal, is to leave rtk alone; the summary then prints one line saying so, with the `--rtk` flag that opts in without a prompt.
|
|
336
|
+
|
|
327
337
|
Re-running the installer updates the same managed files cleanly.
|
|
328
338
|
|
|
339
|
+
## Optional: rtk
|
|
340
|
+
|
|
341
|
+
[rtk](https://github.com/rtk-ai/rtk) is an output compressor that hooks into Claude Code's Bash tool and rewrites commands so their output comes back shorter. It is not required and the installer never installs it. What it saves is real on the noise class — `git status`, `git add/commit/push/pull`, package installs, build logs. What it costs is measured in `docs/research/rtk-output-loss-oct19.md`: its built-in filters also cut the commands an agent reads as evidence, and nothing in the shortened output says which lines are gone. Tested on rtk 0.50.0, raw against filtered: `ls` merges directories, caps at 50 entries and drops names ending in `.` with no marker; `grep` cuts lines at 80 characters and keeps 211 of 480; `find` hides dotfiles and gitignored paths; `git log` stops at 10 commits with no "more" line; `git diff` kept 610 of 7,541 lines; `jq` cuts every line at 120 characters. An agent that counts, quotes, diffs or claims "not found" from that output is wrong without knowing it, and the recovery hints rtk prints were followed 3 times in 480 elisions on the dev box. Large output needs no compressor to stay safe: Claude Code itself saves any Bash output past about 30,000 characters to a file and hands the model the path.
|
|
342
|
+
|
|
343
|
+
rtk has no lossless mode (upstream issue #1313, open since 2026-04), and its built-in filters ignore `filters.toml`. The one knob that makes them lossless is `[hooks] exclude_commands` in rtk's `config.toml`: a listed command is not rewritten at all. The installer offers to write exactly that — **accuracy over savings** — and only on an explicit yes:
|
|
344
|
+
|
|
345
|
+
| Answer | Effect |
|
|
346
|
+
|---|---|
|
|
347
|
+
| `y` in the terminal, or `--rtk` on the command line (`node install.mjs --rtk`, `npx @akinet/akidevrule@latest --rtk`) | writes the `[hooks]` table below into rtk's config (path taken from `rtk config`; `~/.config/rtk/config.toml` on Linux, `~/Library/Application Support/rtk/config.toml` on macOS, `%APPDATA%\rtk\config.toml` on Windows); an existing file is backed up first and other tables are kept; a `[hooks] exclude_commands` you wrote yourself is never touched — the summary lists what it still lacks |
|
|
348
|
+
| `N`, Enter, or no terminal (CI, an agent running the installer) | rtk stays exactly as it is; the summary prints one line saying so |
|
|
349
|
+
| a line `# akidevrule: rtk off` anywhere in the config | the installer skips rtk for good, even with `--rtk` |
|
|
350
|
+
|
|
351
|
+
````toml
|
|
352
|
+
# akidevrule: accuracy-first rtk — commands whose output is evidence run unfiltered (akidevrule README § Optional: rtk)
|
|
353
|
+
[hooks]
|
|
354
|
+
exclude_commands = [
|
|
355
|
+
"ls", "tree", "find", "grep", "rg", "ast-grep", "wc", "diff",
|
|
356
|
+
"cat", "head", "tail",
|
|
357
|
+
"jq", "stat", "du", "df", "ps", "ssh", "rsync", "curl", "wget",
|
|
358
|
+
"gh", "glab", "psql", "aws", "kubectl", "oc", "docker",
|
|
359
|
+
"^git(\\s+-[Cc]\\s+\\S+)*\\s+(diff|log|show|stash|branch)\\b",
|
|
360
|
+
]
|
|
361
|
+
````
|
|
362
|
+
|
|
363
|
+
Everything not listed — `git status`/`commit`/`push`, `npm`, `cargo`, `pytest`, `make` — stays compressed, and the rule corpus covers that residue: `coding.B3` treats any output carrying an elision marker as a sample and reruns it raw (`RTK_DISABLED=1 <cmd>`) before counting or quoting from it. The exclusion list is honoured on every rtk from 0.47.0 to 1.0.1 (hook-tested on 0.47.0, 0.50.0 and 1.0.1); the 1.0 line adds pipelines, `rtk bypass`, and a licence split (Apache-2.0 CLI plus a BUSL-1.1 compression engine, free for production use; `rtk-oss` is Apache-only without the engine), none of which changes the config above. From 0.49.0 you may also enlarge the recall store, which fills in days at its default of 200 entries: `[retriever] mode = "sqlite"`, `max_entries = 2000`, `retention_days = 30` — not written by the installer, since older rtk versions have no sqlite store (they ignore the table). Decision trail: `docs/plan/rtk-accuracy-first.md`.
|
|
364
|
+
|
|
329
365
|
## Gemini / Antigravity model
|
|
330
366
|
|
|
331
367
|
Claude Code loads the core and the router automatically (harness-guaranteed `@`-imports in `~/.claude/CLAUDE.md`). Antigravity/Gemini has no such loader, so the split is: `~/.gemini/GEMINI.md` carries **hard-loaded behavior overrides** that patch Antigravity's weak spots (unrequested artifacts, over-engineering, verbosity), native rules route the corpus with descriptions generated from the `akirule` routes, and a tiny per-project `GEMINI.md` bootstrap points the agent at that project's `CLAUDE.md` as its single source of truth. The per-project bootstrap is copied into a project by hand (it is not distributed by the installer).
|
|
@@ -351,15 +387,16 @@ rm -rf ~/.agents/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitco
|
|
|
351
387
|
rm -rf ~/.kiro/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,akiopen,akiship,aki-article-writer,akidevsync-notes} # Kiro CLI
|
|
352
388
|
rm -rf ~/.grok/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,akiopen,akiship,aki-article-writer,akidevsync-notes} # Grok CLI (other, non-Aki skills already in this folder are untouched)
|
|
353
389
|
rm -f ~/.claude/agents/aki-{hands,judge,conduct,challenger,maker}.md # your own agents in that folder are untouched
|
|
354
|
-
rm -f ~/.claude/hooks/aki-update-check.mjs ~/.claude/hooks/aki_version_check.mjs ~/.claude/hooks/aki-route-guard.mjs
|
|
355
|
-
# then delete the
|
|
356
|
-
|
|
390
|
+
rm -f ~/.claude/hooks/aki-update-check.mjs ~/.claude/hooks/aki_version_check.mjs ~/.claude/hooks/aki-route-guard.mjs ~/.claude/hooks/aki-compact-reread.mjs ~/.claude/hooks/aki-update-check.py ~/.claude/hooks/aki_version_check.py
|
|
391
|
+
# then delete the three entries whose command names those hooks from hooks.SessionStart and hooks.PreToolUse in ~/.claude/settings.json
|
|
392
|
+
# Codex: delete the `>>> akidevrule managed` … `<<< akidevrule managed` block in ~/.codex/AGENTS.md (the rest is yours), and the project_doc_max_bytes line in ~/.codex/config.toml if unwanted
|
|
357
393
|
rm -f ~/.gemini/GEMINI.md # restore from a *.akidevrule-backup-* if needed; GEMINI.local.md is left untouched
|
|
394
|
+
# rtk, only if you answered y: remove the `# akidevrule: accuracy-first rtk` [hooks] table from rtk's config.toml (`rtk config` prints its path)
|
|
358
395
|
```
|
|
359
396
|
|
|
360
397
|
On **Windows** the same targets live under `%USERPROFILE%` (e.g. `%USERPROFILE%\.aki\akidevrule`, `%USERPROFILE%\.claude\skills\...`); remove them with `Remove-Item -Recurse -Force`.
|
|
361
398
|
|
|
362
|
-
Then remove the akidevrule block from `~/.claude/CLAUDE.md` and its entries (permission, skillOverrides, SessionStart and PreToolUse hooks) from `~/.claude/settings.json` if desired.
|
|
399
|
+
Then remove the akidevrule block from `~/.claude/CLAUDE.md` and its entries (permission, skillOverrides, SessionStart and PreToolUse hooks) from `~/.claude/settings.json` if desired. `~/.codex/rules/akidevrule.rules` is a whole file the installer owns and can simply be deleted.
|
|
363
400
|
|
|
364
401
|
## Content for dev.akitao.com
|
|
365
402
|
|
package/claude/CLAUDE.md
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
@~/.aki/akidevrule/RULE-agent-behavior.md
|
|
4
4
|
@~/.claude/skills/akirule/SKILL.md
|
|
5
5
|
|
|
6
|
-
The harness embeds both at session start: the behavior floor and the router. Every other rule enters context when the model `Read`s it on a route match. For routes with an artifact signature the `aki-route-guard` PreToolUse hook denies the first Edit/Write of that artifact type in a session until the routed files were read — the deny reason names them; read them in full, then retry. Meaning-only routes stay model-dependent: route on meaning, load when the domain is in doubt. A turn that only reads, counts or explains what exists routes nothing.
|
|
6
|
+
The harness embeds both at session start: the behavior floor and the router. Every other rule enters context when the model `Read`s it on a route match. For routes with an artifact signature the `aki-route-guard` PreToolUse hook denies the first Edit/Write of that artifact type in a session until the routed files were read whole after the last compaction — the deny reason names them; read them in full, then retry. Meaning-only routes stay model-dependent: route on meaning, load when the domain is in doubt. A turn that only reads, counts or explains what exists routes nothing.
|
|
7
7
|
|
|
8
8
|
Doc corpora named by short name in conversation ("UNIDOC", "the standards doc") are machine-specific: resolve them in `~/.claude/CLAUDE.local.md` before searching or asking.
|
|
@@ -20,7 +20,7 @@ Report which class every violation belongs to. A violation with no class attache
|
|
|
20
20
|
|
|
21
21
|
# Rules you must read before working
|
|
22
22
|
|
|
23
|
-
- `~/.aki/akidevrule/RULE-agent-behavior.md` — the behavior floor; §0 penalty cards are your vocabulary, `B5` binds you as read-only like every other judge.
|
|
23
|
+
- `~/.aki/akidevrule/RULE-agent-behavior.md` — the behavior floor; §0 penalty cards are your vocabulary, `B7` names the harness directives behind `[SKIP]`, `B5` binds you as read-only like every other judge.
|
|
24
24
|
- `~/.aki/akidevrule/RULE-coding.md` — `B4` only, the comment budget behind `[YAP]`.
|
|
25
25
|
|
|
26
26
|
# Receipt — first line of your output, always
|
|
@@ -43,6 +43,8 @@ Run it **at the end of a round, and only when the round wrote durable files.** L
|
|
|
43
43
|
|
|
44
44
|
`[FLUFF]` — padded prose that fails the deletion test — is content judgment and is yours to make by reading. No script produces it, and none ever should.
|
|
45
45
|
|
|
46
|
+
`[SKIP]` — a mandatory step (a read, a receipt, a check, a critique, a re-anchor) skipped or compressed under a harness brevity or speed directive (`agent.B7`) — is yours too. Classify it COMPLY-fail and name the harness line the transcript shows being obeyed instead; after a compaction, a missing receipt or an edit with no re-read is the first place to look.
|
|
47
|
+
|
|
46
48
|
Everything else greppable (credit trailers `agent.B4`, temp files outside the scratchpad `agent.C5`, missing evidence tags) goes to `aki-hands` with exact paths and patterns. A reminder without a quoted `file:line` is noise and does not ship.
|
|
47
49
|
|
|
48
50
|
# Output contract
|
|
@@ -13,7 +13,7 @@ If the brief asks you to decide something, return the evidence and say the quest
|
|
|
13
13
|
|
|
14
14
|
# Rules you must read before working
|
|
15
15
|
|
|
16
|
-
- `~/.aki/akidevrule/RULE-agent-behavior.md` — the behavior floor. `A4` (density), `B2` (verified vs assumed), `B5` (audit is read-only, never mutate git state), `C3` (never hard-wrap a logical line), `C5` (
|
|
16
|
+
- `~/.aki/akidevrule/RULE-agent-behavior.md` — the behavior floor. `A4` (density), `B2` (verified vs assumed), `B5` (audit is read-only, never mutate git state), `C3` (never hard-wrap a logical line), `C5` (no throwaway file the task can do without, and none outside the scratchpad).
|
|
17
17
|
|
|
18
18
|
Nothing else, unless the spawning brief names a file. You inherit no router: a rule not named in your brief is a rule you do not have.
|
|
19
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: aki-judge
|
|
3
|
-
description: Judge an artifact against exactly one standard, named at spawn (pattern, proportion, ux, db, seo, release, …). Returns a verdict with evidence, never a fix. Spawn one per standard rather than asking one agent to hold several.
|
|
3
|
+
description: Judge an artifact against exactly one standard, named at spawn (pattern, proportion, ux, db, seo, release, test, …). Returns a verdict with evidence, never a fix. Spawn one per standard rather than asking one agent to hold several.
|
|
4
4
|
tools: Read, Grep, Glob
|
|
5
5
|
model: sonnet
|
|
6
6
|
---
|
|
@@ -15,9 +15,10 @@ Change exactly what was asked. No adjacent refactors, no cleanup, no renames, no
|
|
|
15
15
|
|
|
16
16
|
# Rules you must read before working
|
|
17
17
|
|
|
18
|
-
- `~/.aki/akidevrule/RULE-agent-behavior.md` — the behavior floor: `B1` scope discipline, `B3` what to ask before, `B4` no model-credit trailers in any git artifact, `C3` never hard-wrap a logical line, `C5`
|
|
18
|
+
- `~/.aki/akidevrule/RULE-agent-behavior.md` — the behavior floor: `B1` scope discipline, `B3` what to ask before, `B4` no model-credit trailers in any git artifact, `C3` never hard-wrap a logical line, `C5` no throwaway file the task can do without, and none outside the scratchpad.
|
|
19
19
|
- `~/.aki/akidevrule/RULE-coding.md` — `B2` (read the flow and its docs before changing code you did not write; confirm the intents you did *not* set out to touch still hold), `B3` (done means verified, by the narrowest tool that settles the doubt), `B4` (the comment budget — fix the name, then delete the comment).
|
|
20
20
|
- `~/.aki/akidevrule/RULE-pattern-core.md` — `C1` is the definition of done at the pattern level.
|
|
21
|
+
- `~/.aki/akidevrule/RULE-test.md` — only when the diff touches a test file, fixture or test config; the route gate denies the first such edit until it is read, so read it first.
|
|
21
22
|
- **The domain rules named in your brief** — stack, ui, db, docs, content, whichever apply. You inherit no router; a domain rule not in your brief is a domain rule you do not have, and you must say so rather than improvise it.
|
|
22
23
|
|
|
23
24
|
# Receipt — first line of your output, always
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Fires on `compact` only: rule files read before a compaction are gone from context while the summary reads as if they were not. Rationale: docs/arch/rule-delivery-architecture.md § Compaction.
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
|
|
5
|
+
const NOTICE =
|
|
6
|
+
"[akidevrule] Context was just compacted: rule files read before this point are no longer in context, and the route gate counts reads only after the compaction. Before the next edit, re-read the routed rule files it needs and emit a [RULES] line for the set now in context; before closing a multi-step task, re-read the originating request verbatim (agent.B7).";
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const input = JSON.parse(readFileSync(0, "utf8"));
|
|
10
|
+
if (input.source === "compact") {
|
|
11
|
+
process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: NOTICE }, suppressOutput: true }) + "\n");
|
|
12
|
+
}
|
|
13
|
+
} catch {
|
|
14
|
+
/* fail silent: a notice must never block a session start */
|
|
15
|
+
}
|
|
16
|
+
process.exit(0);
|