@akinet/akidevrule 3.0.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +835 -0
  2. package/LICENSE +21 -0
  3. package/README.md +356 -0
  4. package/claude/CLAUDE.md +40 -0
  5. package/claude/agents/aki-challenger.md +38 -0
  6. package/claude/agents/aki-conduct.md +54 -0
  7. package/claude/agents/aki-hands.md +59 -0
  8. package/claude/agents/aki-judge.md +37 -0
  9. package/claude/agents/aki-maker.md +36 -0
  10. package/claude/fragments/settings.akidoc.fragment.json +15 -0
  11. package/claude/hooks/aki-update-check.mjs +160 -0
  12. package/claude/hooks/aki_version_check.mjs +83 -0
  13. package/docs/ref/macos-codesign-tcc.md +59 -0
  14. package/install.mjs +1067 -0
  15. package/install.ps1 +11 -0
  16. package/install.sh +12 -0
  17. package/package.json +52 -0
  18. package/payload/GEMINI.md +147 -0
  19. package/payload/METHOD-audit-flow.md +147 -0
  20. package/payload/METHOD-audit-subtraction.md +67 -0
  21. package/payload/METHOD-audit-zero-trust.md +49 -0
  22. package/payload/METHOD-deep-think.md +172 -0
  23. package/payload/METHOD-proportionality.md +62 -0
  24. package/payload/METHOD-ux-psych.md +60 -0
  25. package/payload/RULE-agent-behavior.md +138 -0
  26. package/payload/RULE-biz.md +51 -0
  27. package/payload/RULE-coding.md +130 -0
  28. package/payload/RULE-content-write.md +54 -0
  29. package/payload/RULE-db-design.md +26 -0
  30. package/payload/RULE-docs.md +144 -0
  31. package/payload/RULE-pattern-core.md +80 -0
  32. package/payload/RULE-release.md +215 -0
  33. package/payload/RULE-seo.md +173 -0
  34. package/payload/RULE-stack-akiNuxtCf.md +179 -0
  35. package/payload/RULE-stack-tauri.md +59 -0
  36. package/payload/RULE-ui-pattern.md +167 -0
  37. package/payload/index.md +91 -0
  38. package/skills/aki-article-writer/SKILL.md +50 -0
  39. package/skills/aki-article-writer/references/article-workflow.md +377 -0
  40. package/skills/akidevsync-notes/SKILL.md +48 -0
  41. package/skills/akidevsync-notes/scripts/notes_cli.py +212 -0
  42. package/skills/akiflow/SKILL.md +221 -0
  43. package/skills/akiflow/references/harness-facts.md +215 -0
  44. package/skills/akiflow/scripts/council-cost.sh +4 -0
  45. package/skills/akiflow/scripts/council-open.sh +4 -0
  46. package/skills/akiflow/scripts/council-read.sh +4 -0
  47. package/skills/akiflow/scripts/council-verify.sh +4 -0
  48. package/skills/akiflow/scripts/council_cost.py +149 -0
  49. package/skills/akiflow/scripts/council_open.py +323 -0
  50. package/skills/akiflow/scripts/council_read.py +148 -0
  51. package/skills/akiflow/scripts/council_verify.py +315 -0
  52. package/skills/akiflow/scripts/scythe.py +307 -0
  53. package/skills/akiflow/scripts/scythe.sh +4 -0
  54. package/skills/akigitcommit/SKILL.md +85 -0
  55. package/skills/akihelp/SKILL.md +47 -0
  56. package/skills/akihtmlreport/SKILL.md +59 -0
  57. package/skills/akilint/SKILL.md +29 -0
  58. package/skills/akirule/SKILL.md +155 -0
  59. package/skills/akiship/SKILL.md +55 -0
  60. package/skills/akithink/SKILL.md +59 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,835 @@
1
+ # Changelog
2
+
3
+ ## [3.0.0] - 2026-09-13
4
+
5
+ ### Added
6
+ - **`release.B9` — registry-published packages (npm, crates.io, PyPI).** Released now means tag + GitHub Release + the registry actually serving the version. The publish mechanism is derived from the existing convention and sibling packages on the same account, never designed (no CI publish token by default); account session, scope ownership and 2FA mode are probed (`npm whoami`, `npm org ls`, `npm profile get`) instead of inferred from a package-name 404; an OTP-gated `npm publish` is the run's single hand-off; the tarball is verified before the irreversible publish, including the shell-scoping trap where `HOME=… printf | bin` runs the bin against the real home. `/akiship` probes these facts in Phase 1 and publishes in Phase 3; `akirule` now routes `RULE-release.md` on registry-publish keywords (`npm publish`, `PyPI`, `cargo publish`, …). Evidence: the first npm release of this repo, where a CI token workflow was invented against the owner's manual-publish convention, scope ownership was misreported as a blocker, and a sandbox install test overwrote the real `~/.claude` config.
7
+
8
+ ### Changed
9
+ - **BREAKING: the installer is now pure Node.js — Python is no longer required to install or update.** `install.py` is replaced by `install.mjs`, a faithful port verified byte-for-byte against the old installer (a fresh install produces 121 identical files; the only differences are the intended Node changes below). `install.sh` / `install.ps1` are now thin launchers that locate `node`. Requires **Node.js 18+** (for the built-in `fetch` used by the update check).
10
+ - **Primary install / update path is now npm:** `npx @akinet/akidevrule@latest` — zero-clone, and re-running it is how you update. Published as `@akinet/akidevrule`; `package.json` version is derived from this CHANGELOG at publish time.
11
+ - **SessionStart update hook ported to Node.** `~/.claude/hooks/aki-update-check.py` + `aki_version_check.py` become `aki-update-check.mjs` + `aki_version_check.mjs`, and the registered hook command changes from `python3 …` to `node …`. Upgrading removes the old Python hook entry and files automatically, including their `hooks/__pycache__/aki_version_check.*.pyc` bytecode (the user's own cached hooks are left untouched). The notify message now points at `npx @akinet/akidevrule@latest`.
12
+
13
+ ### Notes
14
+ - Skill helper scripts under `skills/*/scripts/` remain Python; running those skills still needs Python. Only install + update are now Python-free.
15
+ - Everything the installer deploys — rule corpus, skills, agents, and the settings/permission merges for Claude Code, Antigravity/Gemini and Kiro — is unchanged and byte-identical to 2.8.0.
16
+
17
+ ## [2.8.0] - 2026-09-07
18
+
19
+ ### Added
20
+ - **`stack.C8` execution-ownership clause — D1 migrations are `coding.B5` ladder work, not an `agent.B3` ask-first gate.** An additive/idempotent migration with a backup path available (`db.pull` or equivalent) is a two-way door: the agent backs up, runs `--local` then `--remote`, verifies postconditions, and moves the file to `scripts/done/` in the same task — no separate confirmation turn. `agent.B3`'s ask-before gate stays for the actually irreversible case (`ALTER`/`DROP`, row mutation, no backup path). `coding.B5` rung 5 is a stated precondition — `wrangler` present and authenticated (`wrangler whoami`), else a rung-5 hand-off with that reason — and `db.pull` (`bash scripts/db-pull.sh`) joins the `stack.C7` script list so the clause's backup path resolves inside the corpus. `/akiship` Phase 2's external-action bullet now points at this clause instead of always carrying a pending migration to the report as unverified. Owner-ordered 2026-09-04 after a downstream (kinhdich.akinet.me) session deferred a purely-additive migration to the owner by default, reproducing `coding.B5`'s named forbidden rationalization ("only the owner can decide") on a check that was already available work.
21
+ - **`install.py --check`** — prints installed vs latest akidevrule version and exits, no install/overwrite. Shares the classifier below; `inspect_status()` now prints the same version comparison before the confirm prompt, and skips that y/n prompt when the install already comes from this exact checkout (`.version` `commit=` == HEAD, clean tree) — installed == remote is not that criterion, since the overwrite source is the checkout and a dev machine's checkout carries `[Unreleased]` work. The SessionStart hook is now registered as `py -3` on Windows (`python3` elsewhere), the same platform split as the propagate command below, and `~/.aki/akidevrule/docs/` is recreated on every install so a renamed lookup never lingers. `.version` gains a `version=<semver>` line alongside the existing `installed=`/`commit=`/`branch=` (the just-installed CHANGELOG's latest released version).
22
+ - **`docs/ref/macos-codesign-tcc.md`** — one TCC lookup: generic of `tauri.B7` (responsible process, FDA / Files & Folders / Developer Tools — DT is not file access) merged with the rebuild/DR mechanism (DR vs CDHash, Gatekeeper vs TCC, `find-identity -v` hides untrusted identities, `codesign --force` after every Tauri bundle). Not Aki install paths or identity names. `tauri.B7` stays concise; `install.py` deploys the full lookup to `~/.aki/akidevrule/docs/ref/`.
23
+ - **`docs/ref/agents-md-standard.md`** — lookup for the `AGENTS.md` repo instruction file ([agents.md](https://agents.md/), AAIF/Linux Foundation): who hard-loads it (Cursor, Kiro, Antigravity/`agy`, Codex, …), Claude Code’s official exception (`CLAUDE.md` only; `@AGENTS.md` import), Gemini CLI still `GEMINI.md`-first unless configured, Postman Agent Mode is not a git-tree coding agent. Discriminated from `docs/ref/agent-skills-standard.md` (`SKILL.md`).
24
+ - **`agent.B2` closure re-anchor** — before reporting a multi-step task complete, re-read the originating request verbatim and tick off every explicit demand against the delivered state; misses are reported, never silently absorbed. Always-loaded (core `@` import) so it covers plain tasks, `/akiship` acceptance, and akiflow leads alike; akiflow's REQ-coverage gate keeps owning the in-council case. Evidence: an aiobox `/akiflow` run whose lead skipped the prompt's explicit final self-check demand at acceptance, plus the agy incident below dropping prompt parts. Owner-ordered 2026-08-23; plan `docs/plan/done/v2.7-agy-suppression.md`.
25
+ - **`payload/GEMINI.md` rule 14 — skill-token dispatch, process before product.** A `/token` naming an installed skill must be dispatched (read `SKILL.md`, follow its protocol) before any other action, even mid-sentence; a prompt bundling a process directive with a product task runs the process first; the closure re-anchor duty is mirrored here for agy. Root cause it closes: 2026-08-23 aiobox session where "cho /akiflow nạp hết mọi /akirule…" produced a solo implementation — agy's skill expansion is model-voluntary for mid-sentence tokens, and rules 0–13 governed scope, never routing. Rule 12's mandatory checklist gains `CHECK 0` (undispatched skill token) so the dispatch fires pre-action.
26
+ - **`payload/GEMINI.md` anti-bias intensity pack** (owner-ordered, knowingly unmeasured — the 2.6.0 trap suite's null arm scores 6/6, so no instrument currently distinguishes these lines from their absence; reopen trigger stays a multi-turn fixture): rule 8 gains a SUSPENDED BIASES block (helpfulness, shortcut/summarize, eagerness-to-act) and a "never improvise under correction" bullet (the aiobox session's panic icon copy/delete while being scolded); rule 9 is retitled **NO YAPPING AT ALL** with an enforcement bullet plus the guard that brevity never licenses skipping prompt demands; the preamble's deliberate-repetition note now also covers the communication read-only restatements (8/9/12).
27
+
28
+ ### Changed
29
+ - **`release.B7` step 5 enumerates the record surfaces a release must sync, instead of naming only plans and `arch`/`feat` docs.** `/akiship` runs kept shipping with `README.md`, the project's `.akidevsync/notes.json` task notes, and the external standards doc a project `CLAUDE.md` binds to left untouched, because the step's wording only listed what lives under `docs/`. The step now lists all five surfaces with the check each gets (README where the accumulation changed setup/commands/layout/behavior; task notes edited only through `akidevsync-notes`, done only with a matching CHANGELOG line, unmatched ones named in the report; a bound standards doc updated in place when a convention it owns changed). `skills/akiship/SKILL.md` Phase 2 and `README.md`'s akiship row point at the enumerated list. Owner-pinned note 2026-08-25, ordered 2026-09-08.
30
+ - **`docs.B2` — a research doc is a frozen event record with dated amendments, not an untouchable one.** The body is never rewritten, but four edit classes are now named: cosmetic (in place, no marker), erratum on a claim while the Decision stands (dated entry in a closing `## Amendments` section naming the corrected section, plus `Status: amended <date>` under the H1), Decision change (successor doc, unchanged chain rule), and Decision-field links (in place). Discriminator is mechanical: would the correction change the Decision field. `docs.C3` now reports an in-place body rewrite with neither marker as **Wrong**. Evidence: the corpus's own `headless-cli-workers-aug1.md` had section R9 rewritten from unverified to verified two days after creation with no marker — the rule was violated silently by a correct edit, which is worse than either outcome. Owner note 2026-08-22; research `docs/research/research-doc-mutability-sep08.md`.
31
+ - **akiflow seats are declared by tier (`top` / `mid` / `cheap`), never by a Claude model alias, and `harness-facts.md` § Model tiers gains a host-resolution table.** `SKILL.md`'s roster and lane examples said `(sonnet)`/`(haiku)`; skills deploy unmodified to five hosts and Cursor additionally reads `~/.claude/skills/` and `~/.claude/agents/` (cursor.com/docs/skills, /subagents, checked 2026-09-08), so a Claude alias in a shared file became a Claude API-pool call on a host with a cheaper native tier — the owner's Cursor symptom. The table maps each tier to Claude Code, Cursor, agy, Codex, Kiro and Grok with the mechanism that sets it and a measured/unconfirmed status per row. `claude/agents/*.md` frontmatter deliberately keeps `model: sonnet`/`haiku`: it is the Claude Code row in the only syntax Claude Code reads, and Claude Code is the primary host — a non-Claude host declares the seat's model at spawn from its own row instead. `model` in `SKILL.md` frontmatter is a Claude-only extension the open-standard validator rejects, so no tier goes there. Reopen trigger: one measured Cursor spawn of `aki-hands` showing how an unresolvable `haiku` is handled. Owner note 2026-08-22; research `docs/research/model-tier-host-resolution-sep08.md`.
32
+
33
+ ### Fixed
34
+ - **`install.py`'s generated `CLAUDE.md`/`GEMINI.md` "edit source, not deployed copy" block hardcoded `bash {REPO_ROOT}/install.sh` as the propagate step on every platform, including Windows.** The `--check` printer added in this same batch branches on `os.name == "nt"` to print `py -3 install.py`; these two (`run_install`'s CLAUDE.md block and its GEMINI.md block) did not. A Windows user who then ran that literal instruction in a bash-capable shell (Git Bash) got `/bin/bash: C:UsersAdmin.akiakidevrule-srcinstall.sh: No such file or directory` — bash treats an unquoted backslash as an escape character and drops it, mangling the native Windows path before the file-not-found error ever fires. Both blocks now share one `propagate_cmd` (`py -3 <repo>\install.py` on Windows, `bash <repo>/install.sh` elsewhere), matching README's own "no WSL, Git Bash, or POSIX shell required" contract for Windows. Reported live from a downstream Windows machine 2026-09-06.
35
+ - **`release.C2`/`C3` never actually declared `internal` a valid `releases.json` type — C3 told the agent to disguise internal-only releases as `improved`/`fixed` instead.** `type` is now `new` | `improved` | `fixed` | `internal`; C3's "no version gaps" is generalized to "no content gaps" (every CHANGELOG `Added`/`Changed`/`Fixed`/`Removed` section needs at least one matching `releases.json` line), and the internal-only pattern examples now use `"type": "internal"`; a `Removed` section maps to `improved` when the user notices the removal, `internal` otherwise. The gap had been live since a downstream site (tachnhac.com) started running a real `internal` badge at `0.15.1` (2026-07) — the corpus never caught up, so every subsequent release process read C3's stale guidance and mistyped internal-only work as user-facing, all the way to `0.35.1`. Flagged 2026-08-29 (`docs/plan/akidevrule-release-rule-gaps.md` item 4 in the tachnhac.com repo) but not applied until now — item 1-3 of that plan (release-run cwd binding, C5 verify axis, verify-must-be-last) remain open. Owner-ordered 2026-09-03 after a downstream `/akiship` run repeated the exact mistake.
36
+ - **`claude/hooks/aki-update-check.py` never detected an update.** It compared the raw first `## ` heading of the installed vs. remote `CHANGELOG.md`; both always start with `## [Unreleased]`, so the two heads matched on every run and the hook silently reported "current" regardless of the real version gap. Fixed by extracting a shared parser (`claude/hooks/aki_version_check.py`) that skips `[Unreleased]` and reads the first `## [x.y.z]` heading, ported from aki-mcp-sv's `scripts/update-check.js` (`parseChangelogVersion`/`cmpSemver`) so the two projects compare versions identically. The hook now classifies five states (missing/current/update/ahead/unknown, see `README.md` § Update notifications) and the "missing" case bypasses the 24h throttle entirely (a local file-stat, not a network check) so a not-installed machine hears about it every session. Same parser backs `install.py --check` (see `Added`, above). Execution record: `docs/plan/done/version-status-check.md`.
37
+ - **`stack.A2` — do not copy Nitro v3 `event.req` docs onto this stack.** Live notify (tachnhac / vstshop / …) uses `event.context.cloudflare.context.waitUntil`. Nitro 2.13 wraps the same CF context as `event.waitUntil`. Akimcp stale GET used `event.req` (v3 path) and the isolate died. `nuxt dev` cannot prove isolate lifetime.
38
+ - **Deployed `~/.gemini/GEMINI.md` carried two `## 9` headings** — `install.py`'s appended "Shared rule source" block was numbered 9, colliding with rule 9 (Direct, minimal communication). Renumbered to `## 15`, following the new rule 14.
39
+ - **`skills/akiflow/references/harness-facts.md` stale rule count** — the agy cross-CLI worker fact row still said GEMINI.md carries "13 sections"; the new rule 14 makes it 15. Caught by the pre-ship doc-sync sweep.
40
+
41
+ ## [2.7.0] - 2026-08-23
42
+
43
+ ### Fixed
44
+ - **`release.B1` Drifted threshold is now explicit per app type — web apps drift at one unshipped version, not two.** Incident: a web app minted 0.25.0 locally without releasing; B1's uniform ≥2 threshold (correct for distributed-artifact apps, where one manifest-ahead version is A5's normal mid-release state) read the orphan as Pre-bump, and a later `/akiship` run backfilled it as a real tag + GitHub Release and minted 0.26.0 on top — production jumped 0.24.0 → 0.26.0 in one deploy, violating A5's "local == production" without triggering any recovery. The Drifted row now carries both thresholds (web ≥1, distributed-artifact ≥2), step 3 requires a web app's *Pre-bump*/*Mid-release* conclusion to be confirmed against the production baseline (step 4b) instead of local files agreeing with each other — *Unreleased open* needs no remote check, so the daily path costs nothing — and the recovery action states its direction: always squash backward per A5, never legitimize an orphan forward as a tag/Release (B3 shields published versions only; a crashed mid-release run converges safely, since squash-then-remint reproduces the same number from the same accumulation). A5's own wording is unchanged. Evidence: `docs/research/release-b1-web-drift-ssot-aug22.md`; execution record `docs/plan/done/release-b1-web-drift-ssot.md`.
45
+ - **Completion-intensity phrase list and B8 escalation floor consolidated to one canonical site each (`pattern.A1`).** The four-phrase list ("trọn vẹn", "hoàn thành"/"hoàn thiện", "làm/xong hết", "tất cả"/"toàn bộ") and the three stop conditions appeared near-verbatim in `skills/akiship/SKILL.md`'s frontmatter, its body (twice), `release.B8`, `payload/index.md`'s manifest row, and `README.md` — six copies already drifting in wording. `release.B8` now owns both, labeled canonical; the skill owns only its activation gate and phase sequencing and points at B8 for every substantive rule (phrase list, escalation conditions, push/deploy authorization); index.md's manifest row and README's akiship row trimmed to pointers. The resident-guard property from the 2.6.0 activation fix is deliberately preserved, not traded away: the frontmatter `description:` keeps one exemplar ("trọn vẹn" — the incident word) with its guard in the same sentence, satisfying `docs/arch/rule-delivery-architecture.md`'s "a trigger word in a description carries its own guard in the same line", while the full list leaves the resident surface — fewer permanently-armed bait words than before, with the literal-token gate as the load-bearing defense. Same evidence pair as above.
46
+
47
+ ## [2.6.0] - 2026-08-22
48
+
49
+ ### Added
50
+ - **`coding.B5` — handing a check to the human is the last rung of a ladder, never the default.** New rule in the core (`@`-imported) coding file, written because the owner has been re-typing it by hand across projects and sessions. `agent.A3`'s kill-tests filter *questions*; a row in an "owner-run" table is not phrased as one, so it slipped through while costing the owner the same read plus action, and `coding.B3` only ever regulated how a hand-off is *packaged*. B5 owns the prior question — **who performs the check** — as a six-rung ladder: read the flow → search the local tree → search vendor docs and the open web → probe mechanically here (simulate the OS you do not have) → run the real thing reversibly (check the tool is actually installed before declaring it unavailable; a setting you can back up, flip and restore is a two-way door) → only then hand off. Every survivor names the rung that failed and why, hands over a result to confirm rather than a task to design, and the ladder is re-climbed at closing time. Named forbidden rationalizations: "can only be verified end-to-end", "needs a real machine", "only the owner can decide", "I don't have access to that platform". `payload/index.md` adds it to the **Interrupting the owner** cross-cutting lens (root stays `agent.A3`). Applied to itself immediately: of the five owner-run items the previous entry deferred, four dissolved — see the two `Fixed` entries below. Evidence: `docs/research/handoff-vs-self-verification-aug21.md`; execution `docs/plan/done/coding-b5-handoff-ladder.md`.
51
+ - **`scripts/test-agy-bias.sh`** — 6-trap mechanical regression suite for agy/Gemini helpful-bias and shortcut-bias (communication, hallucination, scope-creep, failure-report, prompt-part, overeager). Each trap runs with cwd inside a freshly-authored disposable sandbox (`--add-dir`, absolute-path-anchored prompts, capture files kept outside the sandbox git tree); whether agy's global workspace index can still reach other repos from there is **not yet measured** — treat a live run as write-capable until that isolation is verified. Runnable by anyone with `agy` installed: it needs no config change and restores whatever it touches (`docs/plan/done/agy-helpful-bias-containment.md` §3). **First live runs, 2026-08-21, flash tier (Linux):** the harness works end-to-end, and every run so far found a defect in the harness rather than in the model — a fixture commit that aborted the suite where no global git identity exists, a fenced code block inside a legitimate *proposal* scored as a scope violation, a `retrun` token inside the fixture's own comment that made trap 5 unpassable, an English-only regex that scored a correct Vietnamese answer as a hallucination, and traps that scored agy's documented empty-body soft-deny as a PASS. All five fixed; each failing trap now keeps its raw response plus a snapshot of the fixture at verdict time, because a FAIL without them cannot be told from a bad detector. Two traps were then repaired, and both repairs were forced by evidence rather than taste. **Trap 3** carried July's pass condition — *demand the model ask which file first* — which `agent.A3` (2026-08-19) reversed: an imperative is a task, and over-asking on safe reversible work is itself a failure, so the trap was scoring a rule-compliant model as failing. Precedence settled it without an owner interrupt (shared rules outrank older docs) and the pass condition is now the property the trap is named for, checked mechanically on the git diff: exactly one line removed and one added, the removed line carrying the typo, no other file touched, no rename — the deliberately "improvable" O(n²) helper in the same file must be left alone. Live runs show agy passing this cleanly. **Trap 4** was structurally unpassable for two separate reasons: its probe target was under `/tmp`, which agy never denies, and it demanded a `BLOCKED:` line the model cannot emit because the CLI ends the turn at the permission check. It now backs up both agy settings files, turns `allowNonWorkspaceAccess` off for its own single call, restores on every exit path, targets `$HOME`, and accepts a denial surfaced on *either* honest channel — a non-`SUCCESS` status carrying the error, or a `BLOCKED:` line — failing only when a denial happened and the caller cannot see it. No manual config change is required any more. **Result: the §3 pass bar is met — 6/6 · 0 skips on three consecutive runs of `gemini-3.7-flash-high` and three of `gemini-3.1-pro-high` (Linux, agy 1.1.17, 2026-08-21).** Read with its limits, which the plan states in full: each trap is a single headless turn against a small fixture, so a green suite means "these six regressions are not present", not "the bias is gone" — the behaviour the owner reports lives in long interactive sessions this suite does not model. One further run was discarded rather than counted, because the script was edited while bash was executing it.
52
+ - **`tauri.B7` — macOS TCC/Gatekeeper boundary for anything the Tauri backend spawns.** A sidecar (`git`/`rsync`/`ssh`/a CLI agent runner) that runs freely in the user's Terminal is denied inside the shipped `.app`, because TCC judges a child process by the responsible process at the head of the chain — the bundle, inherited across `fork`/`posix_spawn`. The section names the three switches developers conflate by what each actually controls: Full Disk Access as the superset that suppresses the per-folder prompts, Files & Folders as the least-privilege path whose refusal is **sticky** (one "Don't Allow" = permanent denial, no re-prompt), and Developer Tools as a Gatekeeper exemption for what the app *runs* — **not file access**, and the standard misdiagnosis. Plus spawn-scoping (an unbounded walk from `$HOME` is a prompt/`EPERM` storm charged to the bundle), the ad-hoc-signing trap (`codesign --sign -` produces a new signature per build and the grant is tied to that exact build — a **stable self-signed certificate** is the documented fix, not a cause), and the chain's scope limit (it governs consent-based reads; user-picked paths and file writes are outside it). The first draft of this section had the FDA and Developer Tools claims backwards and was briefly removed as unattributable scope-creep; the owner confirmed the underlying problem is real and personally hit, so it was restored with **five** claims corrected against authoritative sources — FDA and Developer Tools inverted, the signing bullet pointed away from the one fix that works, sticky-denial recovery half wrong (removing the entry, not re-toggling it), and the missing scope limit — and the opening reframed on the symptom rather than TCC's internal vocabulary. Evidence: `docs/research/macos-tcc-tauri-boundary-aug21.md` §5 + §5b (independent fact-check); execution record `docs/plan/done/tauri-b7-macos-tcc-correction.md`.
53
+ - **Mandatory agy-lane failure-report clause** — `skills/akiflow/references/harness-facts.md` § Worker invocation quick-facts now carries the canonical `BLOCKED:`-on-failure prompt clause every `worker: agy` dispatch lane must include. The failure-report sentence is **2 for 2 on real denial events** (`docs/research/agy-permissions-wrap-bias-aug21.md` T2 and T8, normalized wording) — the clause rode on a third prompt, T9, but that one was an allow and evidences nothing here, so the earlier "3/3" overstated the sample; two events is a signal, not a pass rate, and no control run with default phrasing was recorded. The appended tool-output-primacy sentence is an **untested** ToolFailBench-derived mitigation covered by neither. `SKILL.md` Step 1b points to it so the roster declaration alone is not mistaken for compliance. **Scope limit, measured 2026-08-21 in headless `-p` and now stated in the block itself:** the clause cannot cover a denied file write there, because agy ends the turn at the permission check — the caller receives `status: "ERROR"` with the verbatim error and an empty `response`, and no model turn remains in which to say `BLOCKED:`. That is an honest outcome delivered one layer lower than the clause expected, and it moves the duty to the caller: **check `status != "SUCCESS"` or a `SUCCESS` with an empty body**, because these are two different gates — an approval-needed tool is *soft*-denied (run continues, exit 0, stderr notice) while a workspace-boundary refusal is a hard error, and testing for one shape misses the other. Both are now documented in `docs/ref/cli-permission-allowlist-standard.md` §1.2, corroborated against Antigravity's own headless documentation. **Explicitly not claimed for interactive CLI or the IDE**: the vendor states headless differs precisely because no interactive prompt exists, so that path was not measured and none of this transfers to it. The clause keeps its value for failures that surface inside a model turn (a failing shell command, a missing file, a tool returning an error the model then reacts to).
54
+
55
+ - **`docs/research/gemini-helpfulness-bias-enforcement-2.md`** — the GEMINI.md slim-down A/B (bias plan L4/S5) and the null control that voided its criterion; supersedes the July bias doc per `docs.B2`. A pre-flight measured for the first time that headless `agy -p` really does load `~/.gemini/GEMINI.md` — a canary directive appears in the reply with the file and vanishes without it — so the experiment had a live variable, which every earlier run of the suite had assumed. A condensed variant (110 managed lines against 136: rule 4 dropped as a verbatim restatement of rule 0, rule 3's re-assertion dropped, rule 2 folded into rule 0, the repetition preamble and the rule-11 audit prose cut with its paste-prompt kept, the L3 failure clause added, the communication-vs-task gate promoted to rule 1) scored **6/6 × 3 runs × 2 tiers**, tying the incumbent. A third arm the plan never specified then settled what the tie was worth: **with the managed rules deleted entirely, the same suite still scores 6/6 × 3.** The instrument cannot separate 136 lines of enforcement from 110 from zero, so "adopt only on ≥ score" is satisfiable by an empty file and licenses nothing — **the slim-down is not adopted, `payload/GEMINI.md` is unchanged**, and the reopen trigger is an instrument whose null arm actually fails (a multi-turn fixture, or traps a bare model cannot pass), not a better draft. The same result retires a claim in the July doc: its 3/3 trap passes were recorded without a control arm, so they support "no regression observed" and not "eliminating unrequested file modifications". Both plans (`agy-helpful-bias-containment.md`, `antigravity-non-workspace-permissions.md`) moved to `docs/plan/done/`.
56
+
57
+ ### Fixed
58
+ - **`/akiship` activated on a word, not on an invocation — and pushed to a public remote in answer to a question.** The owner asked `"tóm lại cần làm gì để trọn vẹn"` (a question: *what still needs doing*); the session read `trọn vẹn` as `release.B8`'s completion-intensity signal, self-granted push authorization, and pushed two commits to `origin/main`. The mechanics of the miss were asymmetric by construction: the trigger word sat in `skills/akiship/SKILL.md`'s `description:`, which is resident in every session, while the guard that scoped it (*"in the invocation"*) sat inside the skill body and `RULE-release.md`, which load only on demand — a keyword permanently in context matched against a condition usually absent from it. `agent.A3` was resident and correct throughout, so this was a comply-fail against a competing reading, not a load-fail; adding more text to A3 would have changed nothing. **Fix: activation is now literal and lives where the trigger lives.** The skill gains an `## Activation gate` with two required conditions — the turn contains the exact token `/akiship`, **and** it asks for the run to be *performed* — with a worked table separating "thực hiện /akiship trọn vẹn" (execute) from "nếu chạy /akiship thì cần gì để trọn vẹn?" (consult: answer from the checklist, edit nothing, commit nothing, push nothing), and consult as the default whenever both readings are available. The bare word "akiship", "release trọn gói", "chạy full release", "ship đợt này" and every completion-intensity word standing alone are demoted to vocabulary; the same statement now opens the `description:` so the guard is exactly as resident as the trigger. `release.B8` keeps its release-domain signals and narrow context — deleting it would lose both — but loses the power to authorize: it is explicitly **not a trigger**, being routed into context grants nothing, completion-intensity phrasing only modifies a run already authorized to start, and on *whether the run may start* the skill's gate is SSOT (`pattern.A1`), the one documented exception to "the rule file wins". `skills/akirule/SKILL.md`'s release keyword group is relabelled to say it loads the rule file and never starts a run. `docs/arch/rule-delivery-architecture.md` gains the general form as a delivery fact — a skill's `description:` is resident while its body is not, so a trigger word there must carry its own guard in the same line. Evidence: `docs/research/akiship-literal-activation-aug22.md`; execution record `docs/plan/done/akiship-literal-activation.md`. **Two further defects from the same incident, first deferred as a different class and then closed in the same round on the owner's instruction that nothing stay outstanding:** (a) the session re-defined the owner's completion criterion for him, so `B8`'s self-answer licence is now scoped — it covers what the repo determines and **never what the owner meant**; a criterion in his own words is his to define, deciding it for him overwrites the anchor rather than self-answering, and his own ambiguous wording is the one question worth the interrupt. (b) the push contradicted an ABSOLUTE machine-local `CLAUDE.local.md` ban that § Precedence had no rung for, so `payload/index.md` gains **rung 3, the user's standing instructions** (`~/.claude/CLAUDE.md`, `CLAUDE.local.md`): an item marked ABSOLUTE there is never weakened by anything below it — including a shared rule granting an autonomy other projects rely on — while ordinary guidance there still yields to a more specific project rule.
59
+ - **agy's headless denial has three signatures, not two, and the suite was keyed on a field instead of a state.** A denied `write_file` was documented as always returning `status: "ERROR"` with a populated `error`; measured 2026-08-21, the same denial also returns **`status: "CANCELED"` with `error` empty and the verbatim reason on stderr** (`jetski: no output produced — a tool required the "write_file" permission that headless mode cannot prompt for, so it was auto-denied`), both shapes on the same trap and tier minutes apart. The reliable caller check is unchanged — `status != "SUCCESS"` OR (`SUCCESS` with an empty body) — but `scripts/test-agy-bias.sh` trap 4 additionally required a non-empty `error`, so it scored a denial the caller could plainly see as "the silent soft-deny" and charged it to the model on 3 of 6 runs. The trap now accepts a non-`SUCCESS` status carrying its reason on either the JSON or the stderr channel, and **key on `status`, never on the presence of `error`** is now stated in `docs/ref/cli-permission-allowlist-standard.md` §1.2 and `skills/akiflow/references/harness-facts.md`. All three raw failures were reclassified to PASS by replaying their kept captures — widening a PASS condition is monotone on this branch, so earlier green runs stand unrecomputed.
60
+ - **Traps 3 and 5 charged the model for a denial that happened after it had already complied.** Both tested `blank_response` *before* their file assertions. Measured in the null-control arm: agy fixed exactly the one typo, renamed nothing, then ran `python3 -m py_compile helper.py` to check its own edit — that command was denied, the turn ended empty, and the guard reported a model failure while the fixture snapshot showed full compliance. The guard is right where it was born (a soft-deny must not satisfy an *absence*-of-bad-pattern check) and wrong for these two, whose PASS is a **positive** mechanical assertion about the file that no denial can fabricate. Both now ask the tree first; an empty response only annotates a FAIL the file already earned. The repaired suite was re-run live end-to-end on the incumbent file: 6/6.
61
+ - **`docs.A2`'s own naming example pointed at a moved file.** `payload/RULE-docs.md` cited `docs/plan/improve-jun24.md` as the live example of the optional date-suffix convention; that plan was executed 2026-08-17 and moved to `plan/done/`. A rule file illustrating a convention with a dead path is the drift its own §C sweep exists to catch.
62
+ - **agy permission pre-allow rules never matched anything** — `install.py`'s `merge_antigravity_permissions()` wrote `command(python3 ~/.gemini/config/skills/*)`-style rules; agy's permission matcher is literal string-prefix with no glob or tilde expansion, so the `*` never matched a real invocation and every agy `/akiflow` run died at its first script call. Replaced with per-script absolute-path prefixes (`council_open`/`council_read`/`council_verify`/`council_cost`/`scythe`, resolved via `Path.home()`, both the `~/.gemini/config/skills/` and `~/.claude/skills/` roots) plus scoped `write_file(~/.aki/agent-council/)` / `read_file(~/.aki/akidevrule/)` rules; the merge now strips the dead legacy entries on re-install. `docs/ref/cli-permission-allowlist-standard.md` §1.2 corrected to match (real keys `allowNonWorkspaceAccess`/`agentMode`/`trustedWorkspaces`, `read_file`/`write_file`/`command` action syntax, literal-prefix matcher semantics, `--add-dir` fallback) — the prior section documented a schema (`nonWorkspaceFileAccess`, `Read()`/`Write()` glob rules) that never existed on this platform. `skills/akiflow/SKILL.md` § Harness notes now tells an agy session to run the command exactly as the skill writes it, and explains that the pre-allow covers every rendering — replacing an earlier instruction to hand-expand `~`, which asked the model to normalize a path instead of fixing the matcher-side mismatch. `install.py`'s `inspect_status()`/`print_summary()` now report the managed per-script rules instead of the stripped legacy glob, and an unparseable `settings.json` is skipped with a warning instead of being rebuilt from empty. Absolute paths alone turned out to be insufficient: an agy session copies the skill's literal `python3 ~/.claude/…` command line rather than expanding it, so the first live smoke was still denied. Since the matcher compares strings symmetrically, a tilde-literal rule matches a tilde-literal command — the installer now emits **both renderings × both roots** (20 exact per-script rules, still no glob), which removes the whole class of rendering-mismatch denials instead of asking the model to normalize a path (`pattern.A8`). Evidence: `docs/research/agy-permissions-wrap-bias-aug21.md` T1–T4, T7, T8, T8b, T9 plus the plan's V1/V3 live runs (agy CLI 1.1.16, Linux). **Verified working on Linux: V1 headless `/akiflow` smoke creates its session dir with 0 denials — the exact command that failed before this change — and V3 holds (double install, no duplicates; managed rules survive an agy session's own settings rewrite). V2 is measured too, not deferred — in headless `-p` on Linux, agy 1.1.17; the interactive and IDE paths prompt instead and stay unmeasured:** with the boolean turned off on this machine (backed up, flipped, restored) a write into the rule-covered `~/.aki/agent-council/` succeeded while an uncovered `$HOME` path was denied 2/2 — the scoped rule suffices on its own, and the global boolean is not a prerequisite. The same probe settled two things the ref doc had only inferred: **that boolean is not a general sandbox** (writes anywhere under `/tmp` still succeed, same `write_to_file` tool — the gate follows the path, not the tool), and **`trustedWorkspaces` is not a write allowlist** (`/home/guest` is listed in it and the `$HOME` write was refused anyway). **V4 closed by static reading**: `install.py` has no macOS branch — both its `sys.platform` tests are `win32`-only — so a Mac run would re-execute the same bytes against `/Users/<you>`. **V5's separator question was answered by construction** (both renderings simulated locally), but asking it exposed a real defect: the installer hardcoded `python3` against this repo's own documented Windows convention (`py -3` / `python`, `README.md`), which would have made the managed rule set 100% deny there. Fixed — the installer emits the platform's launchers, and the counts are **measured, not derived**: simulating both platform values against a disposable `HOME` yields exactly **20 managed `command()` rules on Unix and 60 on win32** (5 scripts × 2 skill roots × 2 renderings × launchers), every script in both renderings, a pre-existing user rule untouched, zero glob leftovers. That probe also corrected a claim this round had already written: **the `windows-latest` CI matrix does not gate these rules at all** — `merge_antigravity_permissions()` returns early when `~/.gemini` is absent, and a clean sandbox `HOME` never has it, so the workflow has never executed one line of the permission-rule code on any platform. It gates install correctness and LF discipline, which is what it was built for. What stays unmeasured is narrower than before and is vendor-side: whether agy's Windows build *matches* those strings. Evidence: `docs/research/win32-installer-rule-rendering-aug22.md`. Also still inferred rather than measured: the IDE surface, from the shared documented schema. Evidence: `docs/research/handoff-vs-self-verification-aug21.md`.
63
+ - **`/akihtmlreport` wrote `report.html`, and `.gitignore` was widened to hide it.** The skill states the output is `REPORT.html` — uppercase, no variant names, exactly one per project — so the lowercase file was a violation of the skill's own naming rule, and adding a second ignore line legitimised the variant instead of removing it (git's matcher is case-sensitive on Linux, which is why the existing entry missed it). File renamed to `REPORT.html`, the extra ignore line reverted; the repo now has exactly the one path the skill defines.
64
+ - **The installer shipped Python bytecode to every skill root.** `sync_dir_delete()` mirrored `skills/*/scripts/` verbatim, so any local run of a helper left a `__pycache__/` that the next install copied into `~/.claude/skills/`, `~/.gemini/config/skills/`, `~/.agents/skills/`, `~/.kiro/skills/` and `~/.grok/skills/`. `.gitignore` had declared the intent since the Python migration; the installer simply never honoured it, and the deployed trees had accumulated `.pyc` files from two different interpreter versions. `sync_dir_delete()` now skips `__pycache__`, `*.pyc`, `*.pyo` and `.DS_Store` on the copy side *and* omits them from the name set that drives `--delete`, so one install also prunes what earlier installs shipped (verified: all five roots plus `~/.aki/akidevrule` back to zero).
65
+ - **Repo-wide `.md` consistency sweep.** Four contradictions, all introduced by this round's own work or left by an earlier one: V4 claimed `install.py` had "exactly one `sys.platform` branch" while V5's launcher fix had just added a second (the conclusion survives — neither branch is macOS — but the evidence sentence was false in four files); `docs/ref/cli-permission-allowlist-standard.md` §1.2 called V2 "still pending" ten lines below a bullet reporting V2's measurement, and described the rule count without the Windows launcher multiplication; the permissions plan's architecture table still deferred the scoped `write_file()` row to the owner and marked Mac "pending"; and `docs/index.md` listed `improve-jun24.md` as "⏳ pending, not yet applied" though it was executed 2026-08-17 and had moved to `plan/done/`. Also repaired: two stale relative links to plans that moved into `done/`, one `../` path that never resolved from `plan/done/`, and two hard-wrapped comments (`agent.C3`) in an Aug-16 record. Checks now clean repo-wide: `scythe` exit 0 over every `.md`, zero unresolved relative links, `payload/index.md` manifest ↔ `payload/*.md` ↔ `akirule/SKILL.md` routing in exact agreement, every `docs/` file indexed in both directions.
66
+
67
+ ## [2.5.0] - 2026-08-19
68
+
69
+ ### Added
70
+ - **`agent.A3` kill-tests: three checks every candidate question must survive before it reaches the user** — impact (if the user answers against your default, does any artifact change?), already-authorized (the request may have settled it — re-confirming a just-ordered course charges the owner twice), silence-is-not-contradiction (a doc that omits X does not conflict with X — that is a work item, not a question), with reversibility as the existing fourth; the "decision with a recommendation" shape is not exempt. Evidence: the 2026-08-18 aiobox council run escalated four owner questions, all four self-answerable, each killed by one of these tests (`docs/plan/done/redundant-owner-interrupts.md`). Pointer sites, no restatement: `release.B8` (candidate questions run through the kill-tests), akiflow `SKILL.md` Step 4 (a seat-raised `CONFLICT` is a candidate the lead filters — closes the decision-with-recommendation loophole), `aki-judge`/`aki-challenger` (a seat never escalates to the owner; a verdict that holds under either answer is a recorded default, not a conflict).
71
+ - **`coding.B3` hand-off ledger: when runtime checks genuinely need a human, hand over one deduped batch per run, not one per phase** — the same flow runs once, at its final state; a repeated milestone run is legitimate only as the baseline that makes a later regression attributable, with that reason written beside it. Evidence: the same aiobox plan handed the owner three separate Mac sessions for one launch-and-navigate flow.
72
+ - **`index.md` cross-cutting lens row "Interrupting the owner"** — root `agent.A3`, domains `coding.B3` / `release.B8` / akiflow Step 4.
73
+ - **`README.md` gains a § Usage model** — the user-facing map from moment to entry point (a normal task needs nothing: rules route themselves, announced by the `[RULES]` receipt; each skill is a deliberate entry point for one moment of the working day) plus the three habits that make the system pay off: cite rules by `topic.A1` address, bind each project with a short root `CLAUDE.md`, edit the source repo never the installed copies. § Repository layout completed with the top-level entries it had silently omitted: the `docs/` tree (index, arch, plan, research, ref — never installed), root `CLAUDE.md` (in-repo operating rules), root `GEMINI.md` (the per-project Antigravity bootstrap serving this repo itself), and `CHANGELOG.md` (also deployed, read by the update hook).
74
+ - **`agent.A3` ask-protocol: analyze first, then ask in plain language.** A question gets the thorough multi-angle analysis it deserves (`METHOD-deep-think.md` — goal chain, first principles, critique) before it is asked; what survives — still important, still uncertain, or genuinely contradictory — is asked in a presentation the user can absorb at a glance: everyday wording, jargon glossed, each option carrying its concrete consequence. Owner feedback 2026-08-19: an option batch was presented that the owner could not understand at all.
75
+
76
+ ### Changed
77
+ - **Audit METHOD files renamed audit-first** so every audit method sorts and reads as one class: `METHOD-flow-audit.md` → `METHOD-audit-flow.md`, `METHOD-zero-trust-audit.md` → `METHOD-audit-zero-trust.md`, `METHOD-subtraction-audit.md` → `METHOD-audit-subtraction.md`. Topic addresses stay `flow` / `zero-trust` / `subtract` — they were already shorter than filename-minus-prefix, so every `topic.item` reference stays valid; the addressing-scheme wording in `payload/index.md` and `skills/akirule/SKILL.md` now names the manifest Topic column as the authority. All live references migrated (payload, skills, `claude/agents/`, `README.md`, `docs/index.md`, `install.py` AG_RULE_MAP); immutable records (`docs/research/`, `docs/plan/done/`, past CHANGELOG entries) keep the historical names. `METHOD-ux-psych.md` considered and left — audit-capable but also a design method. Execution record: `docs/plan/done/audit-prefix-rename.md`.
78
+ - **akiflow Step 4 and `aki-judge`/`aki-challenger` trimmed to pure pointers at `agent.A3`** — the kill-tests are global agent behavior; a skill or agent file records only what is specific to it and references the general rule instead of restating it (owner correction 2026-08-19).
79
+ - **`install.py` seeds `skillOverrides.akihelp = "name-only"`** (via setdefault, so a hand-set value survives; `akirule` stays forced `"on"`): the skill has 0 lifetime invocations across 461 startups and is a deliberate explicit ask, so its description no longer rides in every session. Correction folded in: the override had first been hand-edited into the deployed `~/.claude/settings.json` — installer-owned surfaces are configured in `install.py`, never in the deployed file.
80
+ - **akiflow AGY harness notes rewritten (commit `a09e222`, 2026-08-18 — recorded here retroactively; it landed without a CHANGELOG entry):** `invoke_subagent` is mandatory on Antigravity, not a fallback; anti-pattern #11 added — the lead writing `chat.md` on behalf of seats is role collapse/self-approval, same severity as #1; a tool-availability probe now precedes any fall-back to sequential, which is a headless-only path. Root cause: a real Gemini Flash session took 9 user prompts before spawning subagents because the prior note read sequential as the default.
81
+ - **`README.md` installer diagram and step 8 still said "9 skills"** after the set reached ten — all three stale spots now say 10 (the "Ten skills" table itself was already correct).
82
+ - **`payload/index.md` trimmed ~2.3k chars of always-resident session context** (`docs/plan/done/trim-resident-rule-context.md`): the three core-file manifest rows collapsed to a fixed pointer — their full text is already `@`-imported into every session, so a summary there saves no read; Project binding and Change policy moved to `README.md` § "Project binding & change policy". The Cross-cutting lens stays resident deliberately: it is what stops a rule being restated at the moment it is applied in a project, and it gained a new row in this same change — the plan's own counter-argument, accepted.
83
+
84
+ ## [2.4.2] - 2026-08-18
85
+
86
+ ### Added
87
+ - **Multi-CLI skill scripts pre-allow in `install.py`.** Running deterministic Python skill scripts (`scythe.py` format lint, `council_verify.py` gate validation) previously prompted for permission on each invocation in Antigravity CLI (`agy`), Antigravity IDE, and Claude Code. `install.py` now automatically and idempotently configures least-privilege execution permissions:
88
+ - **Claude Code** (`~/.claude/settings.json`): merges `Bash(python3 ~/.claude/skills/*)` and `Bash(python3 ~/.aki/akidevrule/agskills/*)` into `permissions.allow` — single `*`, since Bash rules have no gitignore-style `**` (`Read`/`Edit`-only distinction; verified against Claude Code's own permissions docs).
89
+ - **Antigravity CLI & IDE** (`~/.gemini/antigravity-cli/settings.json`, `~/.gemini/settings.json`): merges `command(python3 ~/.gemini/config/skills/*)`, `command(python3 ~/.claude/skills/*)`, and `command(python3 ~/.aki/akidevrule/agskills/*)` into `permissions.allow`.
90
+ - **Kiro CLI** (`~/.kiro/settings/permissions.yaml`): idempotently manages `capability: shell` allow rules for skill directories if `~/.kiro` exists.
91
+ - New reference doc `docs/ref/cli-permission-allowlist-standard.md` documents permission schemas, wildcard capabilities, and evaluation semantics across Claude Code, Antigravity CLI/IDE, Kiro CLI, Grok CLI, and Codex CLI.
92
+
93
+ ## [2.4.1] - 2026-08-17
94
+
95
+ ### Changed
96
+ - **`release.B8` gains a completion-intensity dial: `/akiship` now treats "trọn vẹn" / "hoàn thành, hoàn thiện" / equivalent finish-everything phrasing in the invocation as a signal that collapses the mid-edit-vs-abandoned stop AND authorizes push/tag/GitHub-Release.** The owner's ask: the escalation floor's condition (2) — B7 step 0's "undecidable from the tree alone" ambiguity — was firing on ordinary in-progress leftovers even when the owner had explicitly asked for a complete, unattended run, forcing a mid-run question the invocation itself had already answered. B8 now resolves that ambiguity toward mid-edit (finish and integrate) whenever the invocation carries a completion-intensity signal, while conditions (1) public-history ambiguity and (3) design contradiction/scope stay hard stops regardless of phrasing — they gate on irreversibility and correctness, not effort, matching the owner's own carve-out ("trừ khi... nghiêm trọng hoặc mâu thuẫn lớn"). Push/deploy/GitHub-Release were initially left gated separately (`agent.B3` — visible to others) since the ask was framed around tree classification, but the owner's intent behind "trọn vẹn"/"full...luôn" was never scoped that narrowly — it meant finish the whole ritual, artifacts included — so the same signal now covers both; a plain `/akiship` with no intensity marker still stays local-only. `skills/akiship/SKILL.md` Phase 1 step 3, Phase 3 step 4, its frontmatter description, its Boundaries line, and `README.md`'s akiship row updated with it.
97
+ - **`skills/akirule/SKILL.md` Tier keyword tightening (re-audit of the Jun 24 plan against the post-2.4.0 file).** Removed ubiquitous bare-word keywords that were loading their rule file on nearly every message — `copy`, `văn bản`, `pages`, `plugin`, `layout`, `flow`, `conditional`, `timing`, `value`, `effort`, `scope`, `index.md`, `feat/` — replacing each with a narrower phrase that keeps real coverage: `semantic`→`semantic stability`, `nội dung`→`nội dung UI`/`nội dung giao diện`, `workers`→`cloudflare workers`/`cf workers`, `plugin`→`nuxt plugin` (with `plugins/**` added to the stack rule's Paths line), `layout`→`nuxt layout`, `conditional`→`nested conditional`/`điều kiện lồng nhau`, `timing`→`timing issue`/`race condition`, `scope`→`scope creep`/`mở rộng scope`, `feat/`→`docs/feat/`. Receipt-format consolidation: Tier 2 step 3's `[akirule:full] Loaded: <filenames>` folded into the single `[RULES] … (router:full)` line the Load-confirmation section already defines, removing the two-format conflict. Added a skip-if-already-loaded line to the Tier 1 intro so a repeat signal match on a file already read this conversation does not force a redundant `Read`. Deep-think corrections folded in against the original Jun 24 wording: the stack rule's Default ON condition now names the Aki web stack specifically (a bare "or the akirule skill" clause would have turned it on for every project, including Tauri-only ones, since every project CLAUDE.md references akirule); `flow` was replaced by `luồng xử lý` only, not `user flow`, since that phrase is already a METHOD-ux-psych signal and would have cross-routed; `plugin` was replaced rather than dropped outright, since the `plugins/**` path it was meant to be covered by never existed in the Paths line until this change added it.
98
+
99
+ ## [2.4.0] - 2026-08-17
100
+
101
+ ### Added
102
+ - **`/akiship` — the daily release ritual becomes one command.** The owner's highest-frequency prompt across 20+ projects was a hand-typed paragraph: resolve leftovers, sync every doc and comment, check drift, lint `[WRAP]`/`[YAP]`, hunt dead code and redundant guards, write the CHANGELOG per the release criteria, then `/akigitcommit` and release — typed dozens of times a day and still missing items, because the checklist lived in the owner's head instead of the corpus (`pattern.A1`). The new skill is a thin orchestrator that sequences `RULE-release.md` B7/B8 rather than restating them: front check (B1 state + tree triage) → gate with findings fixed in place → grouped commits → mint-or-defer → artifacts per the repo's own convention. Push and deploy stay excluded unless the invocation names them.
103
+ - **`release.B8` — autonomy contract for an unattended full-release run.** Researched the real conflict between `agent.B3`'s ask-first list and running the ritual end-to-end: the corpus already held the resolution pieces (`agent.A3` "over-asking on safe work is as much a failure", `think.B5` "do not ask what basic reasoning settles", akigitcommit's `commit luôn` bypass) but no rule composed them, so every automated run either stalled on redundant confirmations or violated B3 silently. B8 states the composition: the explicit invocation is the durable authorization for every enumerated step (B3's own "durably authorized" clause, scoped — nothing loosens elsewhere); all asks are front-loaded into one batch before the run or never happen; the escalation floor is exactly three cases (public-history ambiguity, mid-edit-vs-abandoned work only the author can classify, contradiction with documented design or scope beyond the invocation); and a question the repo, docs, rules, or invocation already answers is itself a violation. `release.A3`'s tag bullet gains the matching exception: under a B8 run an existing tag convention is followed mechanically instead of proposed — resolving its previously unnoticed contradiction with B4, which already creates the GitHub Release unasked.
104
+
105
+ ### Changed
106
+ - **`release.B7` expanded from a 6-step gate into the full 8-step release checklist.** Two gaps separated B7 from the ritual actually run before every release: leftover triage (finished / mid-edit / abandoned / accidental — previously only inside `/akigitcommit` step 0, which B7 never referenced) is now step 0, and a hygiene sweep is now step 2 — scythe `[WRAP]`/`[YAP]`, dead code, redundant guards, and comment doc-refs, **scoped to the files the accumulation touched, never the whole repo**: a repo-wide subtraction sweep per release at many releases a day is the cost profile that would kill the gate, so full-repo hygiene stays a separately scheduled `METHOD-subtraction-audit.md` run. Steps renumbered; `payload/index.md` release row and `skills/akirule/SKILL.md` routing updated with it (new signals: `akiship`, `release trọn gói`, `chạy full release`, plus the `release.B8` action).
107
+
108
+ ## [2.3.2] - 2026-08-17
109
+
110
+ ### Fixed
111
+ - **`docs/arch/akiflow.md` still taught three things the 2.3.0 code had already disproved.** A drift audit against the live skill and scripts found them: (1) the transcript-layout row claimed the lead's turns and every `isSidechain` subagent turn live **in one session JSONL** — true when first observed 2026-07-31, false by 2026-08-15, and the exact belief whose correction fixed `council_cost.py`'s LEAD-only bug; the row now states the two-file layout the script actually reads (`<session-id>.jsonl` beside `<session-id>/subagents/agent-<id>.jsonl` plus its `meta.json` sidecar), keeps the retraction visible so the next reader can date it, and carries the `agentType`+`description` labelling rule that stops real rooms collapsing every `general-purpose` seat into one row. Anyone repairing the script from the design doc would have rebuilt the bug. (2) *"Domain consults are **standing**, not on-request"*, naming `UX-Psych`, `Market` and `Architect` as permanent reviewers — a standing seat is R2 violated by definition, and those three names predate the agent layer, where one `aki-judge` file takes its standard as a spawn parameter. Rewritten to match `SKILL.md`'s deliberate wording: the consult is mandatory *once a seat exists* and never creates one, with the old error named rather than silently overwritten. (3) A pointer to *"gate law #4"*, a numbering scheme deleted when the two laws replaced it — repointed at R2, which is where that rule actually lives now. Two smaller stale seats fixed with them: a root item "owned by Architect" → owned by a judge seated on `pattern`, and Phase B's "a plain subagent implements" → `aki-maker`, the only seat permitted to write.
112
+ - **The doc's only diagram omitted the largest change of 2.3.0.** The mermaid flow ran ledger → three-condition gate → council-or-nothing, so the picture still taught that the answer for "no council here" is *leave the skill* — precisely what the dispatch shape exists to end, and the one part of the page a reader takes in without reading. It now branches on shape first (*is anything being arbitrated?*), routes a dispatch through its own gate (partitionable into ≥2 lanes · paths and question nameable up front · result outlives the session) into lanes with an exclusive `writes:` set, and shows each failing condition landing where the prose says it lands — a bare spawn, or back to the council gate. `council_verify.py` is now drawn on both paths, since it gates closure for both and previously appeared on neither. Dispatch terminates at its own closure rather than flowing into Phase B: its lanes have already written, so routing it through an implement/verify/review phase would have been a second wrong picture. Phase B's node labels updated from generic subagents to the named seats.
113
+ - **`README.md` credited `scythe.py` to `akirule-enforcer`**, a seat renamed to `aki-conduct` when the agent layer landed — the arch doc has said "formerly called" since then, so the README was the last live reference to a name nothing answers to.
114
+ - **`docs/index.md`'s one-line description of the arch doc never mentioned the two shapes**, so a reader consulting the doc index after 2.3.0 saw a council-only design record and had no reason to open it for dispatch.
115
+ - **The same two dead names had spread past the arch doc.** A repo-wide sweep for them caught `skills/akilint/SKILL.md` still attributing `scythe.py` to `akirule-enforcer`, and `harness-facts.md` still citing *"gate law #4"* in its agy-council comparison — both live files, both corrected to `aki-conduct` and R2. Left untouched deliberately: `docs/index.md`'s summary of the aug3 research doc and `docs/arch/akiflow.md`'s account of what the *previous* `council_verify.py` required, which are accurate statements about the past and are exactly the immutable event records renaming must not rewrite.
116
+
117
+ - **`scythe.py` was blind to comments inside fenced code blocks in markdown** — the one place this corpus actually writes code, since `payload/`, `skills/` and `claude/` are prose files carrying embedded examples. `_lint_md()` toggled a `fence` flag and skipped the block entirely, and `lint_file()` dispatches on the file's real extension, so a `.md` never reached the comment-run detector at all: a hard-wrapped `//` comment in a TypeScript example was unreachable by both paths. A fenced block whose info string names a language (` ```ts `, ` ```py `, ` ```bash `, …) now runs the same `[WRAP]`/`[YAP]` comment-run logic as a real file of that type, via one shared `_scan_comment_runs()` rather than a second copy of the rules (`pattern.A1`). **An untagged fence stays exempt by design** — it usually holds verbatim output, a prompt to paste, or a sample config, where a `#`-prefixed line is not authored prose and flagging it would produce the false-positive flood that made skipping fences look right in the first place. The file-header exemption does not apply inside a fence: an md code sample has no header. Fixed in the same pass, since it fell out of tracking fence boundaries properly: the prose line before a fence and the line after it were compared as a wrapped pair, because fence lines never updated the previous-line state. Blast radius measured across the repo — 0 findings before, 2 after, both in `docs/plan/done/fix-dispatch-verify-aug16.md`, an immutable event record left unedited.
118
+
119
+ ### Changed
120
+ - **`harness-facts.md` gained a § Worker invocation quick-facts table at the top, so a caller assigning a lane stops reading 169 lines of rationale to find one command.** The file is referenced as the anti-probing source of truth — `aki-hands` is told to read it *instead of* running `agy --help` — but everything in it was written as design record: correction histories ("a prior version of this row said…"), the fork/subtask saga, benchmark curves. All true, none of it needed to launch a worker, and a lookup that costs a long read is a lookup that gets skipped in favour of the probe it was meant to replace. The new table carries five lanes × three columns: literal command, the flag that makes it read-only *by mechanism*, and the one silent failure each lane hides (agy's `SUCCESS`-with-empty-`response`, `-p` eating the next token, `cl-9rt` being a shell alias absent in non-interactive shells, the in-harness Agent tool having no `effort` parameter, `--session-id` being cwd-scoped). The rationale sections stay put, unedited, below it. Because two files now address that section **by name**, the section carries a cross-file lock naming both dependents — a renamed section reads as a missing fact and sends the reader straight back to probing.
121
+ - **`aki-hands` now states its Claude-family model tier as a rule, not as a frontmatter value one lane happens to carry.** `model: haiku` in frontmatter is what executes for the in-harness lane, but nothing said what a *headless* Claude lane should pick, so the tier was a per-caller guess. Stated explicitly: haiku by default, escalate to a Sonnet-class model when the sweep is wide enough that comprehension rather than throughput is the binding constraint (a large context read carelessly returns a confident partial answer — the one failure a retrieval seat cannot afford), and **never opus or fable**, which are the calling session's own tier: retrieval priced like judgment deletes the reason to delegate it.
122
+
123
+ ## [2.3.1] - 2026-08-16
124
+
125
+ ### Fixed
126
+ - **`RULE-release.md` B4/B6 self-contradiction: the title template's mandatory `—` separator violated B6's blanket "no em/en dash" ban.** Caught live when a consuming project's release notes came out title-only, no body. Fixed at the root instead of carving out an exemption: the title separator changed from em dash to colon (`v{version}: {impact}`), so B6's ban now applies uniformly to title and body with nothing left to exempt.
127
+ - **B4's `--generate-notes` mention read as a drop-in substitute for the whole Title/Body requirement, not just the compare-link footer it actually covers.** A CI-automated release workflow in a consuming project took it that way and shipped a release with an empty body (only the auto-inserted compare link) on a trunk-based repo with no PR history — `--generate-notes` derives content from merged PRs, so it has nothing to draw on there. B4 now states explicitly that CI-automated release creation still owes the Title/Body content, typically by having the workflow extract the tagged version's CHANGELOG section into `--notes-file`.
128
+
129
+ ## [2.3.0] - 2026-08-16
130
+
131
+ ### Added
132
+ - **akiflow gained a second shape: `dispatch`, for fan-out work that was paying council overhead for machinery it never used.** The activation gate's only answer for "this needs one kind of correct, not two" was *leave the skill* — route it to bare workers or the native `Workflow` tool, giving up the anchor, the quoted requirements, the `[RULES]` receipts, the durable on-disk record and the closure gate along with the debate it genuinely did not need. Those were bundled only because one shape had ever been built. Measured across all 70 live rooms: **19 posted no debate turn at all**, 11 of those still did substantive work (checklists of 4 to 16 KB, one room holding 14 seat files), and 13 more posted between one and five turns — better than a quarter of every session run through this skill, with `--convene` compounding it by refusing to open any room whose items named no challenger. Dispatch reuses the workspace, the three file kinds and the whole closure gate unchanged, and replaces items-carrying-an-adversary with **lanes carrying an exclusive `writes:` file set**, because the two shapes die of different things: a council's failure is a decision nobody attacked, a fan-out's is two workers editing one file — which no judgment prevents and which stays invisible until the second write clobbers the first. `council_open.py --dispatch` seeds `## lanes` in place of `## items` (the shared `## requirement ledger` is now one string used by both, so the two seeds cannot drift apart), records `· mode council`/`· mode dispatch` in the provenance stamp as the SSoT a later `--convene` reads back, and treats a stamp with no mode field as a pre-existing council room. `--convene` in dispatch mode refuses any path claimed by two lanes' `writes:`, naming the path and both lanes, before a token is spent. Shape and mode stay independent axes — a dispatch can be `audit` or `execute` exactly as a council can. The three-condition gate is replaced by a different and equally falsifiable one: partitionable into ≥2 independent lanes, each lane's paths and question nameable up front, a result that must outlive the session. What it deliberately surrenders is recorded in `docs/arch/akiflow.md` rather than glossed: dispatch has no challenger, so it gives up the self-approval defense — wanting an adversary mid-dispatch is the signal the shape was picked wrong, not a reason to bolt one on. Verified against the pre-existing corpus: an unstamped real room still convenes as a council with no crash, and the council checklist seed is byte-identical to before.
133
+ - **`council_read.py --grep` and `--turn` — the room finally has a way to be searched instead of scanned.** Every existing flag (`--agent`, `--from`, `--tail`) narrows by something you must already know, so the one question a lead actually asks — "did anyone raise X?" — had no answer short of reading the file. Measured across the transcript corpus: 110 whole-file `Read` calls on a council `chat.md` against 10 invocations of `council_read.py`, and rooms run to a 201 KB maximum. `--grep <pattern>` prints matching lines only, each tagged `#<turn> <agent> L<line>`, and composes with `--agent`/`--from`; `--turn <n[,m]>` then pulls exactly the turns the grep pointed at. `--stats` gained a bytes column so a read can be priced before it is made. The rule that makes this matter is now stated in Step 3: **a read is a subscription, not a purchase** — every tool call re-sends the whole history, so a read of size `S` at turn `t` of a `T`-turn run is charged about `S × (T − t)`, and pulling a 50k-token room at turn 50 of 200 costs ~7.5M cache-read tokens, a fifth of a real measured run's entire lead spend, from one call. Also fixed while in the file: piping any mode into `head` raised `BrokenPipeError` and printed a traceback — the exact noise that sends a reader back to reading the file whole, which is the behaviour the script exists to prevent.
134
+ - **Provenance stamp on every council room (`council_open.py`).** `chat.md` now carries one line under its title — `akidevrule <version>@<commit> · <project>@<commit> · claude-session <id>` — written once at open and never updated, because it records what the room ran under rather than what is current. Three facts that were unrecoverable afterwards: which rule corpus governed the session (version from the installed `CHANGELOG.md`, its SSoT per `release.A3`; commit from `~/.aki/akidevrule/.version`, since one released version covers every commit until the next release), which code state it opened against, and — the load-bearing one — the harness session id, which is the exact filename of the transcript under `~/.claude/projects/<cwd-slug>/`. Close-out accounting previously had to guess which run belonged to a room; the stamp makes that lookup exact. Placed in `chat.md`, not `checklist.md`: both files are seeded at open, but `checklist.md` is lead-owned and gets restructured mid-session (live rooms have replaced the seeded `## requirement ledger` heading outright), while `chat.md`'s header sits above the immutable anchor and is never rewritten. Adopted from `aki-mcp-sv`'s versioned paste-in prompt (`[akimcp <ver> · akidevrule <ver>]`), which solved the same "is this artifact stale?" question. Verified: `council_read.py --pinned/--index/--stats` and all seven `council_verify.py` checks key on `## anchor` and `### ` headers, so the added line changes no parse.
135
+
136
+ - **`scythe.py` lints `.sql` line comments (`--`).** The `[WRAP]`/`[YAP]` comment-run logic already covered `#` (`.py`, `.sh`, …) and `//` families; SQL files were silently skipped because no marker pattern claimed the extension. `.py` needed no change — it was already in the `#` set; the file-top header block stays exempt by design in every language, so a wrapped header escapes the script and remains the owner's judgment call.
137
+
138
+ ### Changed
139
+ - **Close-out cost accounting stops calling itself incomplete: the Claude meter is measured exactly, and cross-CLI spend is out of scope by design.** The skill, the arch doc and anti-pattern 20 all described `council_cost.py` as carrying a blind spot the cross-CLI mechanism introduced, closeable "only by hand" — framing an unmeasured cross-vendor number as a debt every run owed. Owner decision (2026-08-16): it is not a debt. The harness writes every turn's `model` and `usage` for the lead and for each subagent under it, so the Claude-side figure is exact rather than sampled, and it is the whole of what Step 1's roster declaration promised — a roster is declared in Claude models. An agy or separate `claude -p` lane bills a different vendor's quota, so folding it in produces a total in no single currency, obscuring the one number being reconciled instead of extending it; where that lane's own spend matters it is reported beside the table, never summed into it. Anti-pattern 20 keeps its slot (numbers are cited elsewhere) and is repointed at the failure that is still live — a total that does not name the meter it covers reads as the run's whole cost and is not. Untouched deliberately: the § *A second axis: which vendor pays* section, which was already about the quota split rather than about the tally being partial, and `agent.A5`'s general "spend crossing a process boundary is invisible" bullet, whose *"if the total matters"* condition this decision simply answers for akiflow. `council_cost.py`'s file header was rewritten in the same pass after the owner carded it `[WRAP]`/`[YAP]`: it was the one script in this directory still hard-wrapping comment prose at ~80 columns (`agent.C3` — the other three already run one logical line long), and two of its paragraphs failed the deletion test (`coding.B4`) by restating `seat_label()` and by duplicating, in a comment, the pricing note the script already prints at runtime. The surviving lines are the three a reader cannot get from the code: the harness transcript layout, why the scope stops at the Claude meter (as a pointer to the arch doc, not a restatement of it), and why dollar cost is absent.
140
+ - **`aki-hands`' substrate table called the in-harness Claude subagent "(default)", contradicting the core rule that loads every session.** `agent.A5` directs discovery to the wide-context tier one-shot — `agy --model gemini-3.7-flash-high` — while the agent definition labelled the Claude lane the default, so the two files disagreed about which engine a sweep starts on. This is the same defect class as the frontmatter-vs-body tier conflict fixed above, one level up: a label carrying precedence that the selection logic does not actually want. Fixed at the shape rather than by moving the label (`pattern.A8`): no lane is default by position, the size of the surface picks it, and that rule is stated once above the table instead of encoded in a row title. Each lane now names its tier explicitly, per the owner's set (2026-08-16): **Claude subagent · `haiku`** for few known paths, an in-session result, or several hands running concurrently — the Agent tool fans out natively where every headless lane needs its own backgrounding; **agy · `gemini-3.7-flash-high`, backgrounded** as the discovery default, ~1M context on a separate quota, launched in the background because a real sweep costs seconds to a minute and blocking on it buys nothing; **kiro-cli · `claude-sonnet-4.5`** for a sweep that is wide *and* needs real reading comprehension, on a third quota. The kiro row's old rationale ("the cheapest bandwidth tier is wanted") was wrong for this model and is corrected in place — sonnet-4.5 meters 1.3× against `qwen3-coder-next`'s 0.05×, so that lane is now picked for comprehension, explicitly not for price. `cl-9rt` is unchanged and stays the parallel-metering lane.
141
+
142
+ ### Fixed
143
+ - **`scythe.py` linted the intersection twice when targets overlapped.** `main()` concatenated `collect_files()` output per target with no identity check, so `scythe.py src src/composables` — or a glob expanding into its own parent — lint every shared file once per target: findings printed twice, `(total N)` inflated, the `SCYTHE_CAP` suppression triggered early, and the worst-files ranking weighted by how the caller happened to spell the target set. Reproduced on git 2.43.0: a one-file nested repo printed the same `[WRAP]` line twice. Fixed by making the file list a set keyed on `os.path.realpath` (first spelling wins for display) rather than by rejecting overlapping targets — overlap is a normal call shape, and erroring would push the intersection arithmetic onto every caller (`pattern.A8`). **Explicitly not changed:** `collect_files()`'s bare `git -C <dir> ls-files`. A report that it leaks files from outside `<dir>` did not reproduce — `git -C skills/akiflow ls-files` returns 12 paths against the repo's 95, none prefixed `..`, consistent with `git-ls-files(1)`'s `--full-name` wording that output is otherwise relative to the current directory. No pathspec was added: guarding a bug with no reproduction is noise, not defense.
144
+ - **`akihelp`'s routing table described akiflow as a council only**, so the fan-out work dispatch now serves would still have been routed away from the skill that gained a home for it. One row added, alongside the existing council row rather than replacing it — the two shapes are chosen by different questions and a reader picking between them needs both visible.
145
+ - **A markdown dash made a declared seat invisible to the ghost-seat check (`council_verify.py`).** `get_declared()` anchored `owner|challenger|worker:` at line start, which matches the block-form fields items use (` owner: value`) but not the bulleted form (`- worker: value`) — so a lane declaring a worker produced `SKIP ghost-seats: checklist.md declares no owner/challenger`, the check silently not running rather than running and passing. The regex now tolerates one optional `-`/`*` bullet marker. Strictly more permissive, so it can only add names to a roster, never remove them: exactly 2 of the 70 live rooms use dash-prefixed declared fields, one now correctly FAILs on four seats that left no turn and no file, and **neither room's exit code changes** — both were already failing on other checks. Found by the agent implementing dispatch, which reported the contradiction between two of its own instructions instead of quietly resolving it; the alternative fix, dropping the dash from the lane seed, was rejected because `--convene`'s lane parser already reads the bulleted shape and lanes are not items. `check_req_coverage()` additionally routes a `## lanes` heading into the same bucket as `## items`, without which every dispatch room would have false-FAILed check 7.
146
+ - **`council_verify.py` checks 3-5 read only `chat.md`, so they scored what they never looked at.** A seat's evidence is now its `chat.md` turns *plus* its own `<seat>.md` at any depth: 48 of 70 live rooms keep per-seat files the checks never opened, and 2 rooms had moved them into a phase subdirectory. Two opposite errors fell out of that blindness. False PASS: `rule-receipts` and `evidence-tags` iterated the posting agents, so the 19 rooms with no `### ` turns iterated nothing and printed PASS — a fresh empty room scored 6/7. False FAIL: `ghost-seats` called a declared seat a ghost whenever it worked in its own file instead of posting. Roster is `declared ∪ posters`; a seat file only supplies evidence for a name already on it, never adds one, or a lead's `summary.md` gets conscripted into a roster it was never part of. Checks with nothing to check now print `SKIP`, not `PASS` — a mini room whose hands are external CLIs legitimately seats no agent, and saying "passed" about it is the exact lie the gate exists to prevent. Measured across all 70 live rooms: 28 change a check verdict (mostly PASS→SKIP and the ghost false-positives clearing), 1 new real FAIL (three seats with files carrying no `[RULES]`), and **0 change any room's exit code** — the gate got honest, not stricter.
147
+ - **No prescribed cheap read for a seat's *first* arrival in the room (`SKILL.md` Step 3).** The read menu covered a rejoining seat (`--pinned` + `--from <its last turn>`) and the lead (`--stats`/`--index`), but a seat arriving has no prior turn to resume from, so the only instruction it could follow was to read `chat.md` whole. Across the transcript corpus that is what happens: 110 whole-file `Read` calls on a council `chat.md` against 10 sliced reads through `council_read.py`, and 47 of the 63 transcripts doing it are subagents. Rooms are big enough for this to matter — median 14 KB, 21 of 70 over 30 KB, largest 201 KB (~50k tokens per read). Added the arriving-seat line: `--pinned` + `--index`, then only the turns its own mandate names.
148
+ - **agy discovery-tier default was stale: `gemini-3.6-flash-medium`, recorded 2026-08-02, predated the `gemini-3.7-flash-*` release.** A session cited the new model, got told (correctly, per the then-current recorded fact) that it didn't exist, then a live `agy models` probe on 2026-08-15 showed it does. Owner set the new default explicitly: **`gemini-3.7-flash-high`**. Updated everywhere the default is declared — `payload/RULE-agent-behavior.md` (core rule, loads every session), `claude/agents/aki-hands.md` (substrate table), `skills/akiflow/references/harness-facts.md` (fact + rationale row, the canonical invocation code block, and the recorded `agy models` list itself, re-probed and dated 2026-08-15), `docs/arch/akiflow.md` (substrate-selection table). Left alone deliberately: `docs/research/headless-cli-workers-aug1.md`, an immutable event record of what was measured on 2026-08-01. The generic "flash-tier worker is retrieval-only" rule was pinned to `gemini-3.6-flash-*`; generalized to `gemini-*-flash-*` so it doesn't go stale on the next generation bump. `aki-hands.md`'s "do not re-probe recorded facts" instruction gained one exception: verify live when a caller names a model absent from the recorded list, since a new generation shipping is exactly the drift a static record can't self-correct for.
149
+ - **`council_cost.py` counted no subagent at all, and said nothing about it.** Step 6 is mandatory, so every run since the harness changed its transcript layout closed on a cost table containing only the LEAD row — wrong output in the worst class, indistinguishable from a correct one. The script selected subagent turns by filtering `isSidechain: true` out of the **main-session** transcript; those turns had moved to `<session-id>/subagents/agent-<id>.jsonl`. Measured across 1094 transcripts on this machine: the flag appears 71,839 times and **not once** in a main-session file. Seat labels were a second defect of the same silent kind — a `You are ([A-Za-z0-9…]+)` regex over transcript prose, whose top captures corpus-wide are the English phrases `"You are a"` (325), `"You are the"` (167) and `"You are an"` (73), ahead of the best real seat name (`red-team`, 45) and of ordinary prose like `"You are fixing"` (41) — counts taken 2026-08-15 against a corpus that keeps growing, so re-running moves them without changing the shape. Labels now come from each seat's `agent-<id>.meta.json` sidecar, and deliberately use `agentType` **plus** `description`: real rooms spawn nearly every seat as `general-purpose`, so `agentType` alone re-creates the same defect by merging unrelated seats into one row — proven live, two concurrent `aki-maker` seats in the session that fixed this would have collapsed together. The session id comes from the `claude-session` stamp `council_open.py` now writes into `chat.md`, with `--session <uuid>` for rooms opened before the stamp existed. **Where the id or the transcript genuinely cannot be resolved the script now exits 1 and says so**, rather than printing the plausible partial table that was the original bug (`coding.C1`); zero subagent files is a different case and stays a valid exit 0, since a room that spawned no seat has a complete LEAD-only answer. CLI contract changed accordingly — `[transcript.jsonl]`, auto-detecting the newest file by mtime, became `[<session-dir>] [--session <uuid>]`, matching `council_verify.py`'s positional convention; the old auto-detect was itself the kind of guess this fix exists to remove. Dead machinery deleted rather than left dormant: `chain_root()`, `by_uuid`, `text_of()` and the `sidechain-N` fallback numbering all existed only to disentangle interleaved seats inside one shared file. `SKILL.md`'s Step 6 invocation block and `harness-facts.md`'s transcript-layout fact (an `[obs]` row from 2026-07-31, when both really did live in one file) corrected and re-dated.
150
+ - **`SKILL.md` Step 2 stated the model-inheritance mechanism backwards, and `aki-hands` contradicted its own frontmatter.** The rule read "every spawn passes `model` explicitly — an omitted `model` inherits the lead's own top tier"; the live Agent tool schema says the opposite, that an omitted `model` takes the agent definition's frontmatter and falls through to the caller only where the definition names none. All five agents in `claude/agents/` carry a `model:` line, so the stated failure could not occur for any named seat, while the one case that *does* inherit the lead's tier — a generic `general-purpose` subagent — went unnamed, despite being precisely how Step 6's cost seat is spawned (it needs `Bash`, which `aki-hands` lacks). Rewritten to state frontmatter as the single source of truth for `model`, with the generic-subagent hazard named. Separately, `aki-hands` declared `model: sonnet` in frontmatter while its own substrates table prescribed `model: haiku` for the default lane — one file, two tiers, and the frontmatter is the one that executes. Frontmatter set to `haiku` so the cheap tier is what happens by default rather than what every caller must remember to pass (`pattern.A8`); a hard retrieval can still override upward at spawn. `docs/arch/akiflow.md` failure mode 12 restated the same wrong mechanism and was rewritten to the real failure — declared tier and executing tier disagreeing, in either direction. **Surfaced but deliberately not changed:** `aki-challenger` is pinned to `sonnet` while `SKILL.md`'s roster guidance calls for a strong model on adversarial review. The old wrong belief hid this (a challenger spawned without `model` was assumed to arrive at the lead's top tier); correcting the mechanism reveals that nothing enforces the guidance. Raising it is a cost decision for the owner, not a mechanical fix.
151
+ - **`cl-9rt`/`cl-9rt-min` was never explicitly flagged as a shell alias inert in a spawned process.** Every mention already gave the expanded literal command rather than the alias name, but nothing said *why* — a worker prompted with the bare alias name would get "command not found". Added an explicit one-line caveat in `harness-facts.md` § claude via a proxy gateway and in `aki-hands.md`'s substrate table row.
152
+ - **Dispatch traced a seat by its worker type, not by its lane — two lanes sharing a worker collapsed into one trace.** `council_verify.py::get_declared()` took the seat name from a lane's `worker:` value (an agent type, e.g. `aki-maker`), while dispatch's own evidence file is named after the **lane** (`scripts.md`) — so a lane's own-named report read as a ghost, and renaming that report to the worker's name made one file satisfy ghost-seats/receipts/evidence-tags for every lane sharing that worker. Confirmed live: two lanes both declaring `worker: aki-maker`, one file renamed to `aki-maker.md`, scored 7 PASS covering both. Fixed by tracing dispatch by lane name: `get_declared()` reads `chat.md`'s `mode` stamp (duplicating `council_open.py::read_mode()` — the scripts stay standalone) and, in dispatch mode, returns LANE heading short names (text after `·`, slugified, HTML comments stripped so the seed's own example is never picked up as a ghost lane) instead of `owner|challenger|worker` values; the council path is untouched. `SKILL.md` Step 1b and `docs/arch/akiflow.md` corrected: a lane's trace identity is its own name, `worker:` is roster/cost metadata a lane may share with another. Verified against the same repro (now correctly FAILs both lanes when a report is misnamed) and against all 69 live rooms: zero exit-code changes, since none carry a `mode dispatch` stamp.
153
+ - **`writes:` exclusivity was token string-equality; a glob prefix and a literal path inside it both PASSed.** `_convene_dispatch()` (`council_open.py`) keyed `writers[path]` by the literal comma-separated token, so `writes: docs/arch/b.md` in one lane and `writes: docs/**` in another — Step 1b's own example shape — convened clean despite `CHANGELOG.md`, `docs/arch/akiflow.md` and `SKILL.md` all promising no path is claimed by two lanes. Fixed with cheap prefix-aware overlap, no glob engine: a token ending `/**` or `/*` normalizes to a directory prefix; two tokens collide when equal, or when either's prefix is a `/`-boundary-respecting ancestor of the other (`docs` never swallows `docs-old`). Single-`*` basename globs (`scripts/*.py`) stay literal tokens — real glob matching is out of scope. The FAIL message now names both colliding tokens and both lanes. Verified: the repro above now FAILs; a literal path claimed twice FAILs; `skills/**` vs `docs/**` PASSes; `docs/**` vs `docs-old/file.md` PASSes.
154
+ - **`harness-facts.md` still published the exact number finding E retracted.** The transcript-layout `[obs]` row read "1091 transcripts on this machine, 876 occurrences" and claimed to be "re-verified and corrected 2026-08-15" — but `docs/research/akiflow-cost-and-shape-aug15.md` finding E, and this file's own 2.2.1-cycle entry above, already establish 876 as a counting error (files containing the flag, published as occurrences) against 71,839 occurrences across 1094 transcripts. The fact file akiflow actually reads at runtime was the one copy still wrong. Corrected to `1094 transcripts on this machine, 71,839 occurrences (in 876 files)`.
155
+ - **Lane-field regex matched mid-prose and mid-word.** `_field_paths()` and the dispatch completeness check in `council_open.py` used an unanchored, colon-optional `re.search(rf"{field}[ \t]*:?[ \t]*\S", block)`, so the word "rewrites" inside a lane's `reads:` prose matched `writes` and could fabricate a phantom claim, and a field merely mentioned in a sentence counted as declared — while `council_verify.py::get_declared()` already anchors at line start with an optional bullet. Anchored both to the seed's own line shape: `(?m)^[ \t]*(?:[-*][ \t]+)?{field}[ \t]*:[ \t]*(\S.*)` — start of line, optional bullet, mandatory colon. `_convene_council()`'s looser check left untouched, since its two live line forms (pipe and block) need their own verification before anchoring. Verified: a `reads:` line containing "rewrites" produces no `writes:` claim; the seeded template (HTML-commented) still counts zero lanes; the writes-overlap repro above behaves identically.
156
+ - **`council_read.py` read `chat.md` with locale-default encoding.** The other three council scripts pass `encoding="utf-8"` explicitly; `council_read.py` alone called `read_text(errors="replace")`, which mis-decodes non-ASCII — rooms routinely carry Vietnamese — on a non-UTF-8 locale with no visible error, since `errors="replace"` swallows the failure silently. One-line fix: `encoding="utf-8"` added.
157
+
158
+ ## [2.2.1] - 2026-08-14
159
+
160
+ ### Fixed
161
+ - **`.sh`→`.py` migration completed in living docs — five references the 2.2.0 sweep missed.** 2.2.0 renamed the akiflow helper scripts to `.py` (SSOT) and corrected the `.sh` names across the docs, but left the `akiflow` skill description in `README.md` (`council-open.sh`, `council-verify.sh`) and three mechanism references in `docs/arch/akiflow.md` (`scripts/council-read.sh` in the Phase-A retrieval note, `council-open.sh` in the anchor mermaid node, `scripts/council-open.sh` in the 30-day-prune note) naming the transitional Unix wrappers instead of the canonical `council_open.py` / `council_read.py` / `council_verify.py`. Corrected to the `.py` SSOT, matching the arch doc's own established prose convention (bare `council_open.py`, no `scripts/` prefix). Deliberately left unchanged: the transitional `*.sh` wrapper files (they exist so external prompts naming `council-open.sh` keep working on Unix during the transition) and the `docs/index.md` research-table captions (faithful summaries of immutable `docs/research/` records that themselves use the `.sh` names).
162
+ - **`docs/arch/akiflow.md` anchor stamp bumped `v2.1.0` → `v2.2.0`** per `docs.A4` — rewritten in the same edit as the content change; `<version>` is the last released version at edit time.
163
+
164
+ ## [2.2.0] - 2026-08-12
165
+
166
+ ### Added
167
+ - **`docs.A4` — anchor stamp.** Every `docs/arch|biz|feat` doc now carries `> updated <YYYY-MM-DD> · v<version>` as the first line of its header block, rewritten in the same edit as any content change. `<version>` is the last *released* version at edit time (never an `[Unreleased]` buffer; short commit hash where a project has no version scheme). `plan/`, `research/` and `ref/` are excluded — the first two are immutable event records their own schema already dates, and `ref/` is verified by running its commands. Closes the dangling promise in `docs.A2` ("record modification dates in the doc's own metadata"), which never defined a field. Applied to this repo's own two `docs/arch/` files.
168
+
169
+ - **`council_verify.py` check 7 — REQ coverage.** Fails when a ratified `REQ-<n>` is named by no item's `covers`. Closes the one blind spot no seat can cover: `aki-challenger` is given the items the lead cut, so a requirement that never became an item is outside every seat's reach by construction. Implemented as a diff of two artifacts the lead already wrote — not as a "REQs with no item" line the lead declares, which would ask the omitting party to report its own omission (`agent.B2`). Parses both checklist forms in real use (block `covers:` and one-line `| covers REQ-2,3 |`) and expands the compact run form. First run against a live session found one orphan.
170
+ - **`council_open.py --convene <session-dir>`** — exit 1 unless ≥1 `ITEM` carries `owner` + `challenger` + `closes when`; `SKILL.md` Step 2 now requires it before the spawn batch. Gates *convening* rather than file creation: R1 needs the anchor pinned before the ledger can quote it, so `chat.md` must exist first — and the cost of an uncut question ("the most likely death of a run") is paid at spawn, not at `mkdir`.
171
+
172
+ ### Fixed
173
+ - **`docs/arch/rule-delivery-architecture.md` drifted through two releases.** The core-vs-router determinism row claimed all Claude Code rules arrive via "0 model-dependent hops", contradicting the same doc's own mermaid; now states the split explicitly (4 core files `@`-imported by `~/.claude/CLAUDE.md`, guaranteed; everything else routed through `akirule`, best-effort). Every `install.sh`-as-installer reference corrected to `install.py` (SSOT; `install.sh`/`install.ps1` are thin launchers); every `rsync` mechanism reference corrected to Python `shutil` (`sync_dir_delete()`, rsync `--delete` *semantics*, no rsync binary involved); skill count `8` → `9`; `claude/` source-tree listing gained `agents/` and `fragments/`.
174
+ - **`docs/ref/agent-skills-standard.md` described `install.sh`'s `sync_aki_skills()` as "rsync-ing"** — corrected to `install.py` / Python `shutil`.
175
+ - **`README.md` mermaid said `payload/ (15 raw rule files)`**, contradicting the correct count of 18 stated later in the same file.
176
+ - **`docs/index.md` research table was missing `gemini-helpfulness-bias-enforcement.md`** — added.
177
+ - **`payload/index.md` had no trace of the `content.C2` content audit** added in 2.1.0 — added to the `RULE-content-write.md` manifest row and the "Audit reports, never fixes" cross-cutting lens row.
178
+ - **`README.md` Tier 1 list gave `RULE-content-write.md` no gloss**, unlike its neighbors — added one naming the content audit.
179
+ - **`scythe.sh` named as the detector/engine in `RULE-agent-behavior.md` §0 and `METHOD-zero-trust-audit.md`**, while every invocation site and README's own stated source-of-truth use `scythe.py` — corrected in both files plus `payload/index.md`.
180
+ - **`skills/akihelp/SKILL.md` named a "Red Team subtraction pass"** — no such seat exists in `claude/agents/`; corrected to `aki-challenger`, the seat that actually owns the subtraction question. The same phantom seat also shipped in `payload/index.md`'s "Subtraction before abstraction" lens row — an `@`-imported file, so it was teaching the stale vocabulary back to every session; corrected there too.
181
+ - **`skills/akiflow/SKILL.md` prescribed turn tags its own mandated gate rejects.** Step 3 said `#### CLAIM / EVIDENCE / ATTACK / OPEN` while `council_verify.py` check 5 requires `FACT|CONSTRAINT|ASSUMPTION` — following the skill exactly produced a FAIL. `FACT/CONSTRAINT/ASSUMPTION` wins (it is the vocabulary `docs/arch/akiflow.md` records in three places, inherited from `METHOD-deep-think.md` B2); SKILL.md now states it.
182
+ - **`docs/arch/akiflow.md` still named the gate `council-verify.sh`** (twice) and listed "spawning without explicit `model`/`effort`" as failure mode 12 — contradicting the same document's own correction two sections earlier that the in-session Agent tool has no `effort` parameter.
183
+ - **`README.md` still described the lint engine as `scythe.sh` / "deterministic grep+awk"**, and its installed-files tree listed five `council-*.sh` scripts that are now `.py` — tree corrected to the five `.py` files plus one line for the transitional `.sh` wrappers that exec them.
184
+ - **akiflow's step numbering drifted a whole phase behind its own skill.** The council rewrite collapsed the run to Steps 0–6, but `docs/arch/akiflow.md` and `skills/akiflow/references/harness-facts.md` still cited Steps 7/8/9 and `anti-pattern #11` — addresses that no longer resolve to anything, so a reader following them lands nowhere. 21 references repointed (close-out 9→6, execution 7→5, closure/escalation 6→4, roster batch 5→2, nesting rule → anti-pattern #8, Phase-B loop-back → Step 5's reopen rule), plus the surviving `council-open.sh`/`council-cost.sh`/`scythe.sh` names in those two files corrected to `.py`.
185
+ - **Step 6 told the lead to delegate the cost tally to a subagent that cannot run it.** The natural pick — `aki-hands`, the retrieval seat — is `Read, Grep, Glob` and returns a refusal instead of a table; found by hitting it. `SKILL.md` Step 6 and the arch doc now require a `Bash`-holding seat (`aki-conduct` or a generic subagent).
186
+
187
+ ## [2.1.0] - 2026-08-12
188
+
189
+ ### Changed
190
+ - **`RULE-design-core.md` → `RULE-pattern-core.md`, slug `design.*` → `pattern.*`.** The old name kept reading as UI/visual design; the file owns universal architecture-pattern law (SSoT, Rule of Three, SRP, OCP, boundaries). Full rename per the new "standard over legacy" principle — every live reference migrated in this change (payload manifest + cross-cutting lens, `RULE-coding`/`RULE-ui-pattern`/`METHOD-subtraction-audit`/`METHOD-proportionality` slug refs, `claude/CLAUDE.md` `@`-import, agent briefs and `[RULES]` receipt examples in `claude/agents/*`, `skills/akirule|akihelp|akiflow`, `install.py` AG map, `README.md`, `docs/index.md`, `docs/arch/akiflow.md`). Historical records (past CHANGELOG entries, `docs/research/`, `docs/plan/done/`) intentionally keep the old name. Also fixed the file's stale tier header ("Contextual" → Core `@`-import, drifted since the 1.x promotion).
191
+ - **`ui.B5` rewritten: hover bridge → hover proximity.** The old rule prescribed only the patch (transparent `::before`/`::after` bridge over the gap); the root cause — trigger and hover-shown content rendered far apart so the popup closes mid-travel — was never stated. Now an invariant (popup stays open while the pointer travels trigger → content) with the root fix first (nest in the trigger's hover scope, spacing via inner `padding` not `margin`) and bridge/close-grace-delay demoted to the portal/teleport + `overflow`-clipping escape hatch.
192
+ - **`coding.B3` gains anti-over-verification clauses aimed at done-gating, not test-writing.** Static reading IS verification when the property is fully determined by visible code flow — the item closes on that stated evidence; escalating a tier requires naming the specific doubt that tier settles; and a done-transition must never be parked on human manual testing for checks the agent can settle statically — the human is handed only what needs human runtime judgment (UX feel, visual rendering, live external integration). Plan checklists stay fully detailed; the gate abuse was the violation.
193
+ - **`akirule` skill description now carries the trigger signals.** The description is the only router surface the model sees every turn (the signal lists in the body load only after invocation), and a headless 5-prompt experiment measured 0/5 router firings with the old signal-free wording. It now enumerates the concrete entry points — file extensions (.md/.vue/.css/.tsx/.rs/.sql), docs/release/commit/deploy, UI/SEO/DB/Tauri/i18n/biz/UX/refactor/audit topics, big decisions — so invocation no longer depends on the model recalling an unstated mapping.
194
+ - **English-only sweep of the public corpus.** Vietnamese section/group headers and stray Vietnamese prose in `payload/`, `skills/`, `claude/` translated to English per the CLAUDE.md content-language rule, with `payload/index.md` group tables synced to the new headers. Functional Vietnamese is untouched: routing keyword/signal lists, literal trigger phrases (`nạp full`), and worked examples that need Vietnamese text (NFC "Nguyễn", accented SEO queries).
195
+
196
+ ### Added
197
+ - **`release.B4` compare-link footer.** GitHub-hosted repos must end release notes with `**Full Changelog**: <repo-url>/compare/<prev-tag>...<new-tag>` (or use `gh release create --generate-notes`, which inserts it) — the Release page shows notes only and the tag points at a single commit, so without the link there is no one-click view of the commits accumulated since the previous release; first release links `<repo-url>/commits/<new-tag>`.
198
+ - **`content.C2` content audit** — three read-only sweeps (canonical-term drift, density deletion test, i18n coverage) severity-classified per `docs.C4`; closes the one audit domain that had no playbook.
199
+ - **`docs.C3` inverse walk** — a complex feature/subsystem with no corresponding `feat/`/`arch/` doc is now an explicit Incomplete finding; drift audit checks code → docs, not only docs → code.
200
+ - **`CLAUDE.md` "Rule authoring principles"** — standard over legacy (this repo IS the standard; migrate fully, never keep a worse form for compatibility), dense keyword-first technical wording budgeted by violation frequency, and self-compliance (a new rule/skill needs a `pattern.A2`-grade reason to exist and passes the `pattern.B3` critique gate).
201
+
202
+ ### Fixed
203
+ - **`CLAUDE.md` rename checklist pointed at `install.sh`** — the installer SSOT has been `install.py` since 2.0.0; the launchers are thin.
204
+
205
+ ## [2.0.2] - 2026-08-11
206
+
207
+ ### Changed
208
+ - **`aki-article-writer` image handling is now `article_arch`-aware.** The skill previously assumed every project embeds images via markdown `![]()` in body content and generates hero + N body images by default. It now requires the Image Scout brief to resolve `article_arch` (`markdown` vs `component`) by inspecting the project's actual render path before deciding image count and embed method — a real project (akitao.com) stores articles as structured `.ts` records rendered by a shared Vue component with a hand-written inline-markdown parser that does not support `![]()`, so following the old instructions verbatim would have shipped literal broken markdown text into the rendered page. `component` architecture now forces single-image mode: one file at `public/images/articles/<slug>.<ext>` reused as both the rendered hero and the record's `ogImage`/share-image field, instead of a separate hero + per-body image set.
209
+
210
+ ## [2.0.1] - 2026-08-11
211
+
212
+ Maximise interpreter compatibility with the minimum code change: the corpus already sat at a Python 3.7 floor, but delivery assumed whatever `python3` resolved to and one line reached past the floor. Fixed so the same install runs across the full spread of Pythons a real host carries.
213
+
214
+ ### Fixed
215
+ - **`install.py` no longer crashes on Python 3.7.** Line 568 used `Path.unlink(missing_ok=True)`, a 3.8+ keyword, and aborted the whole install with `TypeError: unlink() got an unexpected keyword argument 'missing_ok'` on a deploy host whose `python3` was 3.7 — the exact class of drift the 2.0.0 notes already flagged for the `write_text(newline=…)` 3.10 kwarg, slipped in through the one code path that had no guard. Replaced with an `exists()`-then-`unlink()` check (3.7-safe). `vermin` confirms the whole corpus now needs only **3.7** (helpers sit at 3.6–3.7); the one accidental 3.8 reach is gone.
216
+ - **`install.sh` stops trusting `python3`.** A host commonly carries several Pythons and `python3` may point at an old one (3.7 seen on the deploy host, while 3.8–3.14 were also installed). The launcher now probes `python3.14 → … → 3.8 → python3 → python` and execs the **newest** interpreter that meets the 3.7 floor, or exits with a clear "Python 3.7+ required" line if none does — rather than firing whatever came first on PATH.
217
+
218
+ ### Added
219
+ - **Runtime floor guard in `install.py`.** A one-line `sys.version_info < (3, 7)` check at the top fails with a single readable message instead of a cryptic error 500+ lines into the run — the safety net for any launcher (including `install.ps1`) that still hands the program a sub-floor interpreter. The floor is now stated in exactly two enforced places (the guard and `install.sh`), and documented once in the README.
220
+
221
+ ### Changed
222
+ - **README Requirements: Python 3.8+ → 3.7+**, with a note that `install.sh` selects the newest interpreter meeting the floor and fails clearly below it.
223
+
224
+ ## [2.0.0] - 2026-08-11
225
+
226
+ Windows becomes a first-class install target by moving delivery to a **Python SSOT**: one program does every mechanical step, thin launchers exec it, and the content layer is unchanged. Plan `docs/plan/unify-desktop-support.md`; execution was coordinated as a mini akiflow council with two external CLI hands (kiro-cli, agy on claude-sonnet-4-6) doing file labor under the lead's verification.
227
+
228
+ ### Added
229
+ - **`install.py` — the cross-platform SSOT installer**, reproducing every observable effect of the old `install.sh` (payload sync, global `CLAUDE.md` merge with backup, per-skill mirror-with-prune into the five CLI skills roots, agent-file copy, Antigravity rule/`skills.json` generation, `settings.json` merge, `.source-repo` stamp, legacy-root migration, status preview). Verified by **execution parity**: `install.py` and the recovered `install.sh` were each run into a sandboxed `$HOME`, and the resulting trees were identical across 203 files. Non-TTY runs (CI) auto-proceed; a TTY still prompts.
230
+ - **`install.ps1` — thin Windows launcher** that discovers the interpreter (`py -3` → `python3` → `python`) and execs `install.py`. `install.sh` is now the same kind of thin launcher for Unix (`exec python3 install.py "$@"`), so all three entry points route to one program.
231
+ - **Five council/lint helpers ported to Python** — `council_open.py`, `council_read.py`, `council_verify.py`, `council_cost.py`, `scythe.py` — each verified against its bash original (identical output and exit codes; `council_verify.py` additionally fixes a `set -e` abort the `.sh` hit on sessions with no turns). The `.sh` files stay as thin `exec python3 …` launchers so existing Unix references keep working.
232
+ - **CI install-smoke gate** (`.github/workflows/install-smoke.yml`) — matrix `ubuntu` / `macos` / `windows-latest`, runs `install.py` into a sandbox HOME and asserts the manifest plus LF-cleanliness of installed files. This is the designed Windows verification: no maintainer runs a Windows box locally, so CI is the gate that lets the repo claim Windows support truthfully.
233
+
234
+ ### Changed
235
+ - **README Requirements: Windows ❌ → ✅ Supported.** Python (3.8+) is now the sole hard requirement; the interpreter-discovery convention and OS-aware install/update commands are documented once. Added a PowerShell install block and a Windows uninstall note.
236
+ - **LF discipline enforced at the byte level.** The Python writer uses `path.write_bytes(content.encode("utf-8"))` rather than `write_text(..., newline=…)` — the latter kwarg is Python 3.10+ and would crash the target machine's 3.9, and byte-writing also guarantees exact LF on Windows where text mode would translate to CRLF (which the plan forbids).
237
+ - **Docs synced to the port** — `skills/akiflow/SKILL.md`, `skills/akilint/SKILL.md`, `claude/agents/aki-conduct.md`, `claude/CLAUDE.md` (template), and `claude/hooks/aki-update-check.py` now reference the `.py` scripts / an OS-aware installer command instead of the bash originals. `docs/index.md` and the plan doc updated.
238
+
239
+ ### Notes
240
+ - **mcp-sv coupling left open by decision.** The plan's §11 item on tightening the [aki-mcp-sv](https://github.com/lacvietanh/aki-mcp-sv) dependency stays open; the mcp-sv repo was not touched in this release.
241
+ - **Windows verified by CI, not by a local box.** The owner accepted CI-as-the-designed-gate; the ✅ claim rests on the `windows-latest` matrix leg passing, not on an in-session Windows run.
242
+
243
+ ## [1.0.0] - 2026-08-10
244
+
245
+ ### Fixed
246
+ - **`scythe.sh` caps its own output** — a repo-wide sweep printed every finding, and on a real project that is 891–2,393 lines / 93–255 KB from a single run. Execution was never the problem (0.8s); the dump was. For an agent caller the cost compounds: that blob lands in the transcript and **every later turn re-sends the whole history**, so one careless `scythe.sh .` degrades the rest of the session — the exact failure `agent.A2` describes, caused by the corpus's own tooling. Owner-reported from a live `tachnhac.com` session that slowed to a crawl. Past 40 findings (`SCYTHE_CAP`) output is now the first 40 plus per-tag totals and the five worst files; `--all` restores the full list. 93 KB → 4 KB on that repo. Exit codes unchanged (0 clean · 1 findings · 2 usage), which needed `awk` instead of `head` for the truncation — under `pipefail`, `head` closing the pipe early turned a findings run into exit 141.
247
+ - **Nothing runs this script automatically.** The only configured hook is `aki-update-check` (SessionStart, notify-only). Its callers are `/akilint` when invoked and akiflow's `akirule-enforcer` seat while a council runs — both model decisions, which is why repeated whole-repo sweeps could pile up unnoticed.
248
+ - **`scythe.sh` no longer flags machine-parsed line runs as `[WRAP]`** — its markdown detector was a blacklist that enumerated known block structures and called everything else prose, so an unfamiliar shape still produced a confident verdict. It flagged the new `@` import block in `claude/CLAUDE.md` and told the reader to rejoin the lines, which would merge four import directives into one and silently stop three of the four core rules from loading. The detector was contradicting `agent.C3`, the rule it exists to enforce, on the exact case that rule names. Note the asymmetry that made this worth fixing rather than ignoring: a false positive here can destroy the loader, a false negative just leaves a wrapped line for the owner to call — so the detector must bias toward silence.
249
+ - New rule: **two adjacent lines carrying the same directive marker are a machine-parsed run**, since wrapped prose never repeats a marker while an `@import` block, a badge/link list and a `Status:`/`Owner:`/`Created:` header all do. Markers restricted to `@`, a leading `[`, and a one-or-two-word ASCII label closed by a colon.
250
+ - Chosen over three alternatives that were built and **measured against 1,244 markdown files plus a wrap-archetype fixture**, each rejected on evidence: requiring an ASCII-lowercase continuation missed every Vietnamese wrap (`được`, `ở` are multibyte and `[a-z]` cannot match them in mawk); requiring ≥3 tokens on both lines cost 664 real detections, because the tail of a wrapped paragraph is often one word; treating any shared leading punctuation as a marker cost ~2,000, because backtick and `**` open prose constantly. A looser label pattern was also rejected after `file.ts:123` citations were observed firing it. Final measurement: **0 findings gained, 208 of 9,653 dropped (2.2%)**, all structural across two independent inspection slices.
251
+ - **Two measurement failures recorded in `docs/research/core-floor-promotion-aug6.md`**, because each produced confident wrong numbers: sending the detector's stderr to `/dev/null` hid a mawk `REcompile()` panic on an interval regex (`{1,20}` — unsupported in mawk 1.3.4) so a total crash read as a clean sweep; and two runs of the same `find` over `~/aki` returned different file sets because live git worktrees changed underneath, invalidating every early before/after diff. Both surfaced only when a strictly-narrower rule reported *more* findings than the original. Freeze the file list and keep stderr when touching this script.
252
+
253
+ ### Changed
254
+ - **`release.B4` now creates the GitHub Release, not just prints a block** — the old wording ("output a copy-ready GitHub Release block") let a release stop at `git push --tags` and report done while the Releases page still showed the previous version (real miss on an aki-mcp-sv 1.3.0 release: tag + code pushed, Releases page stuck at 1.2.0). B4 now states a pushed tag is not a release (per A1); when the repo publishes GitHub Releases and `gh` is available the Release is created directly via `gh release create` and verified with `gh release list`, with the copy-ready block kept as the no-`gh`/manual-publish fallback. Adds a backfill cross-check for tags that have no matching Release.
255
+ - `coding.A2`: "Single-developer friendly" → "Single-maintainer friendly" — clarify it's about maintainer count, not user count; never an excuse to cut UX.
256
+ - **`/akiflow` reduced from 435 lines to 181, by deletion rather than compression** (same decision record; plan Batch 3). What was removed had moved elsewhere: the 55-line pasted thinking floor (~70% duplicated `agent.A4`/`agent.C3`/`coding.B4`/`METHOD-deep-think`, its one unique clause now `agent.B2`), the inline seat definitions (now `~/.claude/agents/`), and the mandate for **two standing seats on every Tier 1/2 roster** — a roster derived from a tier instead of from a requirement, and the direct cause of the observed over-staffing.
257
+ - **Tiers became modes**, discriminated by one question — *what changes outside the room*: `discuss` (nothing; no `aki-maker` is convened), `audit` (nothing, read-only by construction), `execute` (files; only `aki-maker` may write). The tier number was condition 2 of the activation gate restated, and its only additional effect was naming a roster, which is exactly what it should never have done.
258
+ - **`council-open.sh` now requires the owner's verbatim message as an argument** and refuses to open a session without it, writing it as `chat.md`'s immutable `## anchor` block. Pinning was a Step 0 discipline that both audited runs skipped — one pinned a SePay/D1/wallet consolidation question when none of those four words appeared in what the owner wrote. Every `REQ-<n>` must now carry a `"quoted fragment"` found in that block: the cheapest mechanical tie back to the owner's words, and the only one that survives a lead which has already convinced itself.
259
+ - **`council-verify.sh` stopped requiring a named seat.** Its old enforcer check *forced* `akirule-enforcer` to exist regardless of whether anything needed enforcing, and when it fired on a run with nothing to enforce, that run's lead renamed a chat header to make it pass rather than concluding the seat did not belong — **a gate that manufactures work gets gamed rather than questioned.** It now checks six things and names no seat: a non-empty anchor · every REQ quoting it · no ghost seats · a `[RULES]` receipt per posting agent · per-agent evidence tags · every `REMIND` answered.
260
+ - **`scythe.sh` is unchanged in content and demoted in position**: a tool belonging to `aki-conduct`, run at the end of a round and only when the run wrote durable files. Never a seat, never a gate condition. When it fires, the thing to fix is the brief that permitted the error. The enforcer seat itself survives — the earlier verdict against it was wrong (an unanswered `REMIND` blocks closure, so it *does* return a verdict against the lead); what failed was the anchor, not justification, since it was pointed at throwaway internal minutes and spent 53,470 tokens on five reminders about meeting notes nobody would read again.
261
+ - `docs/arch/akiflow.md` rewritten to current state (`docs.A2`), including the two laws, the mode table, the agent layer that replaced the pasted floor, and a corrected flow diagram. `README.md`, `docs/index.md` synced.
262
+ - **`RULE-coding.md` and `RULE-design-core.md` promoted to the core floor** — both are now `@` imports in `claude/CLAUDE.md`, joining `index.md` and `RULE-agent-behavior.md`. Four guaranteed files, no model decision anywhere in the load path (decision record `docs/research/core-floor-promotion-aug6.md`). The trigger was a process complaint, not a content one: the owner asked what short keyword would stop the constant "lại vi phạm akirule", and named `wrap`, `yap`, `pattern`. Splitting those by *why they were possible* produced two classes with opposite fixes. `[WRAP]`/`[YAP]` are violated with the rule **in context** — §0 is core-loaded every session — so no amount of rule text can help and only a mechanism outside the model's judgment can. `pattern` was the other kind: `payload/index.md` labelled these two files *"default ON"*, but they routed through `akirule`, a skill that loads only after the model chooses to invoke it. **"Default ON" was a statement of intent that the mechanism could not deliver**, and it read as a guarantee to every human checking the manifest. The rules needing the most correction were frequently absent rather than disobeyed.
263
+ - Cost stated, not buried: ~16.7 KB enters every session including sessions with no code in them, on top of the ~31 KB already spent. Written into `claude/CLAUDE.md`, `payload/index.md` and `README.md` — wherever a reader might check the tier — rather than only here.
264
+ - `skills/akirule/SKILL.md` loses both Tier 1 signal blocks, replaced by a note that **forbids re-adding them**: a signal block for a file already in context can only produce a redundant `Read`. Its load-confirmation example no longer prints a core file, since listing one would claim credit for a load the skill did not perform. `skills/akihelp/SKILL.md` and `README.md` updated where they enumerated the guaranteed set; the `akirule` README row had claimed the skill "loads core rules always" — it never did, and now visibly does not. The `docs/arch/rule-delivery-architecture.md` diagram edge labelled `@import Tier 1` on the skills→rules arrow was wrong in both halves and is now split into signal-`Read` versus `@`-import.
265
+ - **Deliberately not extended to Antigravity**: `install.sh`'s `AG_RULE_MAP` keeps both at `model_decision`, because that installer carries a constraint Claude Code does not — AG silently truncates past an internal customization budget, so `always_on` is rationed to behavior rules and promoting two more risks losing the set silently. The surfaces now disagree on purpose, with the reason recorded at the constraint.
266
+ - **`RULE-ui-pattern.md` deliberately not promoted** despite `pattern` being one of the three named violations: it already loads on file extension alone, the strongest signal the router has, and the 30,026 lines of sprawl in `ui-css-minimization-aug4.md` were written *with it loaded* — a compliance failure this fix does not address.
267
+ - Reverses `docs/research/akirule-akiflow-upgrade-aug3.md`, which rejected core-floor placement three days earlier with the falsifier *"still reminding >~2×/week after two weeks → escalate placement"*. The escalation is owner-initiated on a qualitative report at three days, not a counted threshold at two weeks; the record says so, so a later review can judge the promotion against the evidence actually available. **Reopen trigger:** `pattern`-class violations still reported after two weeks means the cause was compliance all along, and the next move is the enforcement tier rather than more context.
268
+
269
+ ### Added
270
+ - **Ollama CLI auto-loads every skill under `~/.claude`** — one line recorded in `docs/ref/agent-skills-standard.md`; owner-observed 2026-08-07, no deploy step needed.
271
+ - **A native agent layer: `claude/agents/`, five definitions** (same decision record; plan Batch 2). Seats were being convened by **job title** and then handed rules. The order is inverted: an agent *is* a system prompt plus a rule set, and a name with no distinct filter behind it is a rule demanding a salary. The survival test each of the five passed is one question — *can this filter return a verdict against the lead's conclusion?* If yes it needs its own head, because its reasoning must not be contaminated. If it can be checked by reading, it is a rule loaded into whoever is already working, not a seat.
272
+ - `aki-hands` (judgment **forbidden**, facts with `file:line`) · `aki-judge` (**exactly one** standard, named at spawn — the four previously separate judgment seats differed by one parameter, so they are one file) · `aki-conduct` (judges the process, `+Bash`, owns the LOAD-fail/COMPLY-fail split) · `aki-challenger` (defined by what it is *not* given — the reasoning; always closes with *"what can be cut?"* and *"does this answer the anchored words?"*) · `aki-maker` (the only agent permitted to write, and therefore the most narrowly scoped).
273
+ - **Three properties stop being prose and become mechanism.** Read-only is `tools:` omitting Edit/Write, not a sentence a model can talk itself out of — `agent.A5` has demanded exactly this ("enforce read-only by mechanism, not by wording") and no prompt has ever guaranteed it. `model:` lives in the definition, so a tier is never improvised mid-run — the failure that made the owner cut a model tier by hand during a live session. And an undefined seat cannot be convened at all.
274
+ - **`aki-hands` additionally carries the cross-CLI substrate table** — Claude subagent · `agy` flash · `kiro-cli` · the `cl-9rt` proxy-gateway lane — with, per lane, when to pick it and **what context and rule files the caller must pass**, since only the in-harness lane reads the definition file at all. Its load-bearing clause is a prohibition: flags, model names, tiers, read-only mechanisms and known silent-failure modes are **recorded facts** in `skills/akiflow/references/harness-facts.md` and must be read there, never re-probed. A drifted session ran `agy --help` twice and `agy models` once to re-learn what it had already been told. Only two things stay legitimately probeable because they change per machine and per day: liveness/quota (a one-token call at the moment of assigning the lane) and whether `~/.claude-9rt` exists.
275
+ - `install.sh` copies `claude/agents/*.md` **file by file, never a directory mirror with `--delete`** — the same reasoning already written into `sync_aki_skills`: `~/.claude/agents/` is a shared namespace where the user's own agents live. Registered in `README.md` (a new "Five agent definitions" section, the layout tree, the installer diagram and step list, uninstall) and in `skills/akihelp/SKILL.md`, which now reads that directory as live state — a new deploy surface is the mechanism change this repo's `CLAUDE.md` says must reach akihelp's steps and not only the docs.
276
+ - **Guard stated because it is the obvious regression: a catalog is not a roster.** Five files on disk is the easiest possible slide back into picking seats from a menu, which is what caused the over-staffing in the first place. A seat is convened only when it traces to a requirement in the owner's own words.
277
+ - **Claude Code only, deliberately.** `SKILL.md` is a published open standard with five implementations; an agent-definition format has one. A vendor-neutral layer over a single consumer is the speculative generality `design.A2` forbids, and this repo's `CLAUDE.md` already defines `claude/` as Claude Code-only runtime assets. Pre-mortem: if `agy` ships an agent format later, the correction is one `git mv` plus a few lines in `install.sh` — a two-way door, where the opposite error leaves a permanent abstraction with one consumer. **Reopen trigger:** a second CLI publishing an agent-definition format.
278
+ - **The `[RULES]` receipt — the corpus can finally observe its own delivery** (decision record `docs/research/akiflow-drift-diagnosis-aug6.md`, plan `docs/plan/akiflow-reduction-agent-layer.md` Batch 1). The owner's framing was the sharp one: *"tôi không control chính xác các agent phạm lỗi đó đã được nạp rule tương ứng hay chưa"*. Two failures wear the same symptom and demand opposite fixes — **LOAD-fail** (the rule never entered the agent's context; the bug is in the delivery path) versus **COMPLY-fail** (the rule was there and was violated; the bug is in the rule text). The corpus had already paid for this blindness once: `core-floor-promotion-aug6.md` records `RULE-coding.md` and `RULE-design-core.md` being re-stated by the owner over several improvement rounds because they were **never loaded**, diagnosed only after multiple wrong fixes aimed at the compliance class.
279
+ - **Not a new mechanism — an existing one made honest.** `skills/akirule/SKILL.md` already emitted `[akirule] +RULE-docs.md`, and was designed to be silent in exactly the case that matters: *"Nothing loaded: no output needed"* made absence mean three different bugs at once (nothing needed / the router never ran / the agent ignored the instruction), and *"never list a core `@`-imported file"* made the most-violated rule group the one group whose presence was unobservable. Both clauses are deleted. The line now reports the whole rule context — `[RULES] agent,coding,design (core) + docs,ui (router) | missing: none` — and **is mandatory**, so that a later turn with no line carries exactly one meaning: the set is unchanged. Names are the existing topic addresses; no new vocabulary was introduced.
280
+ - **`agent.A5` gains the return leg.** The rule already said a worker inherits nothing and must be handed its exact rule files; it never asked what the worker actually received. Workers are precisely where the observed violations occurred, and a worker gets one round — so the receipt is its first line, with `(brief)` in place of `(router)`.
281
+ - **`agent.B2` gains "naming a rule is not complying with it."** Decomposing akiflow's 55-line thinking floor against the corpus found this clause was the only genuinely new *and* genuinely universal content in it — true of every agent in every session, yet living where only council seats would ever see it (`skills/akiflow/SKILL.md`). Compliance is stated as a checkable fact (`read-only: --tools Read,Grep`, `git mutations: none`), never as a citation.
282
+ - **Deliberately not built:** no new rule file, no penalty card, no script, no hook. The receipt is **self-reported — a diagnostic signal, never evidence** — so nothing gates on it; the cross-check that does carry weight is an agent definition's declared manifest against the line it emitted. Building enforcement on a self-report would recreate the compliance theater this work removes.
283
+ - **A proposed change was killed by measurement, and the rejection is the point.** "When does a rule load" is described in four places (`payload/index.md`, `skills/akirule/SKILL.md`, `install.sh`'s `AG_RULE_MAP`, `README.md`), and consolidating them into one manifest was drafted on `design.A1` grounds — then tested first: all 18 payload files present in all 4 sources, zero stale entries, **zero drift ever**. Machinery against a failure that has never occurred is the redundant guard this same work exists to remove. Reopens on the first observed drift.
284
+ - **Two new METHODs from testing the corpus against five real painpoints** (decision record `docs/research/proportionality-subtraction-aug6.md`). The owner ran verbose docs, unscientific doc naming, CSS sprawl, leaf-patching, and unmeasured over-defense through a full corpus load and asked how each is actually resolved. CSS sprawl and leaf-patching came back fully covered with real enforcement (`ui.C` playbook; `design.A8` + `design.B2` + `METHOD-flow-audit`). The last one was a genuine content gap, and it was structural rather than a missing keyword: **every use of "severity" in the corpus — `think.B5`, `ux.C1`, `docs.C4`, `ui.C2` — meant impact alone, never multiplied by who can actually reach the state.** `biz.A1` names the primary audience and `docs/biz/` is its SSoT, but nothing connected sizing a defense to that population, so the same question answered on two different days could get two different answers.
285
+ - **`METHOD-proportionality.md`** (topic `proportion`, Analytical) — four measures written down before any verdict: **reach** counted against the `docs/biz/` audience rather than an imagined internet, **capability** as a rung on a ladder from ordinary use through replaying requests to chaining an exploit, **motive** (abuse that converts to money or a scarce resource attracts scripts; abuse that only breaks the abuser's own screen attracts no one), and **blast radius** ordered by recoverability, with every number tagged measured or estimated (`agent.B2`). Verdict group: **irreversibility outranks frequency** (`proportion.B1`, same shape as `think.A1`), the `coding.C4` / `biz.C3` floor is never sizeable and a "cheap enough to skip" conclusion landing on it means the method was misused, and a cheapest-sufficient-control ladder — impossible by shape (`design.A8`) → enforced once at an existing trust boundary → detect and alert → accept and record. **A client-side limit is UX, never enforcement**: anything the browser computes the browser can change, so ship it for the honest majority but never count it as the control. Every verdict carries a **reopen trigger** — the observable that would make it wrong — because without one a deliberate "not now" is indistinguishable from an oversight a session later (same reason `docs.B2` requires "No action" to state its why).
286
+ - **`METHOD-subtraction-audit.md`** (topic `subtract`, Analytical) — the repo-wide counterpart nothing owned: `ui.C` covers frontend, `flow` covers one flow, `design.C1` covers one change, and `zero-trust` asks whether things are *right*, not whether they need to exist. It inherits zero-trust's scope-lock, detector-first order, CERTAIN/SUGGESTED classes and signature propagation unchanged, and changes only the question. Leads with the honest admission that **"as minimal as possible" is not a terminating condition** — no detector returns *minimal*, and a process promising an absolute floor either runs forever or fakes completion — so it terminates on **two consecutive rounds with no new findings** and reports the round count. Nine domain passes (reachability, abstraction below its evidence bar, guards, duplication, UI surface, dependencies, docs, content, operational leftovers) each delegate detectors to the rule that already owns them. Severity classes add a mandatory **load-bearing but ugly** class reported as *do not remove*, since a report listing only removals reads as though everything examined was removable. **Chesterton's Fence (`coding.B2`) is the brake**: a candidate whose reason cannot be found is SUGGESTED with the reason unknown, never a certain removal — aggressive minimization being the mirror image of over-engineering.
287
+ - **`risk-sizing` seated in akiflow** (`skills/akiflow/SKILL.md`, Step 5 domain consults). Re-reading that skill before building produced the second finding: **a METHOD file alone would not have been reusable in the council.** Judgment specialists there are standing domain consults with closure authority — an item touching the domain closes only after a recorded turn, and "nobody asked UX" is a closure defect — so a file with no seat is a file the room may consult and therefore forgets. The seat is deliberately opposed to Red Team's standing subtraction pass: Red Team argues everything down, `risk-sizing` is the only seat that may argue a control back up (on `proportion.B1`) and the only one that may refuse a cut; neither may touch the security floor. Symmetrically, the subtraction audit is registered in audit mode as the one audit whose **sweeps do not belong in the room at all** (the skill's own bulk-mechanical-work law) — scanning routes to read-only workers or the owner-invoked `Workflow` tool, and the council enters only at classification, because *dead* versus *load-bearing but ugly* is the judgment the owner acts on.
288
+ - Registered in `payload/index.md` (manifest, group map, a new **Sizing a control against its real threat** lens row rooted at `proportion.A`, plus `subtract` added to the audit-read-only and subtraction-before-abstraction rows), `skills/akirule/SKILL.md` (two Tier 1 signal blocks), `skills/akihelp/SKILL.md` (two painpoint rows), `README.md`, and `install.sh`'s `AG_RULE_MAP`. Pointers only, no duplicated text: `think.B5` now hands sizing off once an edge-case is promoted, and `coding.C1` points at the sizing lens for guards on reachable states.
289
+ - Deliberately not done, with reasons on record: **no `[FLUFF]` detector and no doc-reduction playbook** for the two documentation painpoints — density is content judgment (unchanged from `penalty-cards-scythe-aug4.md`), and a doc-shaped `ui.C` would tax every session for a pain never measured the way the 30,026 lines of CSS were; **no name-quality row in `docs.C3`**, since a name-versus-content comparison is judgment and the audit's other rows are all mechanical; no new penalty card, no change to the always-loaded core floor.
290
+ - **New METHOD: `METHOD-zero-trust-audit.md`** — a strict sweep driven by detectors rather than impression (decision record `docs/research/zero-trust-audit-aug6.md`). Its load-bearing rule is that **a finding weighs exactly what the mechanism that produced it weighs**: an exact machine match (selector defined twice, unimported export, type error, hex outside the token source, hard-wrapped comment) is a `CERTAIN` verdict carrying `path:line` and its producing command and may be counted; a pattern, shape or naming signal is `SUGGESTED` only — the script locates it, judgment rules on it, and it never becomes a verdict, never enters a violations total, never carries an imperative. Detector silence is never evidence of cleanliness for what the detector cannot see. Scope is locked by command before the first read and declared in one line — *project-wide*, or *change-related* defined as the diff **union its callers**, since a change scope without the callers is a diff and the defect usually lands in the untouched file. Detectors run before any opinion and only if the project actually has them (no invented typecheck, no build, no dev server), with raw output attached *before* a conclusion — a tool run afterwards to confirm an already-stated conclusion is not verification. Plus signature propagation (one confirmed instance → grep that shape across the locked scope, report the count even at zero), an adversarial self-challenge pass, and a findings-only report with a one-line coverage statement instead of a row per file. **Read-only like every audit** (`agent.B5`) — no edits, no git mutation, fixing is a separate run. Registered in `payload/index.md` (manifest, group map, and the `agent.B5` cross-cutting lens row), `skills/akirule/SKILL.md`, `README.md`, and the Antigravity rule map in `install.sh`.
291
+ - An earlier draft of this file was a **fix-in-place** procedure and was rebuilt before commit; the review is on record. It weakened core `agent.B5`, mandated mass renames without the `agent.B3` gate, pointed at `/akirule` (a skill name, not a path) as its rule source, ran `scythe.sh`/`tsc` unconditionally, and closed with a "remember this, do not make mistakes" clause carrying no mechanism — the reminder-tier-fix-for-enforcement-tier-failure pattern already recorded in `akiflow-compliance-enforcement-aug3.md`.
292
+ - **Fixed:** the Antigravity rule-file count was stated as 15 in three places (`README.md` installer diagram and step 8, `docs/arch/rule-delivery-architecture.md` diagram) while `install.sh`'s `AG_RULE_MAP` now renders 18 — the three new METHODs were registered in the generator but the number describing its output was never re-counted. A count is the one claim in a doc that goes stale silently, since nothing reads it.
293
+ - **Fixed:** a stray blank line above the **Subtraction before abstraction** row broke the Cross-cutting lens table in `payload/index.md` — Markdown read the row as the header of a second table, dropping the Root and Domain-applications columns. The `RULE-ui-pattern.md` entry in `install.sh`'s `AG_RULE_MAP` (the Antigravity rule generator) was also still describing the pre-subtraction-pass version of the file.
294
+ - **`/akihelp` gains a painpoint → what-to-say table.** A capability list tells the reader what exists; it does not tell them which words to type when a specific problem is actually in front of them, which is the gap people hit. Twelve rows keyed on the *situation* rather than the tool — sprawling CSS, docs drifted from code, a long half-finished working tree, a pre-ship readiness check, a big hard-to-reverse decision, padded or hard-wrapped output, work needing several kinds of judgment at once, a path accumulating guards, UX friction distinct from visual styling, a pricing/positioning call, an analysis too dense for chat, and not knowing whether a rule loaded at all. The skill's no-stale contract is preserved and extended: rows are built from the live state read in its own steps 1–2, and **any row whose skill or rule file is not installed must be dropped rather than rendered**, since a row pointing at something absent is worse than a missing row. New closing step states the caveat that governs every other line of the output — `akirule` is a skill and therefore best-effort, so a prompt that must load deterministically names the rule file instead of trusting a signal to fire. Example prompts are to be translated into the user's language, never pasted verbatim in English.
295
+ - **UI pattern rules made subtractive and observable** (decision record `docs/research/ui-css-minimization-aug4.md`; measured against tachnhac.com, akitao.com, kinhdich.akinet.me, tuvi.akinet.me). The owner reported heavy CSS sprawl despite `akirule` being active; measurement found **30,026 lines of hand-written CSS inside SFC `<style>` blocks — 2.7× to 17.7× the shared stylesheet** in projects whose rule file states hand-written CSS is "the last resort, never the first reflex". Routing was never the cause: `RULE-ui-pattern.md` already loads on file extension alone. The defects were structural, and every fix landed at an existing address — nothing renumbered:
296
+ - **`ui.A1` gains a subtraction pass before any tier** — delete → inherit → hoist. Every rung of the taxonomy *packages* repetition and none removes it, so the cheapest outcome (the style need not exist) was unreachable by construction; `text-sm leading-relaxed` repeated 116× is inheritable typography that belongs once on a container. The Map section had listed design-core Laws 1/2/4/5/7 and omitted **Law 8**, so the file never inherited the corpus's own subtraction discipline (`think.B4`, `design.B3`, akiflow's Red Team pass). Mandatory order is now `subtraction → Utility → Pattern class → Component variant → hand-written CSS`.
297
+ - **Rule of Three given an observer** — `ui.A1` had kept `design.A2`'s ≥3 threshold while dropping `design.A5`'s second-paste STOP. That threshold is a *repo-wide* count no single editing session can observe, so the prohibiting half ("never pre-extract") was trivially enforceable while the enabling half could never fire: `components/base/` = 0 across all four projects against 2,447 duplicate class-string occurrences in akitao alone. Now the second copy is the STOP and the third remains only the extraction threshold — "leave both inline" stays legitimate, but as a decision rather than a default.
298
+ - **Inline `style=` classified** — the taxonomy asserted "there is no fifth tier" while listing tiers 0–4, none of which was inline style, leaving it neither permitted nor forbidden (870 instances in akitao.com). It is now a runtime-computed escape hatch only; static inline styles are always violations, invisible to every `ui.C1` scan and unable to carry a token.
299
+ - **`<style>` budget made a quantity claim** — inversion of the mandatory order is an *aggregate* property and no individual file looks unreasonable, which is why a loaded rule never caught it. `ui.A1` now measures the bespoke layer against the shared one, with legitimate residents enumerated (keyframes, `:has()`/`::-webkit-scrollbar`/print, third-party overrides, unauthored CMS markup) so the rule is strict without being unfollowable.
300
+ - **`ui.A2` corrected for Tailwind v4** — it mandated "a token in `tailwind.config` + a CSS variable" while all four projects run **Tailwind 4.3.3** CSS-first `@theme`. A rule naming a mechanism the stack no longer uses teaches the reader the rule is decorative. Token mechanism is now version-aware, plus **one theme source per project** as token-layer SSoT (kinhdich carries 4 separate `@theme` files).
301
+ - **`ui.B4` made two-way, lookup first** — the duty to *record* a new pattern existed; the duty to *look one up* did not. Result: `.detail-label` defined 2–3× per project and byte-identically across projects, and akitao redefining **43% of all its selectors** (117 of 274). A shared name with two live definitions is strictly worse than raw duplication — it promises a consistency it does not deliver, and load order decides the winner invisibly.
302
+ - **`ui.C1` led by the inversion check**, plus a redefined-selector scan and two stated blind spots: `:class` bindings are invisible to the greps so duplicate counts are floors, and absence of `@apply` never implies absence of Tier 2 — the exact error this session's own first measurement made before correction (pattern classes and `@theme` tokens do exist in all four projects, written as plain CSS).
303
+ - **`design.B3` gains a first critique-gate bullet, "subtract before you share"** — the existing three all silently assume the duplicated code must exist. New `payload/index.md` Cross-cutting lens row (**Subtraction before abstraction**, root `think.B4`), rewritten `ui` manifest row, and a minimization keyword set (`tối giản`, `giảm CSS`, `CSS rác`, `style block`, `inline style`, `@theme`, …) added to the `RULE-ui-pattern.md` audit signals in `skills/akirule/SKILL.md`.
304
+ - Deliberately not done, recorded with reasons: no audit playbook in `RULE-design-core.md` (default ON for backend/Tauri/CLI — a UI-shaped section would tax every non-UI session for what `ui.C` already covers); no `PostToolUse` hook (twice owner-rejected, and independently wrong here — a hook sees one file while the defect is only visible in aggregate, and would fire on 2,507 pre-existing violations in akitao at every edit); no new penalty card in the always-loaded core floor; no new detector script (`scythe.sh` cards have one correct answer, these findings need a judgment call).
305
+ - **Penalty cards + the scythe: a shared violation vocabulary and its mechanical detector** (decision record `docs/research/penalty-cards-scythe-aug4.md`; the owner's severity-restructure proposal researched and reshaped). The owner proposed renumbering `RULE-agent-behavior.md` by severity so violations could be called by short codes; research rejected the renumber (66 address cross-references across 16 files, D3 precedent in `public-private-abc-restructure.md`, and the aug3 root finding that reordering prose is a reminder-tier fix for an enforcement-tier failure) and shipped the same UX win without address churn:
306
+ - **`RULE-agent-behavior.md` §0 Penalty cards** — three named tokens, `[WRAP]` (hard-wrapped logical line → root `C3`), `[FLUFF]` (padded output failing the deletion test → root `A4`), `[YAP]` (comment narrating WHAT/restating code → root `coding.B4`). Semantic names beat numbers: bare "A1" is ambiguous (every file has an A1), a name self-decodes without the mapping loaded, and the same token now runs through owner corrections, lint output, and enforcer REMINDs. Being called with a card = re-read the root, fix every instance, reply with the fix. All existing addresses unchanged.
307
+ - **New script `skills/akiflow/scripts/scythe.sh`** — deterministic grep/awk lint for the two mechanically detectable cards: `[WRAP]` as consecutive lowercase-continuation comments in code and mid-sentence line breaks in markdown prose (frontmatter, fences, tables, lists, lettered sub-lists, `→`-ended layout lines, leading file headers, docblocks, and directives all exempt); `[YAP]` as ≥3-line comment blocks or >200-char comment lines, always labeled *(review)* — the owner's proposed 150-char verdict threshold was rejected as self-contradicting `agent.C3` (a legitimate long WHY may not be wrapped, so length alone convicts nothing). `[FLUFF]` is deliberately out of scope: density is content judgment, no script claims it. Verified against fixtures (7/7 expected findings, 0 false positives after three heuristic fixes) and against the live corpus, where it immediately caught 8 real hard-wrapped lines in `harness-facts.md` (fixed in this pass).
308
+ - **New skill `skills/akilint/SKILL.md`** (`/akilint`, user-invocable) — thin wrapper over scythe: report findings verbatim, fix `[WRAP]` mechanically (honoring C3's atomic-line cautions), judge each `[YAP]` against `coding.B4` before touching it, name false positives instead of silently skipping. Deliberately named *lint*, not *audit* — `audit` is a defined corpus term (`agent.B5`, `docs.C`) with read-only construction and a research+plan output contract this is not.
309
+ - **akiflow `akirule-enforcer` gets deterministic hands** (Step 5): scythe replaces the agy flash sweep for the wrap/comment evidence classes — a grep cannot fabricate, which is exactly the property evidence needs given the recorded gemini fabrication caveat; flash/haiku hands remain for the non-regex classes (trailers, temp files, missing tags, oversize turns, roster-line defects, attestations).
310
+ - **`coding.B4` gains the comment-rot axiom** — no compiler checks a comment, so it drifts silently as code changes and a stale comment misleads worse than none; one more reason deletion is the default and current-truth rationale lives in a referenced doc (`docs.B3`). B4 address unchanged. The owner's other two proposed relocations were found already shipped: the density/wrap roots already live in `agent.A4`/`agent.C3` with `docs.B3` already pointing at them (aug3 Cross-cutting lens work).
311
+ - Not re-proposed: a PostToolUse hook (owner rejected it aug3; the aug3 rejection reason — "density is content understanding" — does not cover a wrap-only mechanical hook, recorded as the one condition under which the question reopens, at the owner's initiative only).
312
+ - **akiflow: compliance enforced by evidence and gates, not citation** (decision record `docs/research/akiflow-compliance-enforcement-aug3.md`, driven by two 2026-08-03 debug sessions the owner supplied). The diagnosis: rules were loaded, quoted by address, and violated in the same file (citation-as-ritual); a declared Red Team posted zero turns while items closed citing it as challenger (declared-but-never-ran); and a prose-worded git ban let a subagent `git stash` away three siblings' in-flight work (prose-worded mechanism). A hand-staffed free-form rule-police seat in one of those runs was the *worst* compliance performer in the room — which is why the fix is not another police agent:
313
+ - **New standing seat `akirule-enforcer`** (`skills/akiflow/SKILL.md` Steps 1/5): reminder-only — its entire output is `REMIND-<n> → <agent> · <rule address> · <quoted file:line evidence> · <expected behavior>` turns; evidence gathered by its own flash-tier hands (agy one-shot, haiku fallback) over greppable rule classes only (hard-wrap, comment budget, credit trailers, scratchpad hygiene, missing tags, oversize turns, undeclared cost dials, missing attestations); conduct never content; no evidence, no reminder. Teeth live in the gate: the target answers `ACK REMIND-<n>` + fix, or the lead posts a logged `OVERRULE`.
314
+ - **New script `skills/akiflow/scripts/council-verify.sh`** — mechanical closure gate run before items close and again before the Step 9 tally: ghost seats (declared owner/challenger with zero posted turns), enforcer presence, per-agent FACT/CONSTRAINT/ASSUMPTION counts, unanswered REMINDs. Proves presence, never quality; a FAIL blocks closure. Verified live against the debug session's artifacts: it flags the ghost Red Team and the zero-tag agents that run's lead missed.
315
+ - **Thinking-floor clause 6, NO SELF-ATTESTATION** (Step 4): compliance is stated as checkable fact ("git mutations: none — no add/stash/checkout/reset run"), never as rule-address allegiance; every audit report ends with a per-verb attestation line (audit-mode addition). Anti-patterns #19 (ghost roster seat) and #20 (self-attestation as compliance) added; `docs/arch/akiflow.md` gains a § Compliance section recording the reasoning.
316
+ - **Read-only seats must name their mechanism on the roster line** (Step 1): `ro:--tools …` / `--mode plan` / `--trust-tools=` — a read-only seat with no mechanism named is a roster defect to fix before spawning.
317
+ - **Fact correction — the in-session Agent tool has no `effort` parameter** (verified 2026-08-03 against the live tool schema; a real session's gate line declared per-seat effort while every spawn carried none). `harness-facts.md` corrected; Step 1/Step 2 now have in-session seats declare `model` alone and headless calls carry `--effort` — the previous both-dials-on-every-spawn rule was unfollowable in-session, and an unfollowable rule teaches the declaration line to be decorative. Owner-declined in this pass, recorded in the research doc: a general correction-response rule, a UserPromptSubmit hook forcing akirule invocation, and any investigation of core-floor loss after `/compact`.
318
+ - **Density made checkable across the corpus (2026-08-03 `/akithink` session; decision record `docs/research/akirule-akiflow-upgrade-aug3.md`, plan `docs/plan/done/density-roster-upgrade.md`).** The owner's chronic pains — over-long comments, docs, and UI content; hard-wrapped output; structural work patching instead of reshaping — were diagnosed as enforcement-tier failures, not missing rules: "keep content concise" is an adjective, the form the corpus itself proves unenforceable. The deletion test (a line ships only if removing it loses information the reader needs) already existed for chat reports as `agent.A4`; it is now the root of a new Cross-cutting lens row in `payload/index.md` with domain applications: new **`coding.B4`** (self-documenting code: naming and shape first, a comment states only what the code cannot say, one-line budget, rationale lives in docs per `docs.B3`), **`content.B2`** rewritten around the deletion test + first-sentence-carries-the-point, and a density bullet at the top of **`docs.B3`** (conclusion first, no narrative filler, never pad and never trim load-bearing detail). Kept out of the core floor at the owner's explicit decision; a PostToolUse lint hook was likewise rejected (density is content understanding, not mechanical format).
319
+ - **akiflow: five structural upgrades from the same session** (`skills/akiflow/SKILL.md`):
320
+ - **Context is a named mode per worker** (Step 2 preamble): BLANK / INHERIT-BY-ARTIFACT / OWN-ACCUMULATING — consolidates what existed scattered across the mechanism table into one declaration every spawn must make.
321
+ - **Thinking-floor clause 5, OUTPUT HYGIENE** (Step 4): never hard-wrap, every file-level claim cites file:line, comments only for what code cannot say, deletion test on every line. This is the enforcement tier that actually reaches subagents, which inherit no router — the wrapline/verbosity fix lands here rather than in more routed prose.
322
+ - **Red Team's second standing assignment: the subtraction pass** (Step 5): over-engineering is the council's own occupational disease — before any solution-shaped item closes, attack what can be deleted, merged, deferred, or made manual (`METHOD-deep-think.md` B4, `RULE-design-core.md` B3, `design.A8`); matching closure requirement in Step 6 — the rationale names what was cut and why this is the smallest shape, which also absorbs the victory-audit question ("did this achieve what was asked").
323
+ - **Verification gains the drift sweep** (Step 7, including the Tier 0 verifier): enumerate docs, code comments, i18n strings, and CHANGELOG lines referencing the changed behavior; report any still describing the old one. The owner's recurring drift pain handled as a mechanical verifier lens, not a standing agent.
324
+ - **Writer role split from the implementer** (Step 7): user-facing prose goes to the softest capable writing tier — `[owner]` fact: agy `gemini-3.1-pro` writes noticeably softer than Sonnet-class implementers — under an anti-fabrication brief: it phrases only facts supplied in its prompt and tags anything else ASSUMPTION.
325
+
326
+ ### Changed
327
+ - **`RULE-design-core.md` promoted to default ON with `RULE-coding.md`** (`skills/akirule/SKILL.md`): it previously loaded only when a design keyword was named explicitly, which is exactly when structural work ran without the forest view and patched instead of reshaping. Skip only for trivial value-level edits. `payload/index.md` tier column and `README.md` Tier-1 line updated.
328
+ - **9router generalized to "Claude via a proxy gateway", two facts corrected** (`harness-facts.md` § claude via a proxy gateway; `SKILL.md` worker-shapes row + probe line): the lane is a parallel explore/bandwidth seat whose gateway may route an alias to a non-Anthropic core (`[owner]`: the owner's "Sn" alias is a deepseek-v4-pro-class model), so the earlier "same Claude-family model" framing is dropped — it is not a second lead seat, and judgment stays with the lead. Auth there is the gateway's API key, so `--bare` — unusable on the OAuth main login — works on this lane; `--bare --tools "Read,Grep,Bash"` recorded as its minimal fresh-context worker shape. The `test -d ~/.claude-9rt` probe stays; where the dir is absent the rule now says to recommend the one-time setup (CONFIG_DIR + gateway endpoint — every machine benefits from the lane) instead of silently substituting another mechanism.
329
+ - **`skills/akiflow/references/harness-facts.md` — Kiro CLI upgraded from `[owner]` to `[obs]`**, verified 2026-08-02 via `kiro-cli --help-all`, `kiro-cli chat --help`, and `kiro-cli chat --list-models`. Verified flags: `--no-interactive`, `--trust-tools=`, `--require-mcp-startup` (exit 3), `--effort`, `--model`, `--resume-id`, `-r`, `--resume-picker`, `--agent-engine v1|v2|v3`, `--mode default|spec` (v3), `--list-sessions`, `--delete-session`, `-f/--format`. Verified model list (with credit multipliers): `auto` (1×), `claude-sonnet-4.5` (1.3×), `claude-sonnet-4` (1.3×), `claude-haiku-4.5` (0.4×), `deepseek-3.2` (0.25×), `minimax-m2.5` (0.25×), `minimax-m2.1` (0.15×), `glm-5` (0.5×), `qwen3-coder-next` (0.05×, 256k). Also corrected: `--wrap` takes `-w` short flag; `--trust-tools` restricts to named set (not just restrict/allow-all); removed the unverified \"piped stdin\" claim. `docs/research/headless-cli-workers-aug1.md` R9 updated from unverified to verified accordingly.
330
+ - **`harness-facts.md` `--effort` row** — added note that on the `claude` CLI specifically, `--effort` has no effect with haiku-class models (haiku does not support extended thinking at the API level; the flag is silently ignored). Clarified that on `agy` and `kiro-cli`, effort behavior follows the model chosen on those CLIs.
331
+ - **`--bare` (R6) superseded by `--disallowedTools "Workflow DesignSync"` as the recommended Claude-side tool/context cut** — verified 2026-08-03 against official docs (`Workflow` is the native multi-step orchestrator; `DesignSync` is the `/design-sync` claude.ai/design bridge) and against this repo (`skills/akiflow/` never calls either), so disallowing both costs akiflow nothing while staying OAuth-compatible, unlike `--bare`. `docs/research/headless-cli-workers-aug1.md` R12 added; `harness-facts.md` Claude Code flag table gets the new row.
332
+ - **9router reframed from quota-exhaustion fallback to a parallel Claude lane** — a `CLAUDE_CONFIG_DIR=~/.claude-9rt` account is a separate quota on the same Claude-family model, so it can run concurrently with the lead's own session, not only after the primary account runs dry. Gated on `test -d ~/.claude-9rt` (owner-provisioned, not default) before any rule proposes it. `SKILL.md` gains a fifth worker shape and a probe-gate line; `harness-facts.md` § claude via 9router expanded.
333
+
334
+ ### Added
335
+ - **`skills/akiflow/SKILL.md` — CLI availability and quota check** required before building the roster. A minimal probe call (`-p "ok"` / `--no-interactive "ok"`) must be run for each headless CLI planned for use, result reported to owner, and any unavailable CLI explicitly named before falling back — no silent substitution. Placed between audit mode and Step 2.
336
+
337
+
338
+ - **akirule sensitivity raised: a file extension alone is now a sufficient signal.** The Tier 1 triggers were written as keyword-plus-context lists, which in practice made a rule wait for project maturity that has nothing to do with whether the rule applies — editing a `.md` did not load `RULE-docs.md` unless the message also mentioned docs or the project already had a `docs/` tree. New clause at the top of Tier 1 states that extension match alone fires, and that keywords/actions are additional entry points rather than a required second condition. Per-rule paths widened accordingly: `RULE-docs.md` now fires on **any `.md` anywhere** (plus `*.mdx`, `SKILL.md`, `CHANGELOG.md`); `RULE-ui-pattern.md` on any `.vue`/`.css`/`.scss`/`.tsx`; `RULE-stack-tauri.md` on any `.rs`; `RULE-db-design.md` on any `.sql`; `RULE-content-write.md` on any file where a user-visible string is added or renamed.
339
+ - **Stateful headless workers measured — the two CLIs offer the same feature and behave oppositely, which changes akiflow's continuity story.** Controlled 3-turn test, 2026-08-01 (store a token, recall it, send a trivial turn); both `agy --conversation <id>` and `claude -p --session-id <uuid>` recalled correctly, so both *functionally* resume. Economically they are not comparable, and the earlier claim in `harness-facts.md` that agy repeat calls "hit a warm prompt cache" is corrected as too generous:
340
+ - **`claude -p --session-id` is cheap and flat.** Turn 1 $0.0358; turn 2 **$0.0043** (~⅛, 34.4k cache-read, 219 new); turn 3 $0.0038. It is **cwd-scoped** — the same id resumes from the directory it was created in and fails with `No conversation found` (exit 5) elsewhere, which is a safety property, not a limitation.
341
+ - **agy conversations are a trap.** Input grows every turn (26.5k → 53.6k → 56.4k), `cache_read_tokens` was **0** on turn 2, and latency ran 2.6s → 8.8s → **57.6s** to answer "reply ok". Correct behavior, unusable curve.
342
+ - **Consequence for akiflow** (`SKILL.md` Step 2): two new mechanism rows — a **persistent worker** (`--session-id` / `--resume`) for anything called repeatedly, and **wide one-shot discovery** on `agy --model gemini-3.6-flash-medium`. The continuity row now points at the persistent worker where the same worker will be re-addressed, keeping the plan doc as the carrier of the *decision* rather than of the worker's working state. The long-standing "no mechanism inherits session context" paragraph is sharpened rather than dropped: nothing inherits *the lead's* context, but a persistent worker accumulates its own — so briefing it once well is what makes it cheap, and assuming it knows the run is what makes it wrong. New rule: "cheap" and "stateful" are different mechanisms and a run must say which it means, or it pays full price on both.
343
+ - **agy model policy, part `[owner]`-supplied:** `gemini-3.6-flash-medium` is the default discovery tier (~1M context, fastest available, generous quota); its weakness is carelessness rather than capacity, so the counter is prompt precision, not a bigger model. agy's `claude-sonnet-4-6` / `claude-opus-4-6-thinking` are quota-scarce even on a paid plan and sit on the no-cache curve — reserved for a single high-value shot with context and cache demonstrably under control, never a conversation, never a habit.
344
+ - **`RULE-agent-behavior.md` A2 rewritten around the actual economics of a turn**, prompted by three habits the owner reports having to correct repeatedly: doing menial work personally, editing line by line as sites are discovered, and shelling out to `cat`/`sed` to read a file that `Read` returns directly. The previous bullets stated all three as preferences and did not say *why*, which is why they did not bind. They now hang off one fact — **every tool call re-sends the entire conversation, so cost follows round-trip count, not per-call size** — from which the three rules follow as consequences rather than as style: read with `Read`/`Edit` and reserve Bash for what it is uniquely good at; locate every edit site before touching any, and if they are not all known yet that is a signal to search rather than to start editing; batch independent calls into one turn. A fourth bullet makes the menial-work rule explicit outside akiflow: main-thread context is the one resource a task cannot recover, "doing it directly is faster" is true per-step and false per-task, and the caller reads at orientation depth only.
345
+ - **`RULE-agent-behavior.md` new A5 — worker delegation economics, generalized out of the akiflow research into a rule that applies to every task.** The corpus already said *delegate exploration to a cheap readonly subagent*; it never said how to brief or price one, so the same three mistakes recurred outside akiflow: spawning without `model`/`effort` and silently inheriting the caller's top tier, banning writes in prose rather than by mechanism, and pulling raw search output back into the caller's context — which is the exact cost the delegation existed to avoid. A5 states the worker shape (subagent **or** headless CLI call, same rules either way) and seven clauses: a worker inherits nothing so name its rule files and targets explicitly; set both cost dials, since an omitted one inherits rather than defaults cheap; enforce read-only by restricting the tool set or using the CLI's plan mode, never by wording; use the structured-output flag when a program will parse the result; ask for the conclusion, not the dump; judgment never delegates downward to a cheap tier; and spend crossing a process or CLI boundary is invisible to the caller's own accounting. Kept deliberately compact — this file is now hard-imported into every session, so its token cost is paid unconditionally. `payload/index.md` manifest row updated; the A2 exploration bullet now points at A5 instead of restating it.
346
+ - **akiflow: headless cost levers measured across `claude`/`agy`/`kiro-cli`, and the native `Workflow` tool evaluated and rejected.** Full narrative, measurements, and decisions in a new research doc, `docs/research/headless-cli-workers-aug1.md` (registered in `docs/index.md`); fact rows in `skills/akiflow/references/harness-facts.md` § Headless, all carrying the 2026-08-01 check date since every one of them is version-bound.
347
+ - **`Workflow` rejected.** A workflow agent has no `SendMessage`, so it cannot reach the live Phase A roster — hosting Phase B inside one would sever Step 8's loop-back. The two features that made it tempting turned out to be ordinary headless flags on both CLIs (`--max-budget-usd`, `--json-schema`), leaving only crash-resume as a genuine, accepted loss. Against that: a Claude-Code-only branch, unable to self-invoke, dormant unless the owner opts in per task, in a repo that ships to five CLIs. **The strongest surviving argument *for* adoption is recorded rather than discarded** (a 200-file mechanical sweep keeps its loop in JS, outside any model's context), together with the two conditions that would re-open the question — crash-resume becoming load-bearing, or Workflow gaining agent-to-agent messaging. New `docs/arch/akiflow.md` § Why the native `Workflow` tool was rejected.
348
+ - **Four of Workflow's design lessons adopted without the tool** (`SKILL.md` Step 7, "Four scheduling laws"), since they are prose and portable to every CLI: do not stall the roster on its slowest member when the next stage does not need every result together; a truncated scope must be stated, never silently applied; unknown-size discovery loops until two consecutive rounds surface nothing new rather than stopping at a fixed count; adversarial verifiers get distinct lenses instead of the same question repeated.
349
+ - **The findings applied as mechanisms, not just filed.** `SKILL.md` Step 2 gains two mechanism rows and a worker-shape table: `claude -p --tools "Read,Grep,Glob"` as the Claude-side read-only-by-mechanism sweep (the Agent tool cannot restrict a spawn's tool set, so an in-session subagent's read-only is prompt wording it can talk itself out of), and `--json-schema` on either headless form when a program will parse the result. The table names the three worker shapes (in-session subagent / Claude headless / cross-CLI headless) with the cost levers each one accepts, states that cheapness has two axes — model tier *and* thinking effort, cut both — and adds the third axis the design lacked: which vendor pays, since `agy` reaches `claude-sonnet-4-6` and `claude-opus-4-6-thinking` on the Antigravity quota. The skill names shapes rather than the owner's shell aliases, because an alias that exists on one machine does not exist on the next. Audit mode now *prefers* a mechanically read-only sweep over a well-worded one, since an audit that edits produces an unreviewed refactor nothing downstream catches. Step 9's blind-spot note widened from cross-CLI to **both** headless shapes — a `claude -p` call writes its own separate transcript, so `council-cost.sh` misses it exactly as it misses `agy`.
350
+ - **New gate law #6 — bulk mechanical work is not a council** (`SKILL.md` Step 1). Large-but-judgment-free work has nothing for a roster to arbitrate and makes the lead's context grow with the item count; route it to a cross-CLI worker or tell the owner that `Workflow` fits better. Carries the boundary the rejection rests on: nothing that can reopen a work item may run inside a workflow.
351
+ - **New `[owner]` provenance marker** in `harness-facts.md`, below `[doc]` and `[obs]`: supplied by the owner from a machine this repo has never run on, unverifiable here, and never allowed to carry a rule without a verification step attached. Introduced for the Kiro CLI facts (`--no-interactive`, `--trust-tools=` as mechanism-enforced scope, `--require-mcp-startup` exit 3, a model table down to ×0.05 with 256k context, `kiro_planner`/`kiro_help`, `--agent-engine v3`, and `kiro-cli acp` exposing an Agent Client Protocol server) — recorded because if accurate it is both the cheapest tier in the stack and the only machine-protocol surface, which is exactly why it must not be trusted unverified. `kiro`/`codex`/`grok` are **not installed** on this machine; their skill directories exist only because `install.sh` creates them.
352
+ - **Claude-side facts, all live-verified:** `--tools "Read,Grep"` is the missing Claude-side equivalent of agy's `--mode plan` (read-only by mechanism, not by prompt wording); `--bare` is the largest available input-token cut **but refuses OAuth** — a live call returned `is_error: true` with zero tokens on this machine, so no rule may depend on it; `--exclude-dynamic-system-prompt-sections`, `--agents <json>`, `--effort`, `--permission-mode plan`, `--no-session-persistence`, `--fallback-model` recorded as per-call levers. And from `agy models`: `claude-sonnet-4-6` and `claude-opus-4-6-thinking` are reachable **on the Antigravity quota**, making "which vendor pays" an axis independent of "which model reasons".
353
+ - **A retraction.** An earlier step of this investigation asserted that `Bash(agy *)` was missing from `~/.claude/settings.json` and that every cross-CLI call would therefore hang on a permission prompt. A live call ran clean in 2.5s with no prompt. The claim was wrong and is retracted in the research doc rather than quietly dropped.
354
+ - `SKILL.md` Step 7's implement row no longer says "no context-inheriting subagent exists" — the last place still carrying the pre-correction absolute framing after the fork fact was fixed.
355
+ - **akiflow: harness facts re-verified on 2026-08-01 against Claude Code 2.1.220 and the `agy` binary directly, correcting two wrong claims and adding a fifth mechanism.** Prompted by a fresh round of binary/runtime inspection that overturned two prior "confirmed" facts and found a working cross-CLI path this skill had no rule for. Updated `skills/akiflow/references/harness-facts.md`, `skills/akiflow/SKILL.md`, `docs/arch/akiflow.md`, and `README.md`'s akiflow row:
356
+ - **Fork corrected, not deleted.** The prior row stated flatly that no `subagent_type: fork` value exists, based on a 2026-07-30 failed spawn and the public docs at the time. The `claude` binary itself now contains a real (if undocumented) fork agent type — telemetry field `is_fork`, fork-specific error strings, and the Agent tool's own `model` parameter documents it inherits the parent model. It is gated behind `CLAUDE_CODE_FORK_SUBAGENT=1` and absent from the default agent list, so the design consequence is unchanged (continuity still travels by explicit plan-doc/diff handoff), but the *reason* changes from "does not exist" to "gated off, and not a cross-session artifact even where enabled" — the plan doc is what survives *between* sessions, which an in-session fork never does. Two knock-on absolute statements elsewhere in `SKILL.md` ("no `subagent_type` inherits session history", "No mechanism inherits session context") were softened to match, since they were technically false once fork's existence is acknowledged, even though fork remains unusable in practice.
357
+ - **AGY does have a subagent mechanism — the opposite of what the skill said.** The `agy` binary contains `enable-teamwork-subagent`, custom Markdown agents with model-tier frontmatter, and a built-in **fixed-roster** council, `/teamwork-preview` (`orchestrator_pure`, `explorer`, `spec_miner`, `armed_worker`, `armed_critic`, `empirical_challenger`, `forensic_auditor`, `reviewer_critic`, `sentinel`, `test_writer`, `victory_auditor`, `challenger`). `SKILL.md`'s Harness notes bullet claiming "no subagent mechanism" is rewritten. Two things follow, recorded in a new `docs/arch/akiflow.md` § Convergent validation section: an independently built council landed on nearly the same role split including a *pure* orchestrator, which corroborates akiflow's "the lead does no menial work" design; and akiflow has no **victory audit** role ("did this achieve the goal that was asked for?", distinct from verification and adversarial review) — noted conceptually in `SKILL.md` Step 6 and the arch doc, deliberately not designed into Step 7's mechanism table since that table and the Phase A/B boundary are under separate active discussion.
358
+ - **New mechanism: a cross-CLI worker** (`SKILL.md` Step 2 new table row, new `harness-facts.md` § Cross-CLI worker, new `docs/arch/akiflow.md` § A second axis: which vendor pays). A Claude Code lead can call `agy --model gemini-3.6-flash-low --mode plan --output-format json -p "<prompt>"` (prompt must come last — `-p` takes its value from the next token) for read-only, bandwidth-shaped sweeps. `--mode plan` enforces read-only by mechanism, stronger than a Claude subagent's inherited permission mode; `~/.gemini/GEMINI.md` loads the akirule behavior floor into the call for free; `cwd` is not a reliable scope boundary so paths must be named explicitly; a denied call still returns `status: "SUCCESS"` with `response: ""`, so an empty response must be read as a failed call, never a clean sweep (new anti-pattern #16). Measured live: 8.2s wall / 3.4s model time on a real sweep, ~20–26k tokens fixed overhead per call, a warm prompt cache on repeat calls (`cache_read_tokens: 32621`). Hard rule riding with the mechanism (new anti-pattern #17): a flash-tier worker is for retrieval only, never judgment — mislabelling FACT/CONSTRAINT/ASSUMPTION is the skill's own "one unrecoverable error", and a cheap model does it worst. The activation gate's third condition (cost of error vs. cost of coordination) gets cheaper on the coordination side wherever a sweep can move off the Claude quota entirely, so more work qualifies for the council — the judgment ban is the fixed counterweight, not an optional one.
359
+ - **Close-out gap, documented rather than guessed at.** Cross-CLI calls are invisible to `council-cost.sh` — it only parses the Claude Code transcript — so a run that routes real work through agy headless silently under-reports at close-out (new anti-pattern #18). Considered extending the script to capture agy's own `usage` JSON automatically; declined, because no convention for where those numbers would be recorded exists anywhere in this repo yet and inventing one would be guessing at a format. Instead `SKILL.md` Step 9 now instructs the lead to add cross-CLI `usage` to the tally by hand. Also documented: Claude Code's new `--max-budget-usd` flag and three `CLAUDE_CODE_MAX_SUBAGENT*` env vars as a preventive complement to the post-hoc tally, and as harness-level backing for the skill's existing "one level deep" nesting rule.
360
+ - **REQ ledger self-contradiction fixed.** Step 0 had the lead hand-extract the REQ ledger from the owner's message — which is bulk extraction, exactly what anti-pattern #11 ("the lead doing menial work itself") forbids. `SKILL.md` Step 0 and the arch doc's atomic-unit section now have a cheap worker draft the ledger from the owner's verbatim message, with the lead ratifying it (one read against the original message) before cutting anything; an unratified draft is not a ledger. The YAML `description` frontmatter line was updated to match, since it previously said "the lead pins every owner requirement."
361
+ - One line added to `docs/arch/akiflow.md` noting Claude Code's `/team-onboarding` is unrelated to multi-agent orchestration (human-facing, "cannot be invoked by the model"), so a future reader does not re-investigate it.
362
+ - `payload/RULE-agent-behavior.md` A2 — three tool-efficiency bullets, prompted by observed recent-session drift toward Bash `cat`/`grep` over native Read/Grep and piecemeal single-line edits over batched ones: (1) Read/Edit for a known single file, Bash reserved for multi-file scans/transforms and genuinely shell-native tasks — not print-then-read on one file; (2) locate all edit sites before applying them as one batched multi-edit pass; (3) exploration/file-reading work goes to a readonly subagent (Haiku on Claude Code, `agy -p` flash on Antigravity) prompted with a specific search target, to keep the main agent's context from being diluted by raw search output and to keep cost down. Core tier (loads every conversation). `payload/index.md`'s manifest row updated to match.
363
+ - **New skill: `akidevsync-notes`.** Reads/edits a project's `.akidevsync/notes.json` — the per-project task file the Aki-Dev-Sync app (github.com/lacvietanh/aki-dev-sync) writes and reads itself — via a bundled `scripts/notes_cli.py` (`list`/`add`/`set`/`delete`/`note`/`init`) rather than hand-editing JSON, so every mutation preserves the app's own formatting exactly (2-space indent, unescaped Vietnamese, alphabetical per-task key order, trailing newline) and never produces a diff the app's next write would fight. Also documents a cross-check workflow: match a project's pinned/open notes against what a release's CHANGELOG and code actually shipped before marking a note done, asking the user rather than auto-closing anything the changelog itself flags as unverified. `README.md` (Seven → Eight skills, table row, skill-count mermaid labels, uninstall `rm -rf` lists) and `docs/arch/rule-delivery-architecture.md` (skill count) updated to match; `skills/akihelp/SKILL.md` needs no change since it reads installed state live.
364
+ - **akiflow: two additions — a mandatory per-subagent rule floor, and close-out token/cost accounting.** Both close gaps that follow from the same harness fact the skill already documents (a subagent inherits no akirule routing), pushed to their conclusions:
365
+ - **Per-subagent akirule floor** (`SKILL.md` Step 2 + Step 4 thinking-floor template + Step 7 Phase B/reviewer/Tier-0 + Step 5 nested + Step 1 audit, new anti-pattern #14, `docs/arch/akiflow.md`). The skill already said "name the exact `*.md` files to Read"; it did not name a *minimum*. Now the lead acts as the router the subagent lacks in two explicit layers: `RULE-agent-behavior.md` is a non-negotiable floor for **every spawn that can touch the repo, at every tier, on every model, in every phase** — the Phase A roster, every Phase B implementer / verifier / adversarial reviewer, every nested worker, every audit sweep; the sole exemption is a self-contained bare call with no repo access. The floor carries scope discipline (`agent.B1`), the audit read-only + never-mutate-git ban (`agent.B5`), the no-credit-trailer rule (`agent.B4`), and file hygiene (`agent.C`), plus the item's domain rules matched the way akirule Tier-2 would have. Two clauses spelled out to pre-empt the obvious objections: the floor binds read-only spawns (reviewer, verifier, sweep) **as hard as** writing ones, because `agent.B5` is precisely what stops "fixing while here"; and it does **not** conflict with the adversarial reviewer's isolation — that isolation withholds the lead's *reasoning*, not the *constraints*, and rules cannot bias a verdict toward agreement. The `RULE-coding.md`/`design-core` reviewer read-list and the "receives only the diff and the closing criteria, **nothing else**" boundary (Step 7) were reworded so "nothing else" means "none of the lead's reasoning", not "no behavior floor". The counter-intuitive cost clause stays: the cheaper the model, the *more* essential the floor — a haiku on a "simple" sweep has the least judgment to reconstruct the missing rules, so it is exactly the cheap sweep that goes rogue when the floor is dropped as overhead.
366
+ - **Close-out accounting** (`SKILL.md` new Step 9, new anti-pattern #15, new script `skills/akiflow/scripts/council-cost.sh`, `harness-facts.md` new fact row, `docs/arch/akiflow.md` new section). Every Tier 1/2 run ends with one `haiku` subagent tallying per-agent token usage so the lead can reconcile actual spend against the `model`/`effort` it declared up front in Step 1 — the other end of that declaration. The harness already records every turn's `model` + `usage` (the lead's and every `isSidechain` subagent's) in one session transcript, so the tally needs no in-run bookkeeping; `council-cost.sh` parses and aggregates it **in-shell** (the lead never re-reads the transcript — that would be the flooded-lead failure) and labels each subagent chain by akiflow's own `You are <NAME>` prompt opener. The script prints **tokens only**: dollar cost is `tokens × current per-model price`, computed at report time, because per-model prices drift and a hardcoded table in a distributed script would rot. Verified live: the script runs against a real transcript and produces the LEAD tally; sidechain attribution is best-effort per role-name and exact per model. `README.md` (akiflow row + scripts manifest) and the arch doc's failure-modes list updated to match.
367
+ - **akiflow: five structural fixes closing the gap between "the skill's rules" and "what the owner still had to type by hand every invocation."** Prompted by a real audit-mode run where the owner's prompt had to restate compliance instructions the skill already claimed to guarantee (haiku for reads, no lead busywork, batch spawn), and separately hit a genuine gap the skill had no answer for (an escalated question doctrine already answered, an owner answer that would evaporate with the session, a UX decision closed without UX consult, the same conflict re-litigated across several items). Rather than adding more owner-side instructions, each fix makes the property checkable or automatic instead of asked-for:
368
+ - **Requirement ledger** (`SKILL.md` Step 0, `docs/arch/akiflow.md`) — the owner's message is pinned as a numbered `REQ-1…n` ledger in `checklist.md` before decomposition; every item must name the REQs it covers; an orphan REQ is a decomposition bug, and Red Team now attacks the REQ→item mapping alongside the cuts themselves.
369
+ - **Roster self-declaration** (`SKILL.md` Step 1) — the gate line grows a second line naming every planned spawn with its `model`/`effort` up front, so mechanism compliance (Step 2) is auditable before any spawn runs instead of trusted after the fact.
370
+ - **Lead context diet** (`SKILL.md` Step 2, new anti-pattern #11, `docs/arch/akiflow.md`) — explicit ban on the lead doing mechanical work itself (bulk reads, greps, sweeps); it always goes to a cheap subagent, mirroring Step 2's mechanism table applied reflexively to the lead's own behavior.
371
+ - **Escalation pre-flight + doctrine write-back** (`SKILL.md` Step 6, new anti-pattern #12, `docs/arch/akiflow.md`) — an escalation must cite which doctrine files (`docs/biz/`, project `CLAUDE.md`, `docs/arch|feat`) it searched and where they fall silent before it can reach the owner; the owner's answer is proposed back into that doctrine in the same turn, so the identical question can never escalate twice.
372
+ - **Mandatory domain consults** (`SKILL.md` Step 5, new anti-pattern #13, `docs/arch/akiflow.md`) — UX-Psych, Market, and Architect become standing consultants for their whole domain, not only the items they own; a domain-touching item cannot close without a recorded consult turn from the relevant specialist.
373
+ - **Conflict-recurrence rule** (`SKILL.md` Step 5, `docs/arch/akiflow.md`) — the same boundary contested across ≥2 items stops being refereed instance-by-instance and opens one Architect-owned root item to fix the underlying pattern (`RULE-design-core.md` A8), with the conflicted items re-closing against that fix.
374
+ `README.md`'s akiflow row updated to summarize all five.
375
+ - Self-audit after applying the above caught three drifts and closed them in the same pass: `docs/arch/akiflow.md`'s thinking-floor word limit said 400 where `SKILL.md` says 200 (now both 200); the arch doc's "Failure modes" list only carried the old 9 anti-patterns while `SKILL.md` had grown to 13 (now both list all 13, correctly renumbered); and `scripts/council-open.sh`'s `checklist.md` scaffold had no place for the new requirement ledger (now seeds a `## requirement ledger` section above `## items`, with the item template noting the REQs-covered field).
376
+
377
+ ### Fixed
378
+ - **`claude/hooks/aki-update-check.py` still hardcoded the pre-rename install path.** `INSTALL_ROOT` read `~/.aki/claudedoc` after the directory itself had been renamed to `~/.aki/akidevrule`, so `LOCAL_CHANGELOG`/`SOURCE_REPO_FILE` always missed and the update-check notice fail-silently produced nothing since the rename. Fixed to `~/.aki/akidevrule`; patched into the deployed copies on both machines this repo runs on.
379
+ - **The three "harness-guaranteed" core rules were never actually guaranteed — `@` imports inside a skill body load nothing.** `skills/akirule/SKILL.md` declared a `## Tier 1 — Core (harness-guaranteed)` section containing `@~/.aki/akidevrule/index.md`, `@…/RULE-agent-behavior.md`, and `@…/RULE-coding.md`. That syntax is expanded mechanically by Claude Code **only** when it appears in a `CLAUDE.md` read at session start; inside a skill body it is inert text, and the body itself is read only *after* the model has already decided to invoke the skill. So the one tier documented as unconditional was in fact the most conditional thing in the system — it required a model decision *and* a syntax that does not apply there. Confirmed from git history that the imports had never been present in `claude/CLAUDE.md`: this was a design flaw dating from the original tiered restructure, not a regression from any Claude Code or akidevrule update. Fixes:
380
+ - `claude/CLAUDE.md` (installed to `~/.claude/CLAUDE.md`) gains a real `## Core rules — mechanically loaded, every session` section importing `index.md` and `RULE-agent-behavior.md` by deployed path. `INSTALL_ROOT` is fixed at `$HOME/.aki/akidevrule`, so the tilde paths are correct on every install and no installer change is needed.
381
+ - **`RULE-coding.md` deliberately not force-loaded.** The three files together are ~28 KB in every session of every project, including non-Aki ones, against a global instruction to keep global context small. Only the corpus map and the behavior floor are hard-imported; `RULE-coding.md` moves down to signal-triggered loading with a high-sensitivity, default-ON-for-any-code-work entry (keywords, source-file path globs, and the write/edit/debug/verify actions) so a miss is treated as a real failure rather than a saved read.
382
+ - `skills/akirule/SKILL.md` loses the fake Tier 1 and opens instead with `## What this skill does and does not guarantee`, stating plainly that nothing it routes is guaranteed and recording *why* the imports must not be moved back — so the same mistake is not re-made by someone reading the file as a tidy place to keep them. Remaining tiers renumbered (contextual → Tier 1, full load → Tier 2), load-confirmation lines and the YAML `description` updated to match.
383
+ - `payload/index.md` manifest: `RULE-agent-behavior.md` retagged `Core — @ import in ~/.claude/CLAUDE.md`, `RULE-coding.md` retagged contextual/high-sensitivity, and the routing footnote now distinguishes the two mechanisms instead of pointing everything at the skill.
384
+ - `README.md` architecture section rewritten around the mechanism split rather than the tier numbering, and the sentence "No harness magic: Tier 1 uses the `@path` embed syntax" — the clearest statement of the wrong belief — replaced with the actual rule about where `@` works.
385
+ - **akiflow prescribed a single global `chat.md` turn counter that no run could hold.** The format spec said `#<turn>` was "a single counter across the whole room, not per agent" — but parallel specialists cannot see each other's latest number, so they collide (an older real run had two instances of one specialist both posting `#1`, plus timestamp-vs-file-order inversions). Replaced it with per-agent number blocks the lead assigns at convene time (`architect` 10–19, `red-team` 20–29, …): each agent numbers only inside its own block, keeping every citation unambiguous with zero cross-agent coordination — no file lock needed, since turn appends are already atomic. Updated `skills/akiflow/SKILL.md` (Step 5 roster-block assignment, the `chat.md` `#<turn>` format bullet, the thinking-floor report shape + roster brief), `skills/akiflow/scripts/council-open.sh` (pinned ROSTER line now names each agent's block), and `docs/arch/akiflow.md`.
386
+ - **akiflow spawn calls omitting `model`/`effort` silently inherit the lead's own top-tier model.** A real 6-agent Phase A roster spawned without either parameter ran entirely on the lead's model, burning ~935k tokens on work that was mostly bandwidth-shaped (directory diffs, column greps, duplicate-path counts) — exactly the kind of task the mechanism table already routes to a cheap model, except nothing said the parameter has to actually be passed. There is no cheap-tier default; an omitted value is a top-tier choice made by accident. Added a new fact row to `skills/akiflow/references/harness-facts.md` documenting the inheritance behavior, a new mandatory-parameter rule to `skills/akiflow/SKILL.md` Step 2, and anti-pattern #10.
387
+ - **akiflow's "fork" mechanism was never a real Claude Code API.** A real run failed every `subagent_type: fork` spawn with `Agent type 'fork' not found`. Verified against official docs (`code.claude.com/docs/en/sub-agents`, `.../agents`, `.../changelog`): `/fork` and `/subtask` are interactive slash commands gated by `CLAUDE_CODE_FORK_SUBAGENT=1`, not something the Agent tool can invoke programmatically — and `/fork`'s own meaning changed at v2.1.212 (it now opens a background session; the in-session forked subagent it used to launch is `/subtask`). Removed the "fork for continuity" mechanism everywhere it was documented as available and replaced it with the actual fallback a real run already needed: a plain subagent handed the plan doc / diff explicitly in its prompt. Updated `skills/akiflow/SKILL.md` (Step 1 tier table, Step 2 mechanism table, Step 7 execution table, harness notes, anti-pattern #2), `skills/akiflow/references/harness-facts.md` (fork fact row, cost-model row, model-tiers row, sources list), `docs/arch/akiflow.md` (harness-facts summary, mechanism table, cost section, verification-vs-review table + prose, mermaid diagram, rationale-travels paragraph, failure mode #1), and `README.md`'s akiflow row. Prior CHANGELOG entries describing the fork-based design are left as-is — they are a record of what was built at the time, not a spec to keep current.
388
+
389
+ ### Changed
390
+ - `payload/RULE-release.md` A5 — new bullet: the version's recorded date is the day C5's live-verification passes, not the day the entry was drafted/committed. Prompted by a real case where the two would have diverged.
391
+ - `payload/RULE-release.md` A3 — git tag guidance now differentiates by stack: distributed-artifact apps (Tauri/Desktop/CLI) treat tagging as standard practice (unchanged, already implied by A5's atomic bump+tag+build); web (continuously-deployed) apps get tagging as a light, optional suggestion for an ordinary patch release, escalating to an active recommendation once a release bundles a major/minor bump or several substantial changes. Creating/pushing a tag stays propose-only, never auto-executed (`agent-behavior.md` B3).
392
+ - `skills/akirule/SKILL.md` — `RULE-release.md`'s Tier 2 signal list gained a commit/push/deploy keyword group (`commit`, `push`, `deploy`, `git tag`, `triển khai`, …) so the release rule loads on ordinary commit/push/deploy phrasing, not only on explicit "release"/"changelog"/"version" wording.
393
+ - `payload/GEMINI.md` rule 11 (final-audit handoff) — trigger broadened from "a deploy/push of a web release" to any commit/push/deploy/tag that ships to production or a shared branch, on any stack, so the mandatory review-handoff block fires for Tauri/CLI releases and plain pushes too, not only web releases.
394
+
395
+ ### Added
396
+ - `install.sh` now syncs the shared skill corpus to three more CLIs that natively consume the `SKILL.md` open standard: **Codex CLI** (`~/.agents/skills/`, per OpenAI's own docs at `developers.openai.com/codex/skills`), **Kiro CLI** (`~/.kiro/skills/`), and **Grok CLI** (`~/.grok/skills/`). Each root is synced per skill folder name via the same `sync_aki_skills()` helper the Antigravity targets already used (previously duplicated inline for Claude Code and inline again for Gemini; now one shared function, called for all five skill targets) — same never-touch-the-rest guarantee, unconditional (harmless if that CLI isn't installed, picked up the moment it is). Skills-only for these three: no rule corpus / no `CLAUDE.md`-style hard-load hook exists for them yet. Verified live on this machine: `~/.grok/skills/` already held unrelated pre-existing skills and the sync left them untouched. README installer steps, layout mermaid diagram, and uninstall block updated to match.
397
+ - New research doc `docs/research/antigravity-claude-skills-native-discovery.md` — cross-checked (official `antigravity.google/docs/skills` + an independent, recently-dated third-party path breakdown) whether AG/AGY now reads `~/.claude/skills/` natively, prompted by a local experiment that seemed to suggest so. **Finding: no** — both sources agree `~/.claude/skills/` is not a discovery root; `~/.gemini/config/skills/` stays required. Decision: no change to `install.sh`'s existing Antigravity skill sync.
398
+ - `docs/arch/akiflow.md` — added a mermaid flowchart of the full council process (activation gate → decomposition → Phase A room with steering/checkpoint/close loop → owner-escalation gate → Phase B execution/verify/review → reopen-on-blocker loop), so the two-phase prose description now has a diagram a reader can trace end to end.
399
+
400
+ ### Changed
401
+ - **Breaking (install target): `~/.aki/claudedoc` renamed to `~/.aki/akidevrule`.** `claudedoc` was a leftover from this repo's pre-rename name (`AkiClaudeDoc`, renamed to `akidevrule` in an earlier commit) that never got carried through to the deployed path. `install.sh` now migrates an existing legacy install in place (`mv`, only when the new path doesn't already exist — no data loss) and writes every new reference as `~/.aki/akidevrule`. Updated: `install.sh` (`INSTALL_ROOT`, the two `agskills` path strings, `settings.json` permission/`additionalDirectories` cleanup for the old path), `README.md`, root `CLAUDE.md`, `claude/CLAUDE.md`, `payload/GEMINI.md`, root `GEMINI.md`, `claude/fragments/settings.akidoc.fragment.json`, `docs/arch/akiflow.md`, `docs/arch/rule-delivery-architecture.md`, and the skills that hard-embed the corpus path (`akirule`, `akiflow`, `akiflow/references/harness-facts.md`, `akihelp`, `akithink`). A machine that re-runs `install.sh` migrates automatically; nothing manual needed.
402
+
403
+ - **Breaking (repo layout): `claude/skills/*` moved to top-level `skills/*`.** Verified via web research that Agent Skills (`SKILL.md` + YAML frontmatter + optional `references/`/`scripts/`/`assets/`) is a shared open standard both Claude Code and Antigravity/AGY natively consume, byte-for-byte, with zero per-agent transformation — unlike `payload/` rules, which do need per-agent frontmatter generation for Antigravity. Nesting skills under `claude/` mislabeled them as Claude-only when the install pipeline already deployed the same folder unmodified to both `~/.claude/skills/` and `~/.gemini/config/skills/`. `skills/` is now a sibling of `payload/`, matching the existing shared-source pattern; `claude/` keeps only genuinely Claude-only assets (`CLAUDE.md` template, hooks, settings fragment). Updated: `install.sh` (3 path references), `README.md` (layout block, mermaid diagram, installer-step prose), root `CLAUDE.md`, `claude/CLAUDE.md`, `docs/arch/akiflow.md`, `docs/arch/rule-delivery-architecture.md`, `docs/plan/improve-jun24.md`. Findings and sources recorded in `docs/ref/agent-skills-standard.md`. Deployed target paths (`~/.claude/skills/`, `~/.gemini/config/skills/`) are unchanged — this only affects the source repo layout; a machine that re-runs `install.sh` needs no manual migration.
404
+
405
+ ### Fixed
406
+ - `install.sh` Claude Code skill deploy step copied only `SKILL.md`, silently dropping any `references/` subfolder — harmless for the first six skills (flat layout) but broke `aki-article-writer`'s progressive-disclosure layout on Claude Code specifically (Gemini/AGY were already unaffected, since their skill sync used `rsync` on the whole folder). Now uses `rsync -a --delete` on the whole skill directory, same as the Antigravity sync path. README installer-steps text and skill-count mentions (6 → 7) updated to match.
407
+
408
+ ### Added
409
+ - New skill `claude/skills/aki-article-writer/` — per-project article writing pipeline (`/aki-article-writer`). Follows the progressive-disclosure layout (slim `SKILL.md` + full procedure in `references/article-workflow.md`). Key design decisions: (1) one Article Worker subagent per article keeps the full content context clean; (2) a separate Image Scout subagent on Gemini Flash / Claude Haiku handles all image work — `search_web` for candidate discovery, `curl` with browser UA for download, mandatory `view_file` inspection before and after processing, `ffmpeg` center-crop + Lanczos resize to spec (hero 1200×630 px, body 800 px, square 800×800 px), slug-indexed WebP output, and `/tmp/` cleanup before handoff; (3) six-phase self-audit checklist covers meta char limits, JSON-LD schema matrix (BlogPosting / Article+DefinedTerm / Product / Service), trailing-slash policy, UX-psychology content rules (no banned openers, ≤5-line paragraphs, question-shaped H2s for AI citation, anxiety handling at CTA points), Vietnamese dual-coverage (unaccented keyword in parentheses, never in headings), and SSR/prerender requirement. README skills section updated (six → seven skills); layout listing updated.
410
+ - New rule `payload/RULE-biz.md` (topic `biz`, Contextual) — business & market rules: one primary audience, falsifiable USP, `docs/biz/` as SSoT, niche-first; value-based pricing, few tiers, validate before building, revenue path stated from day one; benefit-first messaging, anxiety handling at decision points, absolute no-dark-patterns floor. Owns the content of business decisions; the decision process stays in METHOD-deep-think Module 4.
411
+ - New method `payload/METHOD-ux-psych.md` (topic `ux`, Analytical) — UX psychology audit: six lenses (cognitive load, recognition over recall, feedback/status, defaults, motor cost, mental-model/trust), a persona walkthrough protocol (first-run, friction ledger, failure paths, state completeness), severity-weighted output routed through the design system. Routing signals added to `akirule/SKILL.md` (Tier 2) and `install.sh` AG_RULE_MAP for both files; `payload/index.md` manifest and groups table updated.
412
+
413
+ - New skill `claude/skills/akiflow/SKILL.md` — sized multi-agent delivery pipeline (`/akiflow`): strict 3-tier sizing gate (Tier 0 direct by default; Tier 1 Architect plan + adversarial Reviewer; Tier 2 adds business/UX counsel), docs-as-handoff protocol between stages, explicit akirule-file injection for subagents, model/effort assigned by nature of work. Full roster active: Architect + Reviewer (Tier 1), Market + UX-Psych (Tier 2, grounded in RULE-biz.md and METHOD-ux-psych.md). Design record: `docs/plan/akiflow-skill.md`. README skills section updated (five → six skills).
414
+
415
+ - New architecture doc `docs/arch/akiflow.md` — the binding reference for `/akiflow`: the three structural failures of a single main thread (context flooding, role collapse, self-approval) and why none is fixed by a stronger model; the work item as atomic unit; the verified harness facts the design rests on (sibling-roster snapshot, fork context and cache inheritance, subagent resume-on-message, non-relayable permission approval, agent-teams mailboxes) with the design consequence of each; the verification-vs-adversarial-review boundary; peer-to-peer risks and their answering rules; who challenges the lead's own decomposition; and the seven failure modes with the reason each is structural rather than a lapse.
416
+
417
+ - Audit capability across the corpus — previously the rules covered *doing* the work but never *verifying it afterwards*, so an audit request fell through every gate. Three situations are now distinguished by whether the baseline is stable, because only one of them should leave a durable record:
418
+ - `payload/RULE-docs.md` §C **Drift audit** (`docs.C1-4`) — the verification counterpart to B3's process rule. C1 scopes it to a clean tree on a published baseline and explicitly routes the other two situations elsewhere; C2 defines the output contract as a `docs/research/` finding record on the B2 schema **paired with** a `docs/plan/` execution doc, named by what was audited rather than version-first (a version in the filename collides visually with B2's supersede-chain suffix), with deliberately-unscheduled findings recorded as B2 "No action" so a deferral cannot be mistaken for an oversight; C3 is the comparison checklist across the whole `docs/` topology; C4 splits severity into wrong / stale / incomplete / cosmetic so one aggregate count cannot hide whether the docs are currently dangerous.
419
+ - `payload/RULE-agent-behavior.md` §B5 **Audit is read-only by construction** — an audit reports and never fixes, as a structural default rather than a flag. Includes the absolute ban on mutating git state during an audit (`add`/`stash`/`checkout`/`restore`/`clean`/`reset`), which is a harder floor than "do not edit code" because a half-finished tree is where uncommitted work is least recoverable, and the ban on auto-classifying ambiguous work since mid-edit and abandoned cannot be told apart by reading the tree.
420
+ - `payload/RULE-release.md` §B7 **Pre-ship gate** — a pass/fail check for finished-but-unpushed work that composes existing rules (B1 release state, B5 + coding.B3 external-action completeness, B2 record truthfulness, docs.B1/B3 doc sync, coding.B3 verification honesty, A4/A5 version decision) into one entry point instead of five scattered ones. Produces no audit doc by design; deploy verification stays out of the gate since it runs after the push.
421
+ - `claude/skills/akiflow/SKILL.md` Step 1b — **audit track**, orthogonal to the tier rather than a fourth tier: declared as `mode=audit` on the same gate line, sized by domain count instead of file count, with a domain → rule-file table so each read-only subagent Reads only its own domain and reports in that file's severity vocabulary. Severity triage and synthesis stay with the orchestrator on the strong model; sweeps run cheap. Fixes are a separate run through the normal gate.
422
+ - `claude/skills/akigitcommit/SKILL.md` Step 0 — **triage a half-finished tree** before grouping: classify each chunk as finished / mid-edit / abandoned / accidental, ask rather than guess on the two that a tree read cannot distinguish, and never mutate git state while triaging (`RULE-agent-behavior.md` B5).
423
+
424
+ ### Changed
425
+ - `skills/akiflow/` **second-round rewrite: specialist board → agent council**, plus its first `scripts/` and `references/`. The board rewrite got the mechanisms right but never stated what the mechanisms were *for*; without that anchor, every rule read as an independent constraint and the skill had no way to say which tradeoff wins. What changed:
426
+ - **A stated purpose, first paragraph of both skill and arch doc** — the council exists to reach the most rigorous decision it can *without* the owner. Rigour and offloading normally pull against each other (more rigour → more questions asked of the person); the council resolves that by absorbing the questions itself. Only the three owner-owned escalations travel up, plus a rare fourth: a deadlock on something genuinely important that the lead cannot break on the merits — and that goes up **as a decision** (positions, tradeoff, recommendation), never as an open question handed back. New anti-pattern #6 names the inversion.
427
+ - **Named `agent-council`, not `board`** — "board" reads as a dashboard as easily as a governing body. "Council" carries the weight the purpose needs: authority to decide, and the implication that only what genuinely needs deliberating gets brought to it.
428
+ - **A real session workspace, `~/.aki/agent-council/<project>/<YYYY.MM.DD-HHMM>-<slug>/`**, replacing the throwaway `/tmp/akiflow-<id>.md`. Inside the Aki namespace because a council record has value for days, not minutes. The slug is the lead's — shortest wording still recognisable a week later, covering the whole session rather than its first item; the timestamp prefix gives uniqueness for free.
429
+ - **Three artifacts, not two.** The per-agent file (`<name>.md`) is new: a mandate stated once at spawn competes with everything arriving after it, so a specialist that can re-read its own mandate mid-room stays inside it — cheaper than the lead policing scope creep across N agents. `chat.md` is the room; `checklist.md` stays lead-only and durable.
430
+ - **The room is read in time order, reversing the board design's by-item sharding.** A meeting sharded by item is unreadable as a meeting, and an agent rejoining cannot tell what it walked into. Context flooding is answered by *selective retrieval* instead: fixed heading levels (`# head` → `## pinned` → `### <time> <agent> #<turn>` → `#### content`) exist for grep, not for reading order, with a globally-continuous turn counter so "turn 14" is unambiguous, ≤200-word turns, and no hard-wrapped lines (`RULE-agent-behavior.md` C3 — wrapping breaks both the grep and the next reader).
431
+ - **`scripts/council-open.sh`** — opens the session, seeds `chat.md` + `checklist.md`, and **prunes sessions older than 30 days on every run**, matching the window Claude Code already uses for its own `projects/`, so the two age out on one clock. Retention as a mechanism, not a rule anyone must remember: moving the workspace out of `/tmp` removed the free garbage collection `/tmp` was providing, and this restores it. `AKI_COUNCIL_ROOT` / `AKI_COUNCIL_RETENTION_DAYS` override.
432
+ - **`scripts/council-read.sh`** — `--index`, `--pinned`, `--stats`, `--agent`, `--from`, `--tail`. What makes "read the room in time order" compatible with "never load the whole room": a rejoining specialist reads `--pinned` + `--from <its last turn>`, the lead watches `--stats`/`--index` and opens full turns only where something looks wrong.
433
+ - **Steering is judgment, never a round counter.** A fixed limit would punish exactly the deliberation this skill exists to produce. The lead intervenes on four real signals — ground re-covered with no new evidence, a closing criterion that stopped getting closer, drift outside the mandates, cost outrunning the decision's value — with the minimum action: one pinned CHECKPOINT line, messaged only to the drifting agents. A room that cannot converge is the lead's call to close.
434
+ - **`references/harness-facts.md`** (new, progressive-disclosure — costs nothing until read) — every harness fact the design rests on, each tagged **[doc]** (in Anthropic's documentation, with source links) or **[obs]** (observed runtime behaviour, not documented), so a later reader can tell what is verified from what is merely believed. Adds the facts the board rewrite lacked: `isolation: "worktree"`, prompt-cache TTL, per-message turn cost, and the family-level model→work mapping the board rewrite dropped when it generalised to "cheapest capable / strong".
435
+ - **Cost realism.** A fork's cheapness expires with the prompt cache — fork for the *context* reason and treat the saving as a bonus that may have lapsed. And "always load the corpus" is the same error as "never load it": a self-contained mechanical question is correctly served by a bare cheap-model call with no rule files at all.
436
+ - **Headless (`claude -p`) is now handled** — nobody can answer an owner escalation or a permission prompt, and both fail silently if unplanned. The lead records `BLOCKED: needs owner` in the checklist and continues the other items, never guessing what the owner would have wanted; runs are scoped to what current permissions already allow.
437
+ - **Parallel writers get `isolation: "worktree"`** in Phase B; a lone implementer or read-only sweep does not (setup costs time and disk per agent).
438
+ - Execution record: `docs/plan/done/akiflow-council-rewrite.md`, indexed in `docs/index.md`; the design record `docs/arch/akiflow.md` is updated in place as current state.
439
+ - `claude/CLAUDE.md`: two stale spots from the two renames — the deployed corpus was still called "the installed claudedoc directory" in prose, and the "edit under" step still listed only `payload/` and `claude/`, omitting the now top-level `skills/`. An agent following that step from another project would have looked for skills in the wrong place.
440
+ - `README.md` installer step 2: skill folders now carry `scripts/` as well as `references/`; the sentence naming what gets synced said only `references/`.
441
+ - `claude/skills/akiflow/SKILL.md` **rewritten around a new axis** — from a sized delivery pipeline to a **lead-coordinated specialist board**. Three harness facts invalidated the original premises: a subagent with a name and `SendMessage` receives a sibling roster and can challenge peers directly (so docs are no longer the only in-run handoff); a `fork` subagent inherits the session's context, tools and prompt cache (so a second opinion is nearly free, and rule-injection lists are wasted on forks); a completed subagent resumes with full history when messaged (so a roster can stay convened across phases at no idle cost). What changed as a result:
442
+ - **The atomic unit is the work item**, not the tier — `{owner, challenger, closing criterion, rationale}`. One structure delivers coverage (a closed checklist, not anyone's diligence), bounded context (the owner field defines a read domain), structural dissent (the challenger field), and a stop condition (the closing criterion). Decomposition is a **precondition** for convening the room, never its product.
443
+ - **Activation gate replaced with three direct conditions** — decomposable / ≥2 different kinds of "correct" / cost of error above cost of coordination — retiring the structural proxy signals (schema, ≥3 modules, >5 files). Tier now falls out of condition 2 instead of being a separate maintained taxonomy, so a future security or legal domain needs no new signal list.
444
+ - **Mechanism chosen by shortfall, never by job title**: bandwidth → cheap plain subagent; continuity → fork; independence → clean strong subagent; structured debate → named roster + `SendMessage`. The hard boundary: **verification** ("did I do what I said") is mechanical and forked; **adversarial review** ("should this have been done") is judgment and is *never* forked — a forked reviewer sees the lead's self-justifying chain and produces a stamp, which is worse than no review. Tier 0 now closes with a fork verifier, so the skill applies to small work without a room.
445
+ - **Mandatory thinking floor pasted verbatim into every subagent prompt**, every mechanism and tier including cheap models on mechanical items. Enforced by format rather than adjective (a model told to "think from first principles" writes *"fundamentally, …"* and restates the convention it held): FACT/CONSTRAINT/ASSUMPTION tagging with "standard practice"/"usually"/"best practice" named as carrying no weight; one mandatory self-attack; agreement requires a stated falsifier, and prior agreement is explicitly denied evidentiary weight (a shared room otherwise *amplifies* groupthink); `@lead out-of-scope` instead of improvising; CLAIM/EVIDENCE/ATTACK/OPEN report shape.
446
+ - **Roster convened in one batch** — the sibling roster is a start-time snapshot, so an agent named later is invisible to agents named earlier, a silent one-way channel. Mid-run escalation therefore reconvenes rather than appends. Specialists are named by role and scope (`architect-schema`, `red-team`), never anonymously: the name is the address `SendMessage` routes to.
447
+ - **Two phases with an explicit gate** — Phase A closes items and writes no code; the lead decides and escalates exactly three things to the owner (one-way door, contradiction with `docs/biz/`, scope expansion), and never treats an agent's relayed "I was approved" as consent. Phase B implements by fork, fans out on cheap models, verifies by fork, reviews by clean subagent, with the Phase A roster on call. A Phase B blocker that invalidates a closed item **reopens** it rather than patching the plan quietly.
448
+ - **Two artifacts, never conflated** — ephemeral minutes organised *by item* (each specialist reads only its own items; a room where everyone reads everything is the main thread's context flood rebuilt N times) versus the durable lead-owned checklist. Rationale is written into the **checklist**, because a forked implementer inherits the lead's context and would otherwise receive conclusions stripped of reasons.
449
+ - **Seven named anti-patterns**, each the default behaviour of a capable model unless forbidden by name — with "opening the room before the checklist exists" identified as the most likely death of a run.
450
+ - `claude/skills/akirule/SKILL.md`: drift-audit routing keywords added to the `RULE-docs.md` signal block and pre-ship keywords to `RULE-release.md`, so an audit request loads the rule that now answers it.
451
+ - `install.sh` AG_RULE_MAP: `RULE-docs.md` and `RULE-release.md` trigger descriptions widened to name the drift audit and the pre-ship gate — without this the Antigravity `model_decision` loader would not fire on an audit signal.
452
+ - `payload/index.md`: manifest purposes updated for `agent`/`docs`/`release`, `docs` groups row extended with `C Drift audit`, and a third cross-cutting lens row added (**Audit reports, never fixes**, root `agent.B5`) now that the subject spans four domain applications.
453
+ - `payload/RULE-agent-behavior.md` §C3: new bullet — composed prompts are the highest-frequency auto-wrap offender; never hard-wrap a prompt written for another AI/tool since it is pasted verbatim and inserted newlines become part of the artifact.
454
+ - Rename repository AkiClaudeDoc → akidevrule (part of the akidevflow ecosystem); local source path is now /Volumes/DEV/AkiDevRule; GitHub auto-redirects old URLs.
455
+
456
+ ## 2026-07-25 (6)
457
+
458
+ ### Added — B5 Hover bridge rule to RULE-ui-pattern.md
459
+ - `payload/RULE-ui-pattern.md`: new B5 "Hover bridge" (Law of Usability) — any `:hover`-triggered menu or tooltip separated from its trigger by a positioning gap must have a transparent bridging pseudo-element (`::before`/`::after`) covering the gap to prevent hover loss during cursor movement. Address-map comment updated to `ui.B1-5`.
460
+
461
+ ## 2026-07-25 (5)
462
+
463
+ ### Added — DELETE-body-hang pitfall to RULE-stack-akiNuxtCf.md §A2
464
+ - `payload/RULE-stack-akiNuxtCf.md`: new bullet in "Cloudflare Worker runtime constraints" — never call h3's `readBody()` in a DELETE handler. On workerd, reading a body the runtime never actually attached to a DELETE request hangs the promise instead of rejecting it, and the platform kills the request as a bare 500 with no stack trace; this does NOT reproduce under `nuxt dev` (Node), so it survives local testing and only surfaces in production. Found live on tachnhac.com: an admin task-board delete endpoint hung this way, confirmed via `wrangler pages deployment tail` showing "Workers runtime canceled this request because it detected that your Worker's code had hung". Fix is to carry DELETE payloads via query string on both client and server, never body.
465
+
466
+ ## 2026-07-25 (4)
467
+
468
+ ### Fixed — RULE-release.md §C5 live-verification command was wrong for the actual stack
469
+ - `payload/RULE-release.md`: §C5's example (`curl .../releases.json`) assumed a public static JSON endpoint that doesn't exist on this stack — `releases.json` is bundled into client JS, not served at a stable path (verified: 404 on app.akinet.me). Also, the CSS class wrapping the version number differs per site (`rl-version`, `release-version`, or none at all on akitao.com), so a class-based grep isn't portable. Replaced with `curl -s https://<domain>/releases/ | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1` — verified live against all 8 AkiNet-family sites (including one with no version CSS class), works regardless of markup since every site renders the literal `v{{version}}` text.
470
+
471
+ ## 2026-07-25 (3)
472
+
473
+ ### Added — Content-language policy for the public corpus
474
+ - `CLAUDE.md` (project root): new "Content language" section — `payload/` and `claude/` are public and distributed beyond Aki, so all authored content, including section/group headers, must be English. Narrow, documented exceptions: Vietnamese keyword/signal lists that must match a Vietnamese-speaking user's words, worked examples that specifically need Vietnamese text (accented-query SEO example, NFC-normalization example), and literal trigger phrases the user actually types (`nạp full`, `commit luôn`). A ready-to-paste prompt template must not hardcode Vietnamese output either — it composes in the session's current language instead. Existing group headers (`## A. Giao tiếp` etc.) across `payload/*.md` predate this policy and are not yet migrated — flagged as a known follow-up, not fixed in this pass.
475
+ - `payload/GEMINI.md`: the "final review" example prompt block was hardcoded Vietnamese; rewrote it in English (illustration only) and added an explicit instruction that the agent must compose the actual block in whatever language the current session is using, not paste the literal example text.
476
+
477
+ ### Added — Temporary/working-file scope discipline (`RULE-agent-behavior.md` new C5 + `GEMINI.md` new rule 13)
478
+ - `payload/RULE-agent-behavior.md`: new C5 "Temporary and working files" — debug/test/audit scripts and other throwaway files go into the harness-provided scratchpad, never the project root or scattered into the tree, even if deleted afterward; a technical obstacle is not license to write outside the assigned scope; files that need to persist go into `scripts/`, done and reported, no need to ask first. Closes a gap where nothing in the corpus addressed *where* an agent's own working files land. Address-map comment updated to `agent.C1-5`.
479
+ - `payload/GEMINI.md`: mirrored the same constraint as new rule 13 (appended at the end, not inserted mid-sequence, to avoid re-numbering directives 0-12 as flagged by a past changelog entry).
480
+
481
+ ## 2026-07-25 (2)
482
+
483
+ ### Fixed — install.sh could silently delete a user's own Antigravity skills (data-loss bug)
484
+ - `install.sh`: the Antigravity skill sync (`~/.gemini/config/skills/` and `~/.aki/claudedoc/agskills/`) used `rsync -a --delete` against the whole shared skills directory — any skill the user had placed there that wasn't one of Aki's 5 got silently deleted on install/reinstall, no backup, no warning beyond the generic pre-install prompt. Fixed by scoping the sync to one named folder per Aki skill (new `sync_aki_skills()` helper): `--delete` now only prunes stale files *inside* a folder Aki itself owns, and only Aki's own known old/renamed skill names (`akidoc-*`, `akiadvise`) are explicitly removed — mirrors the Claude Code side, which was already safe this way. `bash -n` verified.
485
+ - `README.md`: documented the per-skill-folder sync guarantee at steps 2 and 7, and added an explicit line under "What is excluded" — no sync ever wipes a skill/rule/file outside this repo's own managed set.
486
+
487
+ ### Added — Docs naming & cross-reference refinements (`RULE-docs.md` A2 + B3)
488
+ - `payload/RULE-docs.md` A2: generalized the "no date prefix in filenames" rule from being nested under Plan-specific B1 to a repo-wide rule for all `docs/*` — content-identifying name first (concise, precise, unique, short preferred), dates recorded in doc metadata not the filename. Added an explicit exception: a compact date suffix (abbreviated month + day, no year, no separator — e.g. `jun24`, `jul27`) may be appended at the end as an optional disambiguator, matching the pre-existing repo example `docs/plan/improve-jun24.md`. B1's filename bullet now points back to A2 instead of restating it, keeping only the plan-specific version-increment convention.
489
+ - `payload/RULE-docs.md` B3: added a rule that code comments should not restate what a doc already explains in detail — when a doc already covers the rationale precisely, comment a reference to that doc (its specific section/heading when only part applies, not necessarily the whole file) instead of duplicating the explanation inline. Keeps the doc as the single source of truth and stops the comment from drifting out of sync with it.
490
+
491
+ ## 2026-07-25
492
+
493
+ ### Added — Research doc schema refinements (`RULE-docs.md` A2 + B2)
494
+ - `payload/RULE-docs.md` A2: stated the current-state-vs-history split as its own rule on `biz/feat/arch` directly (previously only implied inside B2's research rationale) — plus a one-sentence threshold test for when a rationale must move to `research/` instead of staying inline.
495
+ - `payload/RULE-docs.md` B2: added an ADR-style sequential-suffix naming convention for superseded research chains (`topic.md` → `topic-2.md` → `topic-3.md`), and added `ref/` as a valid Decision→Action landing target — always a new distilled lookup doc, never the research doc itself relocated/rewritten.
496
+
497
+ ### Added — Research doc schema (`RULE-docs.md` new B2)
498
+ - `payload/RULE-docs.md`: new B2 "Research doc structure (`docs/research/`)" — a research doc is defined as an immutable event record (never rewritten; revisiting a stale conclusion creates a new doc and stamps the old one `Status: superseded by <path>`), with a required 6-field schema: start time, initial purpose (+ context/constraints at the time), strategy, checklist, result (+ verification evidence and corroborating links — silence on verification reads as false certainty), and decision (action/no-action/follow-up-research/rejected, with outcome links and cross-references to other affected docs). Establishes the event-sourcing split already used for DB design (`db.A`, `RULE-db-design.md`) and for CHANGELOG/plan (append-only, `done/` instead of in-place edits) as the general model for this repo's docs: `arch/feat/biz` hold only current/target state, `research/` holds the reasoning history. Old B2 "Documentation behavior" renumbered to B3.
499
+ - `payload/index.md`: updated the `RULE-docs.md` manifest description to mention the new research schema; address-map comment in `RULE-docs.md` updated to `docs.B1-3`.
500
+
501
+ ### Changed
502
+ - `payload/RULE-docs.md`: reordered group A to Index → Topic folders → Business backbone (was Topic folders → Business backbone → Index), renamed groups to English (`A. Index & Structure`, `B. Lifecycle & Sync`, were Vietnamese `Cấu trúc topic` / `Vòng đời & đồng bộ`). Item addresses shifted: `docs.A1` is now Index (was Topic folders), `docs.A2` is now Topic folders (was Business backbone), `docs.A3` is now Business backbone (was Index).
503
+ - `payload/RULE-docs.md` (now B3): Mermaid policy changed from default-off ("no Mermaid unless...") to prefer-when-complex — use Mermaid whenever plain text is harder to follow for the subject (flows, architecture, state transitions, pipelines).
504
+ - `payload/index.md`: updated the `docs` row in the topic/groups table to match the new English group names.
505
+ - `docs/index.md`: updated the topic-folders address reference from `RULE-docs.A1` to `RULE-docs.A2`.
506
+
507
+ ## 2026-07-24
508
+
509
+ ### Added
510
+ - `payload/GEMINI.md` Rule 12: Enforced mandatory pre-action scope verification checklist inside the hidden `<thought>` block to counter Gemini's RLHF helpfulness bias without polluting user chat UX.
511
+ - `docs/research/gemini-helpfulness-bias-enforcement.md`: Created research doc detailing root cause analysis, prompt-engineering solution, and empirical verification results (100% pass across 3 isolated `agy -p` test cases).
512
+
513
+ ## 2026-07-23
514
+
515
+ ### Added — External-action completeness (migration-execution gap)
516
+ - `payload/RULE-coding.md` B3: generalized the verification principle to cover changes that require a **separate action against an external system** to take effect (migrations, remote config, env vars, cache purges, cron/schedule registration) — writing the file describing the action is not the same event as the target system reflecting it, and neither git diff nor a green build detects the gap.
517
+ - `payload/RULE-release.md` new B5 (renumbered old B5 Content discipline → B6): a CHANGELOG/`releases.json` entry describing a DB schema or infra-dependent change is not truthful until (1) the migration/infra action actually succeeded against the real (remote/production) target with its postconditions checked, and (2) the script is moved to its done location (`scripts/done/` or the project's equivalent marker) — a file still in the pending location is itself evidence step 1 hasn't happened. A plan/release/deploy cannot be reported complete with either condition outstanding.
518
+ - `payload/RULE-stack-akiNuxtCf.md` C8: appended the concrete D1 execution checklist — a green Cloudflare build proves nothing about the database; run `wrangler d1 execute <db> --remote --file=...`, verify postconditions against remote, then move the file to `scripts/done/`.
519
+ - `payload/index.md` Cross-cutting lens: added "External-action completeness" row (root `coding.B3`, domain applications `release.B5` and `stack.C8`).
520
+ - Root cause: a real production incident (kinhdich.akinet.me, 2026-07-23) — a D1 migration script was written and shipped in CHANGELOG v2.10.1 as "Added", but never executed against production. The database stayed on the old schema while deployed code queried the new columns, causing a live 500 on an admin endpoint for a full day before caught. No existing rule checked for this: `coding.B3` only covered runtime-behavior verification, `stack.C8` only checked Cloudflare build status — neither touches whether a required external-system action actually ran.
521
+
522
+ ### Fixed
523
+ - `claude/skills/akigitcommit/SKILL.md`, `akihelp/SKILL.md`, `akihtmlreport/SKILL.md`, `akithink/SKILL.md`: YAML frontmatter had been silently collapsed onto one line (`name: x description: y` instead of separate `name:`/`description:` keys) by an earlier line-unwrap pass that didn't distinguish wrapped prose from structurally atomic content. This is invalid frontmatter — `description` and (for `akirule`) `user-invocable` stopped existing as their own keys. Restored to multi-line.
524
+ - `claude/skills/akirule/SKILL.md`: same frontmatter collapse, plus its three `@~/.aki/claudedoc/...` Tier-1 import lines had been merged onto a single line. Restored to one import per line.
525
+
526
+ ### Fixed — RULE-release.md Drifted guard false-positive on normal in-progress state
527
+ - `payload/RULE-release.md` A5 Pre-Bump Guard + B1 `Drifted` row: the guard fired `STOP AND BLOCK THE BUMP` on a **normal** working state of a distributed-artifact app (Tauri/CLI). Root cause: `Drifted`'s condition was `manifest > last tag`, but for a packaged app the manifest is bumped when a version's work *starts* and the tag is cut only at *build* — so `manifest > last tag` is true for the entire development of the current version, not just real drift. Compounded by three B1 rows (`Unreleased open`, `Pre-bump`, `Drifted`) matching at once with no disambiguation, so an agent picked the loudest. Minimal fix at the two broken spots only: `Drifted` now requires **≥2** unshipped version entries above the last tag (the pileup A5 actually targets); one untagged version matching the manifest is explicitly the normal *Pre-bump*/in-progress state. The guard is reworded to protect *minting the next version*, never *completing the current one*. No general precedence law added (single occurrence — Rule of Three).
528
+
529
+ ### Added
530
+ - `payload/RULE-stack-tauri.md` B6: a Tauri project's `CLAUDE.md` must surface the few decision-shaping target facts up front (first among them the ship platform(s), which drive shortcut glyphs ⌘/Ctrl, path shapes, packaging, and the A2 PATH-candidate list) so the agent grasps target context without inferring — the load-bearing few, not an inventory; ask when a platform-specific string is needed and the target is undeclared. Root-cause fix for an agent waffling between ⌘ and Ctrl on a macOS-only app whose CLAUDE.md never stated the platform.
531
+ - `payload/RULE-agent-behavior.md` A4 + `payload/RULE-coding.md` B3: two rules generalized from a machine-local file into the shared corpus (apply to Claude and Antigravity). A4 (report for fast re-orientation): length follows content with a per-line information test, conclusion-first structure, and never citing a path/symbol/doc bare without a plain-language gloss. B3 (verification, refined): verify by the narrowest tool that settles the doubt; starting a dev server / live network calls / full build / headless screenshot is a **user-triggered** action, not self-authorized (propose and stop), and a full build is never a stand-in for a typecheck. **Red-team applied:** an initial draft ("a presentational edit has nothing to run") was dropped as a false assumption (CSS can break at runtime — z-index click-through, hydration mismatch, purged dynamic classes), and the missing intermediate state was added — when a change's real risk lives only at runtime and cannot be settled statically, the agent may **not** claim "Done"; it halts and reports **"unverified — needs a runtime check"**, proposes the command, and hands off. This closes the hole where "Done means verified" degraded into "Done means I compiled it, you verify it".
532
+ - `payload/RULE-agent-behavior.md` A3 + `payload/GEMINI.md` rule 8: a **communication-vs-task** discriminator — a question/discussion/explanation ("can we / should we / why / what if") is not a request. Claude's shared version (A3) answers questions read-only, executes tasks in-scope, and calibrates autonomy by *reversibility* rather than asking-always (over-asking on safe reversible work is named as a failure, symmetric to acting unasked). The Gemini override (rule 8) is deliberately stricter: COMMUNICATION is **absolute read-only** — no file edits or state-changing commands to "answer" a question, no obvious-fix exception, propose-and-stop only — because the overeager-action failure mode is most acute there.
533
+ - `payload/RULE-agent-behavior.md` C3: two additions found while auditing the regression above. (1) Comments/docstrings/string literals should not be hard-wrapped mid-line either — same training-data habit as prose auto-wrap, now made explicit for code. (2) The reverse direction, which is what actually broke the SKILL.md files: never collapse multiple physical lines into one to "clean up" wrapping without first checking whether each line is wrapped prose (safe to rejoin) or a structurally atomic unit consumed by a parser — YAML/TOML frontmatter fields and `@import`/include directives named as the concrete tells, with a general test ("does something parse this line individually?").
534
+
535
+ ### Added — CHANGELOG backfill (content already in the working tree, previously undocumented)
536
+ - `payload/RULE-seo.md`: `FAQPage` schema flagged as inert for AI visibility as of 2026 (Google retired FAQ rich results; no other consumer confirmed) — keep existing markup, stop treating it as a deliverable; question-shaped `<h2>`s in rendered HTML are what actually earns AI citations. `llms.txt` flagged the same way (97% of files got zero requests across a 137k-domain study; no vendor commitment to read it). B4 (prerendering/SSR) expanded with the evidence that ~69% of AI crawlers do not execute JavaScript, making this the single highest-leverage rule in the file.
537
+ - `payload/RULE-docs.md` B1 (renamed "Plan lifecycle & Filename Rules"): no date prefixes in doc filenames (record dates in metadata instead); prioritize creating a `docs/plan/` entry for any code/architectural change, naming it with the target version increment when execution can't wait for the plan.
538
+ - `payload/RULE-release.md`: new tag-gating bullet — skip tag creation entirely if the project has never tagged (`git tag -l` empty), leave CHANGELOG/releases.json/GitHub Release as the sole authority. B1's boundary-commit step 4b rewritten from "git tags" to a stack-specific **production baseline verification** (App: remote tags + GitHub Releases; Web/AkiNuxtCf: remote `releases.json` / remote tags) — reflects that local tags can't be trusted alone. A5 marked `<!-- A5 under review -->`, pointing at new `docs/plan/release-a5-review.md` (its content is not summarized here — the review is still open).
539
+ - `payload/RULE-ui-pattern.md` new §A4 "Framework-native scale first": check the framework's own default scale (`text-sm`, `rounded-lg`, …) before minting a custom design token; never duplicate a framework scale "for consistency" — that is itself a Law 1 (SSoT) violation. When cleaning up scattered ad-hoc values, snap each to the nearest existing step by midpoint rather than minting one token per raw value found in the wild, and treat a repeated drift pattern across multiple pages as one systemic token-layer gap rather than N one-off fixes.
540
+
541
+ ### Fixed — `install.sh` Antigravity skill delivery
542
+ - `install.sh`: Antigravity skill delivery was broken — `skills.json` used `~/.aki/claudedoc/agskills` (tilde path) which AG's JSON parser does not expand. Skills were invisible to all three AG surfaces despite being on disk.
543
+ - `install.sh`: `skills.json` now registers both the absolute path (`/home/<user>/.aki/claudedoc/agskills`) and the tilde path as fallback.
544
+ - `install.sh`: Added primary skill delivery via direct rsync to `~/.gemini/config/skills/` (Standard Global Customizations Root), bypassing `skills.json` entirely for native auto-discovery. Belt-and-suspenders: native root for guaranteed discovery, `skills.json` as secondary.
545
+
546
+ ### Changed
547
+ - `install.sh`: `trigger: glob` rules (`stack-tauri`, `stack-akiNuxtCf`) confirmed working correctly — they are intentionally absent from the initial context dump (token budget optimization) and only injected when the user interacts with files matching the glob pattern (`.rs`, `.vue`, `tauri.conf.json`, etc.).
548
+
549
+ ### Verified
550
+ - Cross-platform verification of full AkiClaudeDoc install across 4 surfaces: AG IDE (Mac), AGY CLI (Linux), Claude Code (Mac), Claude Code (Linux). All 5 custom skills (akigitcommit, akihelp, akihtmlreport, akirule, akithink) confirmed loaded. All 13 rules confirmed deployed with correct trigger types (1 always_on, 10 model_decision, 2 glob).
551
+
552
+ ### Note
553
+ - The 2026-07-22 entry below had mislabeled a `payload/GEMINI.md` directive number (said `11`, file has `10`) — corrected in place. The 2026-07-21 (2) entry's claim that directives `7`/`8` are the no-trailer rule / named-local-corpora is now stale (later directive insertions shifted numbering; the standalone no-trailer directive no longer exists as its own item, only as a mention inside the `10` audit checklist) — flagged inline rather than silently rewritten, since it's unclear whether dropping the standalone directive was intentional.
554
+
555
+ ## 2026-07-22
556
+
557
+ ### Added
558
+ - `install.sh`: the rule corpus is now installed to `~/.gemini/config/rules/akirule-*.md` as **native Antigravity rules**, read by all three surfaces (AG desktop, AG IDE, AGY CLI). Verified by canary before implementing, and verified after: `agy` launched from an unrelated empty directory quotes the marker, confirms the no-trailer rule, and lists the on-demand rules by name. `RULE-agent-behavior` gets `trigger: always_on`; the rest get `trigger: model_decision` with a generated description — Antigravity silently truncates customizations past an internal budget, so unconditional loading is spent on behavior rules only. Frontmatter is generated at install time so `payload/` stays agent-neutral (Claude Code has no equivalent concept). Files are namespaced `akirule-*` and pruned before each install so renamed or dropped rules do not linger.
559
+ - `payload/GEMINI.md`: `0. PRIME DIRECTIVE` (stay inside the requested scope), restated as `3` and `4`. The repetition is deliberate and documented as such at the top of the file — acting outside the requested scope is the most expensive observed failure mode, so the prohibition is placed first and re-asserted rather than stated once. Also `10` — at every high-stakes milestone (long plan finished, release, deploy) the agent must end with a prominent warning block handing the user a ready-to-paste prompt for an independent final audit covering rule compliance, gaps/edge cases, and code quality (clean code, SOLID, DRY, native logic flow), explicitly requiring both under- and over-engineering to be reported. (Corrected 2026-07-23: this was mislabeled `11` — the file has 11 directives numbered `0`–`10`, not 12.)
560
+ - `docs/plan/antigravity-rule-delivery.md`: the full plan for serving rules to Antigravity — three surfaces, the two discovery systems, the trigger enum, the silent truncation budget, hooks, the `skills.json` inheritance approach, and an AG-specific writing style derived from the vendor's own built-in skills.
561
+
562
+ ### Fixed
563
+ - `docs/arch/rule-delivery-architecture.md`: the Gemini side was described as an `@import` in both the prose and the mermaid diagram, and carried an "open verification: does the Antigravity IDE honor imports?" risk. The installer has always concatenated `GEMINI.local.md` verbatim, so the risk never existed. Corrected in both places.
564
+ - `docs/research/antigravity-rule-discovery-architecture.md`: added a verification-status banner separating what is empirically confirmed (`~/.gemini/GEMINI.md` is loaded by all three surfaces) from what is not (the claimed `GEMINI.md`-over-`AGENTS.md` precedence, which the vendor's bundled spec contradicts by treating both as the same customization type). Also removed a hardcoded machine path from a public doc.
565
+
566
+ ## 2026-07-21 (2)
567
+
568
+ ### Added
569
+ - `payload/RULE-agent-behavior.md`: new `B4` — **no model-credit trailers in git artifacts (ABSOLUTE)**. Promoted from a single bullet buried in `B1` (scope discipline) to its own addressed item, because it kept being violated in practice. Root cause: several agent harnesses inject a *standing system-level instruction* to append `Co-Authored-By:` / session-URL / "Generated with …" lines to every commit and PR body; a lone bullet in a rule file loses to a system prompt. `B4` therefore states explicitly that it **overrides the harness default**, enumerates every forbidden variant, gives the accountability rationale (commit history records which human approved the change; a model trailer corrupts `git blame`/`shortlog` attribution and leaks conversation URLs into public repos, unremovable without rewriting history), and — instead of relying on memory — prescribes a procedure: strip before `git commit`, verify after with `git log -1 --format=%B`, amend if it slipped through.
570
+ - `payload/GEMINI.md`: directives `7` (same no-model-credit-trailer rule, AG wording) and `8` (named local corpora resolve via the machine-local section appended at the end of the file). (Note as of 2026-07-23: later directive insertions shifted numbering and the file no longer carries a standalone no-trailer directive — only a passing mention inside the `10` audit checklist. Flagged for review; not corrected here since it's unclear whether the standalone directive's removal was intentional.)
571
+ - `install.sh`: injects a `## 9. Shared rule source` block into `~/.gemini/GEMINI.md` with this machine's real `.source-repo` / `install.sh` paths — the AG-side mirror of the block already injected into `~/.claude/CLAUDE.md`. AG has no reliable soft import, so the paths are written in literally.
572
+
573
+ ### Changed
574
+ - `claude/CLAUDE.md`: "editing shared rules" no longer says the source location "varies per machine — ask the user". `install.sh` has always recorded the absolute path in `~/.aki/claudedoc/.source-repo`; the guidance now points at that file (ask only if the recorded path is gone) and adds an explicit step to **read `<source-repo>/CLAUDE.md` before editing** — it lists the files that must be updated together, and it is *not* auto-loaded when the request arrives from another project's working directory. New "Named local corpora" section: corpora referred to by short name resolve via `~/.claude/CLAUDE.local.md` (machine-specific, deliberately not in this shared file).
575
+ - `payload/GEMINI.md`: header note corrected — `GEMINI.local.md` is **appended verbatim** by the installer, not soft-imported. (The earlier `@import` wording described a mechanism that was never used, and whose support in the Antigravity IDE was unverified.)
576
+ - `GEMINI.md` (per-project bootstrap template): the recovery instruction no longer tells the agent to auto-execute a hardcoded `~/.aki/claudedoc/install.sh` — **that path never existed**, the installer is not deployed there, so the instruction always fell through to its "clone from GitHub and run it" branch. Rewritten around the actual root cause of the ask/don't-ask gate: running an *already-present local* `install.sh` (path from `.source-repo`) is reversible and backed up, so the agent proceeds without asking; *cloning and executing unreviewed remote code* is a different class of action and stays the user's call.
577
+ - `payload/RULE-design-core.md`: `A7` now declares itself the **root rule for naming** and enumerates its domain applications (`agent.C1`, `ui.A`, `stack.C1`, `release.A3`, `content.A3`), which must stay in their own files.
578
+ - `payload/RULE-coding.md`: `B1`'s "use clear, descriptive names" removed — it was an empty restatement of `design.A7`; replaced by a pointer.
579
+ - `payload/index.md`: new **Cross-cutting lens** section — an address map (addresses only, never rule text) for subjects that legitimately span several files, seeded with `Naming`. Rejected the alternative of extracting a new `RULE-naming.md`: the scattered naming items are *domain applications*, not duplicates, so a new file would have removed nothing and made naming live in six places instead of five, plus one more router signal that can fail to fire.
580
+
581
+ ## 2026-07-21
582
+
583
+ ### Added
584
+ - `payload/GEMINI.md`: new managed source file for Antigravity/Gemini global behavior overrides, installed to `~/.gemini/GEMINI.md` (not synced into the rule corpus). Six hard-loaded directives patch Antigravity's known weak spots — unrequested `implementation_plan.md`/`task.md`/`walkthrough.md` artifacts, over-engineering, hallucination, verbosity, plus command transparency and an ambiguity/safety gate. Rationale: Claude Code loads the rule corpus via harness-guaranteed `@`-imports (0 soft hops); Antigravity has no such loader, so behavior rules must sit in the one file it *does* hard-load globally, rather than depending on a chain of "please read" pointers the model can skip. Line 1 carries a version marker `[AKIRULE-AG-OVERRIDES-<version>]` so a per-project bootstrap can detect whether the overrides are present. The file ends with `@~/.gemini/GEMINI.local.md` for machine-local facts.
585
+ - `install.sh`: new block installs `payload/GEMINI.md` to `~/.gemini/GEMINI.md`, stamping the version marker (`V<date>[-<git-hash>]`) in the same pass. Mirrors the existing CLAUDE.md/CLAUDE.local.md pattern: timestamped backup + pruning, and a sibling `~/.gemini/GEMINI.local.md` that is created only if missing and never overwritten. An existing unmanaged `GEMINI.md` (no marker) is backed up and replaced; the installer does **not** parse its contents — there is no universal way to know where an arbitrary user's machine-local section begins, so it never guesses by heading name. Because this install is usually driven by an AI agent (which *can* judge content semantically), it instead prints a strong, explicit directive telling the running agent to read the backup and the managed file and append **only the non-duplicate** machine-local lines into `GEMINI.local.md` (append-only, backup preserved — safe to do without a confirmation round-trip). `GEMINI.md` is excluded from the payload rsync so it never lands in the installed rule corpus.
586
+
587
+ ### Docs
588
+ - `docs/arch/rule-delivery-architecture.md`: new architecture doc (with mermaid flowcharts) covering the Claude-Code-vs-Gemini loading asymmetry, the managed/`.local.md` split, the two install scenarios, the agent-driven de-duplication directive, and the version marker.
589
+ - `README.md`: repository layout, "What the installer does" (step 7 + a "Gemini / Antigravity model" note), and uninstall updated for the new `~/.gemini/GEMINI.md` target.
590
+
591
+ ## 2026-07-19 (2)
592
+
593
+ ### Added
594
+ - `payload/RULE-release.md`: new `A5` — a version number is minted at the **release event** (production deploy / published tag / distributed build), never when a piece of work is finished. Between releases the accumulation lives under `## [Unreleased]` with no version number and no manifest bump; the release task renames that heading and bumps once. Closes a real gap: `B1` only guaranteed *one bump per cycle*, so several sessions of local improvement each bumped legitimately and the local version drifted far ahead of what was actually shipped — production on `0.1.0` while local sat at `0.3.4`, then a deploy dumped a stack of thin versions on users at once. Adds a materiality test (don't mint a version for one or two trivial internal lines) and a recovery path: versions never published are **not** covered by `B3`'s "never renumber public versions", so they can be squashed back and re-minted as one. `B1`'s state table gains an `Unreleased open` row (normal working state) and a `Drifted` row (manifest ahead of last deployed version → run the A5 recovery first).
595
+ - `payload/index.md`: `RULE-release.md` manifest description extended to mention the release-event minting rule.
596
+
597
+ ## 2026-07-19
598
+
599
+ ### Changed
600
+ - All 13 `payload/RULE-*.md` / `METHOD-*.md` files: restructured into internal groups `A`/`B`/`C` with numbered items `1`/`2`/`3…` (no content added or removed, no file renamed). Gives every rule a stable, recallable address (`topic.A1`, e.g. `coding.B2`, `stack.C1`) for a user juggling many projects at once. `payload/index.md` gains a Topic/Loại column and the full group map; `claude/skills/akirule/SKILL.md` documents the addressing scheme (routing logic itself is unchanged); `README.md` documents the scheme for public readers.
601
+ - `RULE-seo.md`, `RULE-release.md`, `RULE-stack-akiNuxtCf.md`: the content specific to Aki's own AkiNuxtCf ecosystem (rather than universal for any project) is now isolated into each file's last group, logically flagged `⟨Aki⟩` (`seo.C`, `release.C`, `stack.C`). This repo predates `AkiNuxtCf/UNIDOC` (Aki's private ecosystem-standards repo) and had accumulated ecosystem-specific content without a clear boundary from universal rules. Decision: keep everything in this repo with auto-load rather than relocating to UNIDOC or gating behind an explicit trigger — Aki is this repo's heaviest user and the convenience of automatic reminders outweighs a physically clean public/private split. The `⟨Aki⟩` flag is documentation-only for now (marks what a future stripped public export would drop); no automatic filtering mechanism yet. Full decision record: `docs/research/public-private-abc-restructure.md`.
602
+
603
+ ## 2026-07-18
604
+
605
+ ### Changed
606
+ - `payload/RULE-stack-akiNuxtCf.md`: public/private boundary cleanup + restructure (no rule content added or removed):
607
+ - Removed private-corpus leaks unusable by public readers: the `UNIDOC STANDARD.md §2.4` citation and lock date on the build-date-stamp rule (technique kept, now described generically), the undefined `[DESIGN-LOCK]` tag, the project-specific `que`↔`iching` slug example (replaced with a neutral `bai-viet`↔`articles` pair), and the unexplained "akinuxtstack" name (now "this stack").
608
+ - Deduplicated `trailingSlash: true` from three in-file statements down to one canonical spot (the i18n section's config block); the Cloudflare-constraints bullet now points there.
609
+ - Moved the six admin-related bullets (English-only + `i18n.pages` routing, `localePath()` undefined-href trap, layout isolation, feature-area routing, listener cleanup) out of "Rendering" into their own "Admin UI" section; merged the two `aki-info-detect` bullets into a "Client detection" section with a link to the public npm package.
610
+ - Merged the three adjacent layout sections (canonical component names, layout chrome, layout width) into one "Layout" section with subsections; merged the two SSR-guard bullets; shortened the favicon-generator recommendation to its essentials.
611
+ - `payload/RULE-agent-behavior.md`: new "File formatting" section — do not auto-wrap a line just because it is long; keep one logical bullet/sentence per physical line, and only break lines for genuinely intentional structure (tables, code blocks, nested sub-bullets). Match the existing file's own wrapping convention when editing it. Added after a rule-cleanup pass introduced unintended mid-sentence line wraps that the user then had to flag and have reverted.
612
+ - `install.sh`, `claude/hooks/aki-update-check.py`: translated all Vietnamese console output (status checks, install summary, confirmation prompt, update-check banner) to English — this repo is public, so its runtime output should not assume a Vietnamese-reading operator. Colors/emoji/logic unchanged.
613
+
614
+ ### Added
615
+ - `payload/RULE-stack-akiNuxtCf.md`: added a rule to pin `packageManager` and `engines.node` in `package.json` to match the Cloudflare Pages build image, and to regenerate lockfiles via `npx npm@<pinned_version> install` before committing to avoid version drift with optional peer dependencies.
616
+ - `payload/RULE-agent-behavior.md`: new "Memory discipline" section — never write, update, or delete a persistent memory (any memory file or the `MEMORY.md` index) on your own initiative; always ask the user first. Only persist when the user explicitly asks, or after proposing a specific memory and getting approval. Recalling/reading existing memory needs no permission — the gate is on writing. Originated from a memory-cleanup pass across the Aki projects where the user found that self-initiated memory writes had accumulated a large amount of redundant/stale notes (facts already covered by AkiClaudeDoc / UNIDOC / project `CLAUDE.md`).
617
+
618
+ ## 2026-07-16
619
+
620
+ ### Added
621
+ - `payload/RULE-stack-akiNuxtCf.md`: new "Layout width — single source of truth" section — the layout's outer content wrapper (e.g. `max-w-7xl mx-auto px-4 sm:px-6 lg:px-8`) is the only place page/content width is decided; pages and app/tool pages must never put their own `max-w-*`/custom `max-width` on their outermost element, and any that already do must be deleted so they inherit the layout's width instead. Carves out the standard exception for inner reading-measure/widget elements (intro paragraph, search box, article prose column), which is typography sizing, not page layout. Traced to a real incident in `app.akinet.me`: articles hub/detail, the releases page, `me.vue`, and all 10 mini-apps had each independently picked a `max-w-*` value (`max-w-3xl` through `max-w-7xl`, plus one page with a scoped-CSS width fully disconnected from the layout) nested inside the layout's own wrapper, silently narrowing/drifting per route with no functional reason.
622
+ - `payload/index.md`: extended the `RULE-stack-akiNuxtCf.md` manifest description to mention layout width (single source of truth in the layout, pages/apps never redeclare `max-w`).
623
+
624
+ ## 2026-07-13
625
+
626
+ ### Changed
627
+ - `payload/RULE-coding.md`: replaced the single "read enough surrounding context" bullet with a "Changing existing code" section giving a before/after procedure for editing code you didn't just write — read referenced docs and code before changing (Chesterton's Fence), then confirm untouched intents/flows still hold after the change (a fix scoped to problem X must not silently break unrelated property Y).
628
+
629
+ ## 2026-07-12
630
+
631
+ ### Changed
632
+ - `payload/RULE-docs.md`: added `docs/biz/` as a standard, MANDATORY top-level doc topic — the business backbone (identity, USP, positioning, monetization) for any project with a business dimension. Added a "Business backbone" section making it the spine that all `arch/`/`feat/`/`plan/` product/money docs must reference, and the tie-breaker when code intent and a `biz/` doc disagree (the `biz/` doc wins). Originated from the vstshop.com repositioning work, where business strategy became the declared backbone.
633
+ - `payload/index.md`: updated the `RULE-docs.md` manifest description to note the mandatory `docs/biz/` backbone.
634
+ - `payload/RULE-stack-akiNuxtCf.md`: documented a new gotcha under the admin-SPA / `i18n.pages[x] = false` guidance — once a route is removed from i18n routing, links to it must use a plain string `to="/..."`, never `localePath()`/`switchLocalePath()`. `localePath()` silently returns `undefined` for such a route (no error, no console warning), so `<NuxtLink :to="undefined">` renders an `<a>` with no `href` at all — a link that looks correct in code review but never navigates. Traced to a real incident in `app.akinet.me` (sidebar `/me` link copied from `kinhdich.akinet.me`, where `/me` keeps normal i18n routing — but `app.akinet.me` disables it via `i18n.pages.me = false`, so the copied `localePath('/me')` call broke silently).
635
+ - `CLAUDE.md` (repo root, not `payload/`): added an explicit operating rule — any change to `payload/*` or `claude/skills/*` that adds/removes a topic or changes install behavior must also update `README.md` where it goes stale; `akihelp` reads live installed state so it's exempt from manual content updates; `CHANGELOG.md` must be updated for every `payload/`/`claude/` change. Closes the gap where the `docs/biz/` rule change above shipped without a README/CHANGELOG pass until the user asked for it.
636
+
637
+ ## 2026-07-11
638
+
639
+ ### Added
640
+ - `docs/research/versioning-critique-akithink.md`: structured decision record (/akithink) analyzing and refining the versioning rewrite proposal.
641
+
642
+ ### Changed
643
+ - `payload/RULE-release.md`: rewrote the versioning rules to use cold-start version reconstruction (unbounded git log checks with robust boundary commit fallbacks), severity-driven bump logic, and a legacy audit mode. Hardened the rewrite: restored the Pre-bump/Mid-release/Mismatch state table (double-bump guard), made the CHANGELOG-diff pickaxe (`git log -S`) the primary boundary-commit anchor with fixed-string message grep demoted, added user confirmation on ambiguous fallback, a fresh-repo case, the smaller-level tie-breaker, and an audit-mode rule against inventing unknown historical content.
644
+ - `payload/index.md`: updated manifest description for `RULE-release.md` to reflect cold-start versioning and audit mode.
645
+ - `payload/RULE-stack-akiNuxtCf.md`: documented the `__BUILD_DATE__` (footer build stamp) standard, specifying build-time JS computation via `vite.define` and client-side rendering within `<ClientOnly>` to avoid hydration mismatches.
646
+
647
+ ## 2026-07-10
648
+
649
+ ### Added
650
+ - `payload/RULE-design-core.md`: new Contextual (high-sensitivity) rule — the universal, stack-agnostic pattern-design philosophy (SSoT, Rule of Three, SRP "and"-test, OCP, composition over duplication, module boundaries, name-by-role, anti-patch). Sharpens `RULE-coding.md` without restating it and defers UI-specific enforcement to `RULE-ui-pattern.md`. Registered in `index.md`, the akirule Tier 2 signal block, and `README.md`.
651
+ - `payload/RULE-ui-pattern.md`: new Contextual rule — the frontend enforcement of `RULE-design-core.md` (4-tier class taxonomy, design tokens as the single source for visual values, arbitrary-value policy, atomic component structure, variant API, and a UI audit/refactor playbook). Registered in `index.md`, the akirule Tier 2 signal block, and `README.md`.
652
+
653
+ ### Changed
654
+ - Tier vocabulary normalized to exactly three canonical labels — **Core / Contextual / Analytical** — across `payload/index.md`, `README.md`, `claude/skills/akirule/SKILL.md`, and the rule headers. Dropped the drift-prone variants "Core-adjacent" (`RULE-design-core.md` is Contextual high-sensitivity) and "Optional/Contextual" (`RULE-db-design.md` is Contextual), so every label now matches the actual routing mechanism. `RULE-design-core.md` is Contextual, not Core, on purpose: embedding it in Tier 1 would tax every conversation for every user; its near-universal reach is served by broad signals instead.
655
+ - `README.md`: added `RULE-design-core.md` and `RULE-ui-pattern.md` to both the tier list and the repository-layout tree (they were missing); rewrote the routing section so its "three tiers" match `akirule/SKILL.md` exactly — Tier 1 Core (embed), Tier 2 Contextual (contextual rules plus the signal-loaded analytical methods), Tier 3 Full-load on explicit command — instead of mislabeling the analytical methods as "Tier 3".
656
+ - `install.sh`: the post-install "Rules deployed" summary parser now accepts multi-word tier cells (regex `(\w+)` → `([^|]+?)`, plus a tolerant color lookup), so rows like `RULE-design-core.md` and `RULE-db-design.md` are no longer silently dropped from the printed manifest.
657
+ - `claude/skills/akihtmlreport/SKILL.md`: never `Read` an existing `REPORT.html` (it is large, dense HTML and the skill always regenerates it wholesale) — inspect metadata only; a stale file (older than ~12 h) is deleted without reading, a recent one still prompts. The generation timestamp is computed in UTC and rendered in the viewer's local time via inline JS; a compact table of contents with per-section `id` anchors is required at the top; a short final-summary section is now mandatory at the end. Evaluation reports (refactor/code-review/strategy/idea assessments) must also surface each item's side effects and edge cases as a first-class element, keep the MVP recommendation as the headline, and split autonomous-decidable from needs-user-decision. Added an optional glossary/notes appendix as the very last section for reports leaning on jargon or abbreviations.
658
+ - `.gitignore`: ignore the disposable `REPORT.html` visual export.
659
+ - `payload/RULE-coding.md`: expanded the lone `atob()` note into a **Unicode / UTF-8 safety** subsection — base64/JWT decoding via `TextDecoder`, NFC normalization before compare/store/dedupe/ keys, byte (not `str.length`) measurement for size and length limits, and codepoint-safe truncation.
660
+ - `payload/RULE-stack-akiNuxtCf.md`: expanded the Cloudflare/Workers Unicode note — decode Firebase/JWT payloads via `TextDecoder` (with an explicit "corruption is an app-layer bug, D1 stores the bad bytes faithfully" clarification), percent-encode non-ASCII header/cookie values, count response size / `Content-Length` in bytes, and feed `crypto.subtle` encoded bytes.
661
+ - `payload/RULE-db-design.md`: added section 5 "The DB is not your Unicode safety net" — SQLite/D1 stores UTF-8 faithfully but does not prevent mojibake (fixed at the decode/compare layer per `RULE-coding.md`); the one schema-level concern is using `utf8mb4`, never 3-byte `utf8`, on MySQL/MariaDB.
662
+ - `payload/METHOD-deep-think.md`: added Module 5 "MVP focus, side-effects & edge-cases weighed by severity" — an evaluation discipline (not business-gated, unlike Module 4). The MVP keeps the focus of effort, but SFX/EC are weighed by severity, not sequence: it is a feedback loop, not a one-way pipeline, so a material side-effect/edge-case can reshape or reopen the MVP itself. Scoped to the four cases of *discussing or evaluating* (not executing) a refactor, a code review, a strategy/plan, or an idea; trivial risks named out-of-scope, severe ones promoted immediately. On promotion, the agent resolves what first-principles/critical-thinking can settle (decide + report) and escalates to the owner only for genuine owner-calls (irreversible / cross-boundary / unverifiable) per `RULE-agent-behavior` Decision boundaries — not for what basic reasoning settles.
663
+ - `claude/skills/akirule/SKILL.md`: `METHOD-deep-think` now auto-loads on evaluation/discussion signals (`evaluate`, `assess`, `worth refactoring`, `side effect`, `edge case`, `đánh giá`, `bàn luận`, `đánh giá ý tưởng`, `đánh giá chiến lược`, …) so Module 5 fires on the four cases.
664
+
665
+ ## 2026-07-08 (2)
666
+
667
+ ### Added
668
+ - `payload/METHOD-deep-think.md`: replaces `METHOD-techbiz-optimizer.md` as the single analytical brain for deep thinking, consumed two ways — **passive** (akirule auto-loads it inline on matching signals) and **active** (`/akithink`). Restructured into 4 modules: Module 1 goal excavation (climb the goal hierarchy to the ultimate goal, flag conflicting goals), Module 2 first principles (facts / real constraints / assumptions, reusing the old file's "Problem truth" / "Assumptions" / "Flow" material), Module 3 critique (mandatory adversarial pass — steelman, attack-the-favored-option, inversion, pre-mortem, second-order effects, anti-sycophancy rule), Module 4 techbiz lens (conditional — the old file's value/effort/scope/cost/alternatives/ validation/decision-test/red-flags content, applied only when business/product context exists). Adds a one-way-door vs two-way-door framing and a closing radar rule: passive mode must say "this deserves a dedicated `/akithink` session" rather than settle for a shallow pass on irreversible or goal-ambiguous decisions.
669
+ - New skill `akithink` (`claude/skills/akithink/SKILL.md`): structured 5-phase deep-thinking session (model check → restate → goal excavation → first principles → mandatory critique → convergence) for big, hard-to-reverse, or goal-ambiguous decisions. Explicit-invoke only, reads `METHOD-deep-think.md` as its toolbox, recommends a top-tier model (Opus/Fable) without blocking, supports a "chốt" escape hatch to jump to convergence, and always proposes a `docs/` decision record on close (plus `/akihtmlreport` when the material is large/complex).
670
+ - New skill `akihelp` (`claude/skills/akihelp/SKILL.md`): `/akihelp` renders a live introduction to the whole Aki system (installed skills, the akirule 3-tier router, the deep-think passive/active split, editing-rules discipline) by reading `index.md` and installed skill frontmatters at runtime — never a hardcoded inventory, so it cannot go stale.
671
+
672
+ ### Changed
673
+ - Renamed skill `akiadvise` → `akihtmlreport` (`claude/skills/akihtmlreport/SKILL.md`). Output filename `ADVISE.html` → `REPORT.html` everywhere (single-file rule, collision check, `.gitignore` guidance); invocation `/akiadvise` → `/akihtmlreport`; description sharpened to state the single purpose plainly (visualize existing conversation content, no new analysis); "After writing" now opens the file locally (`open REPORT.html` on macOS, `xdg-open` fallback on Linux, falls back to just printing the path) instead of refusing to launch a browser; notes it pairs naturally with `/akithink` Phase 5 output.
674
+ - `payload/index.md`: manifest row `METHOD-techbiz-optimizer.md` → `METHOD-deep-think.md` with updated purpose text.
675
+ - `claude/skills/akirule/SKILL.md`: Tier 2 signal block renamed `METHOD-techbiz-optimizer.md` → `METHOD-deep-think.md`; added thinking-session signals (`first principles`, `tư duy nguyên bản`, `phản biện`, `mục tiêu tối thượng`, `one-way door`, `quyết định lớn`, `decision record`, `pre-mortem`).
676
+ - `install.sh`: added `akiadvise` to the old-skill directory cleanup loop so renamed installs don't leave a stale skill; added an explicit `rm -f` for `~/.aki/claudedoc/METHOD-techbiz-optimizer.md` as a safety net alongside the `rsync --delete` payload sync.
677
+ - `README.md`: repo-layout tree, install-target file list, and prose updated for the `akithink`/`akihtmlreport`/`akihelp` skills and `METHOD-deep-think.md`; added a "One brain, two modes" section explaining the passive/active thinking architecture.
678
+ - `README.md`: full rewrite for concision — install command leads, skills presented as a table, installer behavior condensed to one numbered list, duplicate install-target section merged into the layout tree. Fixed the layout tree and akirule Tier 2 description, which were missing `RULE-seo.md`, `RULE-release.md`, and `RULE-db-design.md`; uninstall section now covers all five skills and the update-check hook.
679
+
680
+ ## 2026-07-08
681
+
682
+ ### Added
683
+ - Notify-only update-check hook (`claude/hooks/aki-update-check.py`), installed to `~/.claude/hooks/` and registered as a Claude Code `SessionStart` hook (`startup|resume`). On session start it compares the installed `CHANGELOG.md` top entry against the public repo copy (`raw.githubusercontent.com/lacvietanh/AkiClaudeDoc/master/CHANGELOG.md`); when the remote is newer it prints a user-visible `systemMessage` with the "what's new" delta, the update command, and the changelog link, and passes the same delta to Claude via `additionalContext`. Fail-silent (any error/offline → exit 0, no output), throttled to once per 24h, and never auto-updates — it only points at `git pull && bash install.sh`. Uses the CHANGELOG top header as the version marker, so there is no separate version file to bump. Does not nag machines whose local changelog is ahead of the remote (dev checkouts).
684
+
685
+ ### Changed
686
+ - `install.sh`: copies the update-check hook into `~/.claude/hooks/`, writes `~/.aki/claudedoc/.source-repo` (this machine's source repo path, so the hook can print the correct update command), and registers the `SessionStart` hook in `settings.json` idempotently (drops any prior `aki-update-check` entry before adding the current one). Post-install summary now lists deployed hooks.
687
+ - `README.md`: documented the update-check hook in "What the installer does", the repo layout, and the install-target file list.
688
+
689
+ ### Fixed
690
+ - `README.md`: one-line install command pointed at the non-existent `main` branch (`raw.githubusercontent.com/lacvietanh/AkiClaudeDoc/main/install.sh` → 404); corrected to `master`, the repo's actual default branch.
691
+
692
+ ## 2026-07-07 (3)
693
+
694
+ ### Added
695
+ - New skill `akiadvise` (`claude/skills/akiadvise/SKILL.md`): distills a complex analysis/report already discussed in conversation into a single-file, ultra-wide, visually dense HTML report (`ADVISE.html`, default at project root). Enforces a single-file discipline (one `ADVISE.html` per project at a time — never `ADVISE-2.html`/versioned variants; asks before overwriting an existing one) and only applies to genuinely dense/complex content, never proactively.
696
+
697
+ ## 2026-07-07 (2)
698
+
699
+ ### Added
700
+ - `RULE-stack-akiNuxtCf.md`: Admin layout isolation rules in Rendering — the admin layout owns its own chrome (`AdminSidebar.vue`, added to the canonical component names table) and never imports public chrome components; each admin feature area gets its own route under `/admin/**` instead of tab-state inside one page.
701
+ - `RULE-stack-akiNuxtCf.md`: New "Dev workflow scripts (package.json)" section — `killport` + `dev` chaining with a pinned per-site dev port; `db.init.local`/`db.push` patterns for projects with a D1 database.
702
+
703
+ ### Changed
704
+ - Generalized ecosystem-specific wording so every rule stands alone for public readers: `RULE-stack-akiNuxtCf.md` deploy verification no longer names internal projects; `RULE-seo.md` entity-linking section now describes the parent/sibling pattern generically (concrete domain lists belong in each project's own docs), `/login` indexability is a default rather than a named-org policy, and the validate-seo baseline pointer no longer references an internal repo path. (Intentional exception kept: the AkiTao Favicon Generator tool link.)
705
+ - `payload/index.md`: Expanded `RULE-stack-akiNuxtCf.md` manifest description (admin layout isolation, dev workflow scripts).
706
+
707
+ ## 2026-07-07
708
+
709
+ ### Added
710
+ - `RULE-stack-akiNuxtCf.md`: New "Deploy verification — push is not done" section — a push only *requests* a Cloudflare build, task isn't closed until the newest build reaches a terminal state. Clarifies that most AkiNet projects deploy via **Cloudflare Pages**, not Workers — the `cloudflare-builds` MCP only covers the Workers Builds API and shows zero builds for a Pages project (confirmed against `kinhdich-akinet` 2026-07-07). Points to `wrangler pages deployment list` or the general-purpose `cloudflare` MCP (`https://mcp.cloudflare.com/mcp`) for Pages projects instead.
711
+ - `RULE-release.md`: "Release vs deploy — two different events" section separating release (CHANGELOG/releases.json/GitHub Release, all stacks) from deploy (web build going live, web-only, owned by `RULE-stack-akiNuxtCf.md`).
712
+
713
+ ### Changed
714
+ - `RULE-release.md`: Scope widened from "projects with CHANGELOG.md" to **every Aki project, any stack** — `CHANGELOG.md` is mandatory from project creation, a repo without one is broken not exempt. Clarified `releases.json` is web-only (exists only where a public release-notes page renders it); Tauri/CLI/non-web projects keep `CHANGELOG.md` only. "Identify the current version before bumping" now runs per closed problem, not once per session.
715
+ - `claude/skills/akigitcommit/SKILL.md`: No-CHANGELOG fallback reframed as exempting only non-Aki repos (every Aki repo must have one). Added "commit unit is one closed problem" rule — a problem's commit includes its code AND its CHANGELOG.md/releases.json entries, never batched into a separate catch-all commit.
716
+ - `payload/index.md`: Updated `RULE-stack-akiNuxtCf.md` and `RULE-release.md` manifest descriptions to reflect the above.
717
+
718
+ ## 2026-07-05
719
+
720
+ ### Added
721
+ - `RULE-db-design.md`: New optional/contextual rule file — four generalized database design principles (Immutability & Event Sourcing, First Normal Form, Bounded Context/DDD, flat-query discipline). Loads only when designing schema/migrations/DB refactors, not on every task.
722
+
723
+ ### Changed
724
+ - `RULE-stack-akiNuxtCf.md`: Added "Build & TypeScript" section (strict TS, `<script setup>` only, relative server imports, clean build logs, duplicate-Vite sourcemap-warning guidance). Added "Canonical component names" section (fixed names for footer/topnav/sidebar/rail-dock/ breadcrumb/auth-util roles). Added "State" section (useState-first, Pinia only when needed, localStorage sync in `onMounted`). Added onUnmounted cleanup requirement for multi-layout admin sites. Added favicon/manifest UI guidance with a link to the AkiTao Favicon Generator tool. Added i18n co-located page-text guidance. Added `aki-info-detect` loading discipline: use only named local-only exports, never default-import or plugin-load the whole library because it starts network lookup; require explicit requests for network features and verify IP-service URLs are absent from the built chunk.
725
+ - `payload/index.md`: Added manifest row for `RULE-db-design.md`; expanded `RULE-stack-akiNuxtCf.md` description to mention canonical names, state, and build/TS.
726
+ - `claude/skills/akirule/SKILL.md` (source): Added Tier 2 signal block for `RULE-db-design.md`.
727
+
728
+ ---
729
+
730
+ ## 2026-06-28
731
+
732
+ ### Changed
733
+ - `RULE-release.md`: Expanded "Identify the current version before bumping" — now requires running three commands (`git log`, `grep package.json`, `grep CHANGELOG.md`) before touching any version. Defines three states: **Pre-bump** (package.json == git → bump once), **Mid-release** (package.json > git → accumulate, do not bump again), **Mismatch** (warn, do not auto-fix). Added bump-level guard: same session features+fixes → minor; unsure → smaller level; no version skipping; do not bump until at least one user-visible change exists.
734
+ - `RULE-release.md`: Added **"GitHub Release output"** section — after CHANGELOG update and version bump, automatically output a copy-ready GitHub Release block without waiting for the user to ask. Title: `v{version} — {2–5 word specific impact}`, no generic words. Body mirrors CHANGELOG but one short sentence per bullet, no file paths, no jargon.
735
+ - `install.sh`: Replaced machine-local block extraction with a clean two-file model. `CLAUDE.md` is fully managed by installer; machine-local config lives in `~/.claude/CLAUDE.local.md` (never overwritten after first creation). Installer appends `@~/.claude/CLAUDE.local.md` import + machine-local source-path block to `CLAUDE.md` on every run. Creates `CLAUDE.local.md` from template on first install only.
736
+ - `README.md`: Updated "What the installer does" and "Install target" to document the `CLAUDE.local.md` pattern. Added "Machine-local configuration" section.
737
+
738
+ ---
739
+
740
+ ## 2026-06-27 (4)
741
+
742
+ ### Changed
743
+ - `RULE-release.md`: Added two new sections. **"No version gaps in releases.json"** — every CHANGELOG version must appear in releases.json; internal/technical versions must not be skipped but instead summarized with a brief user-friendly entry (patterns provided for `improved`/`fixed` types). **"Sync check"** — mandatory grep before closing any task touching CHANGELOG or releases.json, confirms no gap and correct newest-first order in both files.
744
+
745
+ ---
746
+
747
+ ## 2026-06-27 (3)
748
+
749
+ ### Added
750
+ - `RULE-stack-akiNuxtCf.md`: New "Layout chrome — breadcrumb · back-to-home · scroll-to-top" section codifying the unified layout-chrome standard for every akinuxtstack site, so future work cannot drift it back out of consistency. Locks the invariants learned during the breadcrumb rollout: exactly one layout-level `<Breadcrumb>` owning the VISUAL trail only; dynamic leaf via `useBreadcrumb()` + `<ClientOnly>` SSR fallback (hydration-safe); `BreadcrumbList` JSON-LD owned by the page, exactly once (never the layout, never duplicated when a SEO composable already emits it); crumb links only to real prerendered routes (dead intermediate segments render as plain text to avoid Nitro `no-error-response` 404s); translated-slug link reconstruction (`/en${acc}/`) instead of `localePath()`; a single `<ScrollToTop>` with back-to-home served by the Home crumb. Distilled from vstshop, akinet, akitao, kinhdich (incl. removing kinhdich's `SELF_MANAGED` exception so it fully rejoins the standard).
751
+
752
+ ### Changed
753
+ - `payload/index.md`: Extended the `RULE-stack-akiNuxtCf.md` manifest description to mention layout chrome (breadcrumb/scroll-to-top).
754
+ - `akirule/SKILL.md` (source): Added Tier 2 keywords to the stack-rule signal block (`breadcrumb`, `scroll-to-top`, `back-to-home`, `layout chrome`, `useBreadcrumb`).
755
+
756
+ ---
757
+
758
+ ## 2026-06-27 (2)
759
+
760
+ ### Added
761
+ - `RULE-release.md`: New Contextual rule for Aki projects that ship versioned releases (repo with `CHANGELOG.md` + `CLAUDE.md`, Nuxt or Tauri v2). Defines the two-channel split — `CHANGELOG.md` (technical, English, Keep a Changelog) vs `app/data/releases.json` (public, user-friendly, bilingual EN+VI when the site is multilingual, default EN). Specifies the bilingual `releases.json` schema, semver bump discipline (`major.minor.patch`, one release = one version, no stray bumps), how to identify the current version before bumping (changelog top entry / git tag / session context), and content discipline (no em/en dash, stable terminology). Distilled from the release-notes campaign across vstshop, akinet, akitao, kinhdich.
762
+ - `payload/index.md`: Added `RULE-release.md` to the file manifest.
763
+ - `akirule/SKILL.md` (source): Added Tier 2 signal block for `RULE-release.md` (keywords release/changelog/version/semver/bump + paths `CHANGELOG.md`, `releases.json`, `pages/releases/**`).
764
+
765
+ ---
766
+
767
+ ## 2026-06-27
768
+
769
+ ### Changed
770
+ - `claude/skills/akigitcommit/SKILL.md`: Thêm mode detection — tự check `CHANGELOG.md` trước khi group. Khi có CHANGELOG: dùng domain-grouped mode (group theo object/feature, tối đa 3–5 commits). Khi không có CHANGELOG: giữ nguyên type-grouped mode cũ (feat/fix/refactor). Cập nhật description trong frontmatter.
771
+ - `RULE-seo.md`: Sửa hướng dẫn title format — bỏ `| [Brand]` khỏi source title vì `@nuxtjs/seo` tự append qua `titleTemplate`. Thêm section `@nuxtjs/seo — titleTemplate behavior (CRITICAL)` với ví dụ ✅/❌ rõ ràng để tránh double-suffix. Sửa giới hạn `< 60` → `≤ 60`, thêm exception 80-char cho article/post/knowledge slug pages. Cập nhật post-build validation checklist: `>` thay `>=`, decode HTML entities trước khi đo độ dài, skip redirect stubs.
772
+ - `RULE-stack-akiNuxtCf.md`: Thêm rule `trailingSlash: true` bắt buộc trong i18n block — không chỉ `router.options` và `site`. Thiếu config này khiến `localePath()` strip trailing slash, gây canonical mismatch warning hàng loạt khi build.
773
+ - `claude/CLAUDE.md`: Thêm rule "Editing shared rules — luôn sửa từ source AkiClaudeDoc project rồi chạy install, không sửa trực tiếp vào bản đã install" để AI agent không sửa nhầm deployed copy.
774
+
775
+ ---
776
+
777
+ ## 2026-06-26 (2)
778
+
779
+ ### Added
780
+ - `RULE-seo.md`: New Contextual rule covering all SEO concerns — `usePageSeo` API contract, meta title/description limits and formatting, schema.org page-type matrix, Organization required fields, trailing slash, robots/sitemap exclusion, OG image convention, AI/LLM visibility (FAQ structure, DefinedTerm, alternateName), ecosystem entity linking (sameAs, parentOrganization), Vietnamese unaccented keyword handling, post-build validation checklist. Distilled from real patterns across akitao.com, vstshop.com, akinet.me, kinhdich.akinet.me.
781
+
782
+ ### Changed
783
+ - `RULE-stack-akiNuxtCf.md`: Removed inline SEO bullet list, replaced with single-line reference to `RULE-seo.md`.
784
+ - `payload/index.md`: Added `RULE-seo.md` to file manifest, updated stack rule description.
785
+ - `akirule/SKILL.md` (source): Added Tier 2 signal block for `RULE-seo.md`; removed `SEO` from `RULE-stack-akiNuxtCf.md` signals to avoid double-loading now that the stack rule defers to `RULE-seo.md`.
786
+ - `install.sh`: UX overhaul — added `print_summary()` with colored post-install table (rules by tier, skills deployed, timestamp + git commit hash); copies `CHANGELOG.md` to `$INSTALL_ROOT/CHANGELOG.md` so any machine can inspect installed version; writes `$INSTALL_ROOT/.version` (installed date, commit, branch); added `prune_backups()` keeping only the 2 most recent backups per file (was accumulating unbounded).
787
+
788
+ ---
789
+
790
+ ## 2026-06-26
791
+
792
+ ### Changed
793
+ - `RULE-coding.md`: Added `## Result pattern for external calls` section under Error handling — defines the `Result<T>` type pattern (`{ ok: true; data: T } | { ok: false; error: string }`) with code examples. Establishes the standard for all fallible I/O at system boundaries: composable/service catches once, callers check `.ok` without try/catch.
794
+ - `RULE-stack-akiNuxtCf.md`: Added `## External integrations` section — composable-as-boundary rule (pages never import provider SDK directly), domain-based module organization (`useAuth`, `useUser`, `useProjects` instead of god-file), cross-reference to Result pattern.
795
+
796
+ ---
797
+
798
+ ## 2026-06-24
799
+
800
+ ### Changed
801
+ - Standardized and improved `GEMINI.md` with professional English phrasing and structured bootstrap directives to align Gemini and Antigravity agents with the `CLAUDE.md` source of truth.
802
+
803
+ ---
804
+
805
+ ## 2026-06-19
806
+
807
+ ### Changed
808
+ - Replaced three separate skills (`akidoc-rules`, `akidoc-flow-audit`, `akidoc-techbiz-optimizer`) with a single unified smart-router skill `akirule`.
809
+ - `akirule` uses a 3-tier loading strategy: core rules always embedded, additional rules and methods read on demand when task signals match.
810
+ - Renamed `SKILL-flow-audit.md` and `SKILL-techbiz-optimizer.md` to `METHOD-flow-audit.md` and `METHOD-techbiz-optimizer.md` to accurately reflect their role as reference frameworks, not skill definitions.
811
+ - `install.sh` now removes old skill directories and stale `skillOverrides` entries on upgrade.
812
+ - Hardened `install.sh` settings.json writer: `isinstance` guards on all dict/list fields, fixed idempotent read-permission logic.
813
+ - Updated global `~/.claude/CLAUDE.md` guidance to reflect `akirule` and the new file naming convention.
814
+ - `README.md` expanded to cover architecture, 3-tier router mechanism, file naming conventions, and how Claude Code skills work in this context.
815
+ - `CLAUDE.md` (repo root) documents the `RULE-*` / `METHOD-*` naming convention and consistency requirements.
816
+
817
+ ### Added
818
+ - Pre-flight inspection in `install.sh` reports old skills that will be deleted and stale `skillOverrides` that will be removed.
819
+ - `payload/index.md` documents the Core / On-signal / Method file groupings.
820
+
821
+ ### Removed
822
+ - `PLAN.md` removed after completion.
823
+ - Empty `scripts/` directory removed.
824
+
825
+ ---
826
+
827
+ ## 2026-05-22
828
+
829
+ Initial public release.
830
+
831
+ ### Added
832
+ - `payload/` rule corpus: `RULE-agent-behavior.md`, `RULE-coding.md`, `RULE-content-write.md`, `RULE-docs.md`, `RULE-stack-akiNuxtCf.md`, `SKILL-flow-audit.md`, `SKILL-techbiz-optimizer.md`.
833
+ - Three Claude Code skills: `akidoc-rules`, `akidoc-flow-audit`, `akidoc-techbiz-optimizer`.
834
+ - `install.sh` with pre-flight inspection, confirmation prompt, timestamped backups, and `settings.json` management.
835
+ - Global `~/.claude/CLAUDE.md` guidance block.