@akinet/akidevrule 3.8.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.9.0] - 2026-10-29
4
+
5
+ ### Added
6
+ - **WorkBuddy becomes the sixth `SKILL.md` target: `install.mjs` syncs the shared skill corpus to `~/.workbuddy-ai/skills/`, and the router's Delivery section gains a WorkBuddy row whose skill invocation also `Read`s `RULE-agent-behavior.md` once per session.** Evidence: on the owner's machine the router reached WorkBuddy only through a hand-made symlink `~/.workbuddy-ai/skills/akirule` → `~/.claude/skills/akirule`, which was gone again within the day while the app's own skill cache still pointed at that path — manual wiring is invisible to the installer and to the change sweep, so it rots silently. Root cause: WorkBuddy loads the same `SKILL.md` standard but has no `@`-import, managed block or hook surface, so neither the skill root nor the behavior floor had a delivery path in the installer. Mechanism: one more `syncAkiSkills()` call beside Kiro/Grok (real per-folder copy with managed-names-only prune, other skills untouched), and the floor carried by the artifact the installer already ships rather than by writing `app/app-config.json`, which is app-owned state and outside this repo's non-goals. Tradeoff: nothing is resident on WorkBuddy — routing and the floor still depend on the model invoking the skill, and no route gate exists there; naming `akirule` in Settings → Personalization stays a manual per-machine step. Swept together: `install.mjs`, `skills/akirule/SKILL.md` (Delivery + the `(core)` receipt row), `skills/akihelp/SKILL.md`, `README.md`, repo `CLAUDE.md`, `docs/arch/rule-delivery-architecture.md`, `docs/index.md`, plus new `docs/research/workbuddy-skill-delivery.md`, `docs/ref/fact-workbuddy-harness.md`, `docs/plan/workbuddy-skill-target.md`.
7
+ - **`tauri.B8` — Windows: a cross-compile proves it builds, never that it runs. A change touching files, paths or processes runs the test suite natively on Windows before it ships, with the runner traps named (Common Controls v6 manifest in a fresh dir, direct start, pass only on the summary line) and the five Windows semantics that broke a shipped app: append handles cannot truncate (os error 5), `canonicalize` returns verbatim `\\?\` paths, npm global bins are `.cmd`/`.ps1` shims with the package in `node_modules` beside them, `Command` starts only `.com`/`.exe`/`.bat`/`.cmd` from `PATHEXT`, and a test signals only a child it spawned.** Evidence: a Tauri desktop app shipped after `cargo xwin check` passed for x64 and arm64 and its 812 tests passed on macOS; on Windows every start of its managed CLI failed with `Access is denied (os error 5)` (the log was truncated through the append handle the child inherits; Rust std maps `append(true)` to `FILE_GENERIC_WRITE & !FILE_WRITE_DATA`, and `set_len` needs `FILE_WRITE_DATA`), and an npm-installed CLI was labelled a dev checkout at `\\?\C:\Users\<name>` because the code walked up from `<bin>.cmd` to the nearest `package.json`, the user's home folder. Running the same suite natively in a Windows 11 ARM64 VM then surfaced three more failures no compile check could: a test exe that dies at load with `0xC0000139` (it imports `comctl32!TaskDialogIndirect` and carries no manifest), a path assertion with a literal `/`, and a test using its own pid inside a kill-on-close Job Object that ended the run with exit 0 and the suite half run, i.e. a false green. Root cause: the rule corpus had no Windows section, so a green cross-compile read as Windows verification. Mechanism: one section in the existing Tauri rule, symptom first, each bullet a platform fact a model does not derive from `coding` or `test` alone; the native run is tied to `coding.B3` rung 5 and the child-process rule to `test.B3`, both pointed at, not restated. Rejected: a separate `RULE-windows.md` (every fact is reached from a Tauri/Rust project and the `tauri` route already loads on `.rs`); a CI Windows matrix as the only check (a hosted runner spends minutes and is not where a desktop dev iterates; the rule names the native run, not the host). `pattern.B3` gate: no new abstraction; the section replaces "compile passed, so it works" rather than adding a check beside it. Updated together: `payload/RULE-stack-tauri.md` address map `tauri.B1-8`; `skills/akirule/SKILL.md` `tauri` route signals gain Windows build or path, `\\?\`, `PATHEXT`, os error 5 / 193, cross-compile, npm shim (VI: lỗi trên Windows), because a Windows bug report carries none of the existing Tauri signals; `README.md` rule summary; `docs/arch/corpus-map.md` `tauri` row. Checked and unchanged: `payload/route-map.json` and `install.mjs` (the route clause and globs did not change).
8
+ - **`ui.B6` — Popups: one framework-free wrapper owns every popup (`confirm`/`alert`/`toast`/`fire`, the library loaded by a dynamic `import()`), and the look is the library's `--swal2-*` variables mapped to tokens once on `.swal2-container`, outside any `@layer`, with no per-popup class and no `!important`; the modal defaults `reverseButtons` + `focusCancel` + `heightAuto: false` skip toasts, and a toast must not replace an open confirm.** Evidence: an inventory of 11 sites on one Nuxt stack found 11 different wrapper files (758 lines), about 250 lines of near-copied theme CSS with `!important` on nearly every property, variable names that do not exist in SweetAlert2 11.26 (`--swal2-popup-box-shadow`, `--swal2-title-color`), toast offsets forced with `top … !important` in 4 places, and no wrapper setting `focusCancel`, so "focus the safe button" was required on paper and applied nowhere. Root cause: the theme was written as a per-popup class fighting the library's CSS instead of feeding its variables, so it could not be a token mapping and every site re-derived it by hand. Mechanism, each cascade claim measured in Chrome against SweetAlert2 11.26.25 with Tailwind 4.3.3, test styles inserted before the library's own `<style>` (the worst case): variables on `.swal2-container` beat the library's injected `:root` block while a `:root` mapping loses; one class outside any layer beats the library's `:where()` rules for `z-index`, `top`, `height`, `backdrop-filter` and `box-shadow`; a rule inside `@layer` loses (`padding` kept the library value); `text-left` through `customClass` stays `center` while `text-left!` applies; a class `top` loses to the unwrapped toast-position group while `--swal2-container-padding` moves the toast; the mixin focuses Cancel and puts it before Confirm, and an alert with no cancel button still focuses OK; an undefined top-inset token collapses the container to the bottom of the viewport; a toast fired over an open confirm resolves that confirm as dismissed. Rejected: a per-popup theme class with `!important` (cannot be a token mapping, and the measurements show it is unnecessary); a shared npm package for the wrapper (a public rule cannot assume shared infrastructure, and one small copied file is the whole distribution); a copy in `RULE-stack-tauri.md` (this file already governs desktop frontends). `pattern.B3` gate: subtraction first, since the per-site wrappers and theme blocks are deleted rather than packaged; every bullet carries a library fact a model cannot derive from `A2` or Law 8 alone; the z-index scale and token naming stay pointers (`stack.B5`, `A2`). The address `ui.B6` is reused: the earlier drag-and-drop section that held it was cut in favour of `pattern.A9` (3.6.0). Updated together: `payload/RULE-ui-pattern.md` address map; `payload/RULE-stack-akiNuxtCf.md` `B2` dialogs line now points to `ui.B6`; `skills/akirule/SKILL.md` `ui` route signals gain popup, dialog, modal, toast, SweetAlert2 (VI: hộp thoại, thông báo nổi), because an edit to a `.ts` popup wrapper never matches the `ui` file-extension gate. Checked and unchanged: `payload/route-map.json`, `install.mjs` (Antigravity descriptions derive from the route clause, which did not change), `docs/arch/corpus-map.md` (no lens row or group lists `ui.B` items).
9
+ - **Two gates that refuse instead of remind: `plan_lint.py` fails a release on a fully ticked plan still outside `done/`, an unticked box inside `done/`, and a `docs/index.md` link that is dead or points at a file git does not track; `ship_gate.py` refuses an `/akiship` push or deploy when the run's receipt lacks any `S0`–`S8` line, scores a step FAIL, gives a step no evidence or a hedged PASS, lacks a self-interrogation answer, or still holds an unverified `Q`.** Evidence: the painpoint survey below found the decidable violations were rules delivered and broken (44 COMPLY against 3 LOAD), and its plan's decision rule names a mechanism, never more wording, as the fix for a compliance gap; the owner's standing complaint is plans closed long ago with boxes never checked and checks skipped; the first `plan_lint` run on this repo found 10 unticked boxes in 3 plans under `done/`, and the cloud review of this release flagged 6 index links to plans and research that existed on disk but had never been added to git. Root cause: B7's fail-closed contract and `docs.B1` were text the agent reads and can skip; nothing outside the agent read the receipt or the plans. Mechanism: two scripts in `skills/akiflow/scripts/` on the `release_lint.py` grammar (`[TAG] path:line | label`, exit 0/1/2; `[CLAIM]` is a review line that never changes the exit code); `plan_lint` runs at B7 step 5 and in a new `record-lint` CI job beside `release_lint`; `ship_gate` reads the Report's first block written to a scratchpad file and its exit code decides Phase 3 step 4, so an intensity phrase cannot talk past it. `docs.B1` gains `- [-]` for an item closed without being done, reason on the line, so a deliberate deferral passes and a forgotten box does not; the 10 boxes found here were deferrals or verify steps the status line had already measured, now marked that way. Rejected: checking whether a done-claim in chat rests on a run record (judgment, not presence); a Stop hook over every reply (the owner forbade new check steps per reply, and the gate is needed only at push); gating redundant guards or reruns mechanically (each needs a judgment the remeasure on 2026-11-03 will size). Updated together: `skills/akiflow/scripts/plan_lint.py` and `ship_gate.py` (new), `payload/RULE-docs.md` (B1), `payload/RULE-release.md` (B7 step 5), `skills/akiship/SKILL.md` (Phase 2 doc sync, Phase 3 step 4, Report grammar), `README.md` (scripts list), `.github/workflows/install-smoke.yml` (`record-lint` job), three plans under `docs/plan/done/` (boxes marked `- [-]`), `docs/plan/agent-painpoints-oct28.md` (note under Not scheduled).
10
+
11
+ - **`/noyap` skill — the fix procedure behind the `[FLUFF]` card: rewrite the reply just given, or answer the current request, as the shortest text that loses no idea.** Evidence: `agent.A4` already mandates density and `[FLUFF]` existed, yet replies stayed long and the owner's note (task-1793166568668, 2026-10-28) asked for "rút gọn cực đoan … không được mất đi bất kì ý nào quan trọng"; the gap is compliance and intensity, not missing text, and a core line is barred anyway because the generated Antigravity `agent` file is already 25,790 bytes against the 24,000 cap. Mechanism: four slots in a fixed order (Answer · Open items `Q`/`T`/`N` unchanged · Evidence · Notes grouped by what the reader does with them), a unit is an idea not a sentence, a lossless test last ("would the reader believe or do anything different?"), no numeric cap, and a named never-compressed list — the `agent.A3` decision block, a verbatim rule quote with its meaning lines, the `[RULES]` receipt, passed-check names, a failing check's excerpt, a path with its gloss, a word carrying state or negation (đã/chưa/không), any shape another rule or skill mandates; harness-requested preambles and recaps are cut (`agent.B7`: brevity shapes prose, never steps). Two invocations, no persistent mode: bare `/noyap` (or the card, "dài quá") rewrites the previous reply; `/noyap <request>` answers it short the first time. The thinking-channel question is answered by construction — the rewrite's draft is on screen, a fresh answer is written into the slot order with no draft — so nothing can leak and it runs on a model without extended thinking. Rejected: a session mode (invisible, decays unnoticed, ambiguous with "rewrite"); a numeric cap (guaranteed load-bearing loss); delta-only reporting (`A4` exists to re-orient a context-switching reader); a detector script (`[FLUFF]` is judgment); extending `akilint` (mechanical by contract). Four design-time rounds: self-run `/akithink`, an Opus 5.5 clean-context challenger, revision, re-challenge — record in `docs/plan/noyap-skill.md`. Updated together: `skills/noyap/SKILL.md` (new), `skills/akilint/SKILL.md` (description no longer claims `[FLUFF]`), `skills/akihelp/SKILL.md` (painpoint rows split: padded → `/noyap`, wrapped → `/akilint`), `README.md` (skills table, entry points, layout, all six uninstall lists), `docs/arch/corpus-map.md` (Density row names the skill), `docs/index.md`. Same day, revised after the owner measured the first replies under it as longer than before and asked for 10%, at most 40%, of the replaced text with obvious and unimportant ideas gone: an Opus 5.5 `aki-challenger` seat, read-only, judged the skill against 27 replies from 12 sessions and the painpoint survey, and the three measured `/noyap` rewrites had landed at 72%, 87% and 39% (median 72%) with every idea kept. Root cause: the skill was default-allow — the four slots gave every idea a home, the deletion test ran last on ideas already placed, and "would the reader believe anything different" is passed by every true new fact; a first same-day patch (a second half of the test, passed checks dropped, a 40% budget) only stacked guards on that path. Mechanism now: the objective is "the answer, plus what the owner must do or heed", a whitelist of three (receipt · answer · what the owner must do or heed, one plain sentence each with its A4 letter) with a do-or-decide test — an idea stays only if the owner asked for it or would act or decide differently without it; leftovers are settled, never listed (doable → done before replying, unimportant → unsaid, important → self-run `/akithink` to convergence then A3's decision block); an always-cut list (passed checks, files touched, process, seat or run, scope or cost, restated content, hypotheticals, unasked reasoning, self-assessment, harness preambles); a kept-exact list (state and negation words, a failed or unverified claim as a few words on the claim, a command, path, error or version the owner needs, every mandated shape as its rule defines it); the shape persists for later replies to the owner until they ask for detail, with worker briefs, files and commit messages excluded; the owner's ratio stays as a symptom for rewrites only, mandated shapes aside, with no count, script or hook. Rejected this round: tightening the slot test a fourth time (`pattern.A8`); a word counter or Stop-hook measure (the owner forbade new check steps, and forced rewrites at 12–20% still drew objections for what they kept); moving the procedure into `agent.A4` (resident and already the most-broken rule). Closed in this release by the `agent.A4` change below. Updated together: `skills/noyap/SKILL.md`, `docs/plan/noyap-skill.md` (Decisions 2–5, Rejected, Reopen, § Revision), `README.md` (skills table, entry points), `skills/akihelp/SKILL.md`, `docs/index.md`.
12
+ - **Agent painpoint survey over 30 days of Claude Code transcripts on both machines, measure-first: `docs/research/agent-painpoints-oct28.md` (36 recurring owner-corrected behaviors ranked by rows and by distinct sessions, 8 behaviors counted mechanically, uptake per model, corrections per 100 turns split by `[RULES]` receipt, and a LOAD-fail / COMPLY-fail verdict per top-20 cluster), `docs/plan/agent-painpoints-oct28.md` (extractor v3, a regex-recall sample, the 2026-11-03 remeasure with its decision rule, agy as a later item), and the instruments `scripts/akistrict_extract.py` and `scripts/akistrict_loadcomply.py`.** Evidence: the owner's pinned order (task-1793166819433) to list every recurring agent behavior of the past month and to "đo tỉ lệ ăn rule theo model, theo lượt có [RULES] receipt, trước khi vá thêm chữ", because Opus 5.5 and Sonnet 5.5 kept violating rules that 3.8.0's `agent.B7` already targets. Result: 240 regex hits hand-tagged (185 corrections, 55 not), 36 sub-clusters in 22 code families, top by rows P01 verbose reply 29, P09 ignored order 14, P09 open items left 12, P07 redundant verify 9, P16 concluded without reading 8; where the violated rule is decidable it was resident and broken (44 COMPLY against 3 LOAD of 150 top-20 rows, 19 of 20 clusters governed by the always-loaded core), and a first-reply receipt did not lower the correction rate for Mac sonnet-5-5 (1.82 against 1.05 per 100 turns); 103 of 150 rows are undecidable because the extractor records compaction counts, not times. Mechanism: no model call anywhere (the owner's quota floor); transcripts read by one read-only Python extractor run on each machine (the Mac through an AkiMCP task, outputs read in place), tagging by cheap read-only seats under an akiflow council, every P99/NOTC row and the three largest codes ratified by the lead, two challenger passes. Rejected: patching rule wording per cluster before the remeasure (the owner's words, and the decidable evidence says the text was delivered); a `PreToolUse` gate on repeated heavy commands and a numeric cap on runs (same ground as `verify-run-record-oct28.md`); padding the list to the 50 target with singletons (44 entries, 6 short, stated on the research doc's first line; the recall sample is the route to more). Tradeoff: the `CORRECTION` regex has unmeasured recall, so every count is a lower bound and ranks among close clusters are unstable; the plan's first two items buy recall and decidability before the remeasure decides, per family, between a mechanism (compliance gap), a router or gate fix (delivery gap) and no change. Updated together: the two docs, `docs/index.md` (two rows), the two scripts under `scripts/`, and a second `## Amendments` entry in `docs/research/verify-run-record-oct28.md` holding the one non-measurement reopen trigger (a delivery miss gated by a version marker, one incident, no edit); no file under `payload/`, `skills/` or `claude/` changed in this entry. Same-day follow-up: extractor v3 (compaction and receipt timestamps, per-correction delivery fields, `--sample-unmatched`) and a 100-message hand-tagged sample put regex recall at 0.32 [0.26, 0.42], recorded in the research doc's Amendments; no rule text changed.
13
+
14
+ ### Changed
15
+ - **Claude Code's own commit and PR attribution is turned off by the installer: `install.mjs` sets `attribution` (`commit` and `pr` empty, `sessionUrl` false) in every target's `settings.json`, the settings fragment carries the same block, and `agent.B4` shrinks to a residual that names the mechanism; `payload/GEMINI.md` § 5 and `akigitcommit` keep one line each.** Evidence: the owner's pinned note (task-1793258166203) asked to stop the "Đồng tác giả: Claude" line through `~/.claude/settings.json` and to wire it into the installer; the painpoint survey still counted `Co-Authored-By` commands under an ABSOLUTE rule (at most 2 per model row), and a Claude Code 2.1.312 session with no setting still received "End git commit messages with: Co-Authored-By: Claude Fable 5.1 …" and "🤖 Generated with [Claude Code]" for PRs. Root cause: `B4` fought a standing harness instruction with text, the contest `agent.B7` documents the model losing, while the harness has had a setting for it that nobody set (`attribution`, read from the 2.1.312 binary: `commit`/`pr` strings where an empty string hides the attribution, `sessionUrl` boolean for the `Claude-Session` trailer and PR link). Mechanism: `mergeSettings()` assigns the three keys unconditionally, since the rule is ABSOLUTE, and leaves other `attribution` keys and a deprecated `includeCoAuthoredBy` alone; the preview and summary print the state; the smoke test asserts the three values after install. `B4` keeps the forbidden forms, the override of a harness that still injects one (Codex, agy, Kiro, Grok, WorkBuddy, or Claude Code after a config change) and the `git log -1 --format=%B` check; the `B7` row quoting the attribution reminder is dropped because the quote no longer reaches a session once the setting applies and B4's override clause covers its return. Rejected: `includeCoAuthoredBy: false` (the binary marks it "Deprecated: Use attribution instead", and `attribution.commit === ""` already decides first); deleting `B4` from the core (five of six harnesses have no installer-set switch, and the owner asked for a residual); keeping the `B7` row (a quote the setting removes is a dead row, and the generated Antigravity `agent` file already exceeds its cap). Updated together: `install.mjs`, `claude/fragments/settings.akidoc.fragment.json`, `.github/workflows/install-smoke.yml`, `payload/RULE-agent-behavior.md` (`B4`, `B7` table), `payload/GEMINI.md` § 5, `skills/akigitcommit/SKILL.md`, `README.md` (mermaid, install step 3, uninstall), `docs/arch/rule-delivery-architecture.md`, `docs/plan/agent-painpoints-oct28.md` (owner-ordered exception noted). Checked and unchanged: `claude/agents/aki-maker.md`, `claude/agents/aki-conduct.md`, `docs/arch/akiflow.md`, `skills/akiflow/references/harness-facts.md` (each names `B4` in one phrase that still holds).
16
+ - **`release.yml` publishes `@akinet/akidevrule` to npm through Trusted Publishing before the GitHub Release exists: three jobs `verify` → `publish` → `release`, workflow permissions `{}`, actions pinned by commit SHA, no stored npm token.** Evidence: `CLAUDE.md` § Release process ruled publishing "a manual local step" because the account has 2FA on writes and an automation token was the only CI route, which it rejected; npm Trusted Publishing (GitHub Actions OIDC) needs no token, so the stated reason no longer holds, and the owner ordered the same setup already made for `@akinet/akimcp` on 2026-10-29. Root cause: the publish was the one release step that needed a human OTP, so a tag could produce a GitHub Release for a version the registry never received (the reverse of `release.B9`'s order). Mechanism: `verify` (`contents: read`) checks tag == `package.json` version == CHANGELOG heading with `npm run check-version`, then installs the packed tarball into a scratch HOME and starts `install.mjs --help`; `publish` (`contents: read` + `id-token: write`) installs no dependency and runs only the repo's own `prepack`, installs npm 11.21.0 because trusted publishing needs 11.5.1 or newer and Node 22.14.0 ships an older npm, skips a version the registry already has, and polls `npm view` after publishing; `release` (`contents: write`) is the unchanged GitHub Release step and runs only after the registry shows the version. Rejected: an automation token in a GitHub secret (the long-lived credential the old rule refused); `npm publish <tarball>` (npm's docs do not say OIDC works with a tarball). Unverified until the first tag release runs it; a manual `npm publish` stays the fallback until then. Updated together: `.github/workflows/release.yml`, `CLAUDE.md` § Release process.
17
+ - **akiflow Step 4 — a blocker is an item with an owner, never a closing footnote: anything blocking what the anchor asked for becomes an `ITEM` with an owner seat in `checklist.md` when found, and closure may carry `DEFERRED:` only for an act no seat can perform (the owner's hands, or an act the anchor did not order).** Evidence: two consecutive council rooms closed with every remaining blocker written as a `DEFERRED:` line labelled another seat's or another session's work (a stale local tag, two shared-rule edits, an untraced number, an unverified runtime check), so the owner received a debt list nobody owned and had to order each one again; the owner's correction was that every item blocking the mission must have an owner in `checklist.md`. Root cause: the closure step checked that items closed, not that blockers found mid-run ever became items, so deferring was the cheapest way to close. Mechanism: a doctrine line beside the closure rationale, where the lead decides what reaches the owner; rejected a `council_verify.py` check, since whether a `DEFERRED:` reason names an owner-only act is judgment, not presence. Updated together: `skills/akiflow/SKILL.md` § Step 4 only (no other file under `skills/`, `claude/`, `payload/` or `docs/arch/` names DEFERRED).
18
+ - **`coding.B3` checks are gated by the claim, never by the edit: a check runs once per batch, when a claim is about to rest on it, at the tier the named doubt requires; a rerun needs a changed tree under a new claim; doubt about a recorded run is answered by opening its log; a run is reported as a record (command, exit code, log path) that belongs to the tree, not to the seat that ran it.** Evidence: the owner's correction on 2026-10-28 ("đừng có động tí là chạy test được không nhỉ? không thấy thừa à?", a months-old pain by their own words); that day an akiflow lead re-ran `npm test` (710 tests), `nuxt typecheck` and `vue-tsc` on a tree the web lane had just run them on, and a read-only audit turn ran `npx nuxt generate` (91 routes) against `zero-trust.B2`. Root cause: the old `B3` bullet read "after edits → typecheck/lint/related unit tests", a per-edit schedule that licensed a run at every touch and sat beside the bullet that forbids escalating a tier without a named doubt; the one-run bullet then licensed a rerun on "a change in between (an edit by any tool)", so ten edits were ten sanctioned runs; and no layer said a run recorded by another seat counts, so each seat re-ran to own the evidence. Mechanism: the schedule is rewritten from edit-triggered to claim-triggered on the same bullet, the rerun license now needs a new claim on a changed tree, and the run record (exit code captured with `echo "exit=$?"` — the old example's `; tail` reported `tail`'s status, so a red suite could travel as green) is named once in `B3`; akiflow's Step 5 Verify row applies it (the verifier gets each lane's record with the lead's attestation that no edit followed, opens the log, re-runs only what has no such record), `aki-maker`'s output contract reports the record. Rejected: a tree-state fingerprint (`git diff --stat`) in the record — it cannot tell two dirty trees apart and invites trusting a stale record, so the lead's attestation of no edit since replaces it; a `PreToolUse` gate denying a heavy command repeated on an unchanged tree (false denials on flake probes and environment changes; the 2026-10-20 rerun record's remeasure from 2026-11-03 decides, now counting per-edit and cross-seat reruns separately); a numeric cap on runs; new text for junk-test shapes (`test.A1`, `C1`, `C3` already name them). An Opus challenger rejected the first draft (cross-seat record in the root rule, masked exit code, weak tree-state test, a format check standing in for a log check); the shipped text is the second. Extended the same day from a session that closed six "runtime-only" hand-offs by reading code, logs and history with zero live runs (aki-mcp-sv, 2026-10-28): the ladder's rung 1 names the live-client equivalence (a path a live client exercises daily is verified by that client — name the client and the shared function), and the rerun license lets a recorded run, this session's or a live check at a named earlier commit, stand while the diff since it cannot reach what the check observed; a dependency, build-config or shared-module change reaches everything. Rejected there: a `B4` line on lint hits (`agent` §0's card semantics already say every instance, not only the cited one) and an Impact clause for self-run checks (the claim gate and the ladder's kill-test preamble already say it). Updated together: `payload/RULE-coding.md`, `payload/RULE-release.md` (B7 step 6 now points at the claim, not "the moment"), `skills/akiflow/SKILL.md` (Step 5 Verify row, the no-room closing line), `claude/agents/aki-maker.md`, `docs/arch/akiflow.md` (Phase B diagram), `docs/index.md`; decision record `docs/research/verify-run-record-oct28.md` (with its `## Amendments` entry for the extension).
19
+ - **`agent.A4` deletion test asks "would the reader do or decide anything differently with it?", and a `T` item lists only a call the owner might overrule; a call they would make the same way is carried out unsaid.** Evidence: the `/noyap` transcript review above found the old test ("information the reader does not already have") passed by every true new fact, so done-reports listed every call made and every fact learned, and the owner rejected replies at 12–20% of their original length for what they still carried. Root cause: the root rule measured novelty, not consequence, so the skill and the rule disagreed once the skill moved to a do-or-decide test. Mechanism: the test and the `T` definition reworded so the resident rule and the invoked skill apply one standard; the generated Antigravity `agent` file grows 129 bytes to 25,919 against the 24,000 cap already tracked in `docs/plan/agy-rule-loader-epistemic-floor.md`. Tradeoff: a call the agent misjudges as minor goes unsaid; the owner's correction of such a call is the reopen trigger. Updated together: `payload/RULE-agent-behavior.md`, `docs/arch/corpus-map.md` (Density row), `docs/plan/noyap-skill.md` § Revision, `docs/index.md`.
20
+ - **Runtime-only risk is run before it can be called unverified: `coding.B3` sends it to ladder rung 5 (the app on a port of its own, the touched flow exercised, the process stopped before reporting), and `release.B7` step 7 scores `unverified` only what survives rung 5; an unverified flow the accumulation touched blocks push and deploy as a `Q`, and no completion-intensity phrasing waives that (`release.B8`), except a production-only flow (no local, preview or staging run can reach it, the missing dependency named), which B11 checks right after deploy with its rollback stated first.** Evidence: the 2026-10-28 incident in the `### Removed` entry below; deleting the dev-server ban alone left the chain that shipped it intact, as a clean-context Opus 5.5 `aki-judge` review of the diff from 3.8.0 found: `coding.B3`'s runtime bullet went straight from "runtime risk" to an unverified `N`, skipping rung 5; `release.B7` step 7 called "Untested but I expect it works" a valid gate output; `akiship` carried it as a note; and B8's completion-intensity phrasing still unlocked the push. Root cause: "unverified" was a terminal state any seat could reach without trying to run anything, and the gate treated it as passable. Mechanism: the same bullets now route through rung 5 first, and `akiship` Phase 3 step 4 adds "no touched flow left unverified" to the push/deploy condition. Rung 1's live-client equivalence now holds only for code that client runs (name the commit; close only when the diff since cannot reach the path), since a production client says nothing about code the diff just changed; the human hand-off names visual rendering and live integration only when rung 5 cannot reach them (no rendering tool, a credential only the owner holds). Rejected: an unverified item as an `N` with push allowed (the incident's exact path); blocking every deploy on a production-only flow (deadlock, since no local run can reach it; B11 plus a stated rollback covers it). Fixed in the same review: `/noyap` keeps the one-line run record a done-claim rests on, which its "cut passed checks" list had removed; `akiflow` Step 4 no longer lists push, tag and publish as owner-hands-only, which contradicted `release.B9`; `coding.B4` points at the `agent.A4` deletion test instead of quoting its old wording. A second clean-context review closed four more paths: an undefined "production-only" that could relabel a locally reachable flow; B8's stop-only list read as letting the hold drop to a note; "every flow exercised" read as a dev server for statically settled work (now only flows whose risk cannot be settled statically); and rung 5 read as web-only (now also a CLI, binary or installer against a scratch HOME). A run that spends paid credits stays an `agent.B3` ask, reported as a `Q`. Updated together: `payload/RULE-coding.md` (B3 runtime bullet, rung 1, hand-off line; B4 preamble), `payload/RULE-release.md` (B7 step 7, B8 completion-intensity bullet), `skills/akiship/SKILL.md` (Phase 2 verification line, Phase 3 step 4, Report), `claude/agents/aki-maker.md` (output contract), `skills/noyap/SKILL.md`, `skills/akiflow/SKILL.md` (Step 4 DEFERRED line), `README.md` (akiship row). Checked and unchanged: `docs.C2` (an audit marks runtime-only findings unverified because an audit runs nothing), `docs/arch/akiflow.md` and `docs/arch/corpus-map.md` (neither names step 7, the hand-off line or DEFERRED's examples).
21
+ - **`stack.B5` — z-index is one `--z-*` scale ordered modal < dialog < toast, applied as `z-[var(--z-*)]` in templates or `z-index: var(--z-*)` in CSS, because Tailwind v4 builds a `z-<name>` utility only from a `--z-index-<name>` theme key; stacking local to a component stays a plain utility, max-int only for UI injected into third-party pages, and the built CSS is grepped for the toast rule.** Evidence: in a desktop frontend on Tailwind 4.3.3 a toast sat under an open modal because `z-toast` emitted no CSS; the project's scale was named `--z-*`, so `z-toast`, `z-modal` and the rest produced nothing. Root cause: Tailwind v4's `z` utility reads only the `--z-index` theme namespace (`themeKeys:["--z-index"]` in its dist), and the old line, "a scientific z-index system (`--z-index` variables)", read either as "name the scale `--z-index`" or as "variables exist, so the class works"; the second reading ships a dead class with no build error. Mechanism: one `--z-*` scale referenced through `var()`, so the same token works in a template arbitrary value and in plain CSS, with a fixed order so a toast is never under a modal, drawer or dialog; the built-CSS grep is the check because a missing utility fails silently. Rejected: renaming the theme keys to `--z-index-*` so `z-toast` resolves (works, but splits one token into two forms: the named utility in templates, `var(--z-index-*)` in CSS and arbitrary values), and a `--z-index-*` alias beside the scale (the same split, now named in the line); restating a full chrome order (topbar, sidebar, chat panel) in a public rule (that order is a site's own layout convention, so the line keeps only the steps every popup stack needs). Sharpened the same day after a review: the line names which SweetAlert2 selector takes which step, because a site that copies the popup CSS block without a `--z-dialog` token gets an invalid `z-index` and the dialog falls under the open modal; it bounds `z-10` to one component's own box; and the check is two-sided, because the built-CSS grep passes while another layer still carries a dead `z-<step>` class. Updated together: `payload/RULE-stack-akiNuxtCf.md` `B5` (the radius sentence moves to its own bullet, unchanged); `payload/RULE-ui-pattern.md` `A2` now points to `stack.B5` instead of restating the scale. Checked and unchanged: `skills/akirule/SKILL.md` (the `ui` route already carries modal, toast and design token, no missing concept), `docs/arch/corpus-map.md`, `payload/route-map.json`, `install.mjs` (none references the line); `docs/research/public-private-abc-restructure.md` keeps its historical wording.
22
+
23
+ ### Removed
24
+ - **`coding.B3` no longer says a dev server or a live network call "stays user-triggered"; the agent may run the app to verify a change, and `aki-maker` no longer forbids a build or dev server on its own initiative.** Evidence: on 2026-10-28 a two-repo release session (web app plus compute hub) pushed a version to production that broke in the first real use: video files were refused at upload, two new engines would not open, and the local dev server crashed on a missing column. Nobody had opened the app. The agent handed the UI check to the owner because the rule said a dev server is the owner's call, and the release gate (`release.B7` step 7) accepts "unverified" as a passing output. So under a "finish everything, then release" order the check fell to no one. Root cause: the sentence came into the shared corpus on 2026-07-23 (`bb34dfe`), moved from a machine-local file with "cost and side effects are the user's call" as its only reason and no incident behind it; the 2026-09 change that freed build and test (`release.B7` step 6) left it in place. Mechanism: deletion only. The real costs it guarded are already owned elsewhere: paid calls by `agent.B3` (ask before spending credits), leftover processes by `agent.B1` (what you create, you remove), and proportion by `coding.B3`'s first bullet (never a dev server to catch what a typecheck catches). The narrow guards specific to this machine (own port, never the owner's running server, stop it before reporting) stay in the owner's local file. Rejected: keeping the ban and adding a release exception, because two rules pointing opposite ways is the gap that caused the failure. Checked and unchanged: `METHOD-audit-zero-trust.md` step 2 (an audit runs detectors, not the app), `skills/aki-article-writer/references/article-workflow.md:364` (says no dev server is *needed*, not forbidden). Updated together: `payload/RULE-coding.md`, `claude/agents/aki-maker.md`.
25
+
26
+ ### Fixed
27
+ - **`scythe.py` closes a Markdown code fence only on a bare run of the opening character at least as long as the opening run, as CommonMark specifies, so a three-backtick line inside a four-backtick block is content.** Evidence: on 2026-10-22 a plan doc whose four-backtick template held a three-backtick `css` block drew 4 `[WRAP]` findings on CSS declarations (`.a {` followed by an indented property) and left the prose after the block unlinted, because the inner fence closed the outer one and the outer closing fence then opened a new block. `agent.C3` itself tells authors to fence copy-ready artifacts with four backticks precisely because they contain fences, so the lint punished the form the corpus requires. Root cause: the fence matcher toggled on any line starting with three backticks or tildes and never compared the closing run with the opening one. Mechanism: the opening run (`` `{3,} `` or `~{3,}`) is kept; inside a block only a line whose run uses the same character, is at least that long and carries no info string closes it; everything else is body, linted as before when the fence names a language. Rejected: a per-file exemption or an ignore marker (hides real wraps after the block; the parser was wrong, not the doc); counting only backticks (tilde fences follow the same rule). Verified: a fixture with a four-backtick `markdown` block holding a three-backtick `css` block, a wrapped prose pair, a `js` block with a wrapped comment and a tilde block: the old script reports the false `[WRAP]` at the CSS lines plus the three real findings, the new one only the three real findings; `--all` over this repo, two other standards corpora and one app's `docs/` gives byte-identical output before and after apart from that fixture; the plan doc that surfaced it is now clean. Updated together: `skills/akiflow/scripts/scythe.py` only; no rule text, address or route changed.
28
+ - **Antigravity 1.4.7 now loads the two stack rules and routes from the router's full text: `globs` is rendered as one quoted comma-separated string, every generated description carries the route clause plus the full bilingual `Signals` column, `skills.json` registers one absolute `agskills` entry and expands and deduplicates leading-`~/` paths without removing anything else, `payload/GEMINI.md` gains one narrow negative-claim rule and the canonical lookup boundary, and the agy model facts are re-labelled by evidence class.** Evidence: the agy 1.4.7 log (`cli-20261026_173837.log`) records `cannot unmarshal !!seq into string` for both `glob` rules because `install.mjs` emitted YAML sequences, so neither stack rule could attach by file match; the generated `akirule-deep-think.md` had no `Signals` (the installer parsed only the clause column), and `METHOD-deep-think.md` stayed unrouted in the session that made an unverified capability claim; `~/.gemini/config/skills.json` carried tilde and absolute duplicates of the same root; `scripts/test-agy-bias.sh` still defaulted to `gemini-3.7-flash-high` and `harness-facts.md` still listed the 4-6 Claude slugs while `agy models` lists `gemini-3.8-flash-*`, `claude-opus-5-5-*` and `claude-sonnet-5-5-*`. Root cause: one hand-written YAML shape that predates the vendor's string-only `globs`, a router parser that returned a single column although the table has two, an installer that appended the tilde form on purpose, and model facts recorded without separating a live `agy models` listing from strings read out of the binary. Mechanism: `AG_RULE_MAP` keeps each entry's globs as an array and renders `JSON.stringify(globs.join(", "))` (3 Tauri and 9 Nuxt patterns, none added or removed); `routerRoutes()` returns `{ clause, signals }` per row and both consumers read it (the install summary uses `clause` only); `updateSkillsJson()` appends the absolute own root, expands a leading `~/` through the existing `expandTilde`, drops later entries with an already-seen absolute path and spreads each survivor so extra fields and order stay; `GEMINI.md` § 7 adds "no closed-world negative claims" (a pretrained prior or one tool schema never proves a capability is absent; check the authoritative current source or mark the claim unverified) and § 3 restores `and passes no judgment` to the lookup exemption; `harness-facts.md` lists the 1.4.7 live-visible slugs, marks `gemini-3.1-pro-*`, `gemini-3.1-flash-lite-preview` and the `-max` Claude slugs `[obs-static]` (registered in the binary, never invoked), records the `invoke_subagent` tier words (`inherit`, `flash_lite`, `flash`, `pro`) as the contract rather than any server-side backend such as `M322`, and gives the headless command for a specific model; re-verified on agy 1.4.8 (2026-10-28), the same slug families stay live-visible, the live consumer rows that named `gemini-3.1-pro-*` now name `gemini-4-argon-*` (also the pro-tier example in `scripts/test-agy-bias.sh`), and a new `harness-facts.md` § agy quota by plan records the per-plan structure read from `agy -p "/usage"` and the `RetrieveUserQuotaSummary` / `GetUserStatus` RPCs (Free: `weekly` only, no `5h` bucket and no `Gemini 4 Argon` group; Pro: `5h` + `weekly` plus a separate weekly-only `Gemini 4 Argon` group; Ultra: `5h` + `weekly` with Argon merged into `Gemini Models`). Rejected: embedding the globs as a YAML flow sequence (still a sequence); a second hand-kept signal table (the drift this fixes); stripping tilde or legacy `claudedoc` entries (foreign config, not installer garbage); new text in `agent.B2` or `agent.A3` (the existing source-of-truth and verification rules own it; reopen on a reproducible miss after this lands); a `how/why not` trigger (an explanation without judgment stays a lookup). Verified: the extended installer smoke fails 24 collected assertions against the previous `install.mjs` and passes against this one, and a scratch-HOME install shows `globs` as one string, all 19 router rows reproduced in their descriptions and no `[object Object]`; a seeded `skills.json` (tilde entry, its absolute duplicate, a foreign entry) holds two entries after two installs, the second run byte-identical; no live `agy` call was made, so injection by glob and the routing canaries are unverified. Not fixed here: the generated `akirule-agent-behavior.md` (25,790 bytes) and `akirule-release.md` (49,607 bytes before this change, the plan's F2 figure; 49,966 after the Signals were added) still exceed the 24,000-byte per-file cap (`docs/plan/agy-rule-loader-epistemic-floor.md` Phase B). Updated together: `install.mjs`, `payload/GEMINI.md`, `skills/akiflow/references/harness-facts.md`, `scripts/test-agy-bias.sh`, `.github/workflows/install-smoke.yml`, `docs/arch/rule-delivery-architecture.md`, `docs/research/rule-delivery-force-load-sep25.md` and `docs/research/core-floor-promotion-aug6.md` (dated amendments), `docs/index.md`, the plan's status; `README.md`, `claude/agents/aki-hands.md` and `skills/akiflow/SKILL.md` were checked and needed no change.
29
+
3
30
  ## [3.8.0] - 2026-10-20
4
31
 
5
32
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # akidevrule
2
2
 
3
- One install command turns a fresh environment into Aki's full working baseline — for **Claude Code, Antigravity/Gemini, Codex CLI, Kiro CLI, Grok CLI, Cursor and OpenCode**, generated from one agent-neutral source: a shared rule corpus that loads itself at the right moment (Claude Code + Antigravity), plus a small set of sharp, single-purpose skills synced to every CLI that natively consumes the shared `SKILL.md` open standard.
3
+ One install command turns a fresh environment into Aki's full working baseline — for **Claude Code, Antigravity/Gemini, Codex CLI, Kiro CLI, Grok CLI, WorkBuddy, Cursor and OpenCode**, generated from one agent-neutral source: a shared rule corpus that loads itself at the right moment (Claude Code + Antigravity), plus a small set of sharp, single-purpose skills synced to every CLI that natively consumes the shared `SKILL.md` open standard.
4
4
 
5
5
  **Quick install (npm):**
6
6
 
@@ -73,8 +73,9 @@ Interpreter convention (documented once): the installer and hooks run on `node`
73
73
  | `aki-article-writer` | `/aki-article-writer` or natural language | Per-project pipeline for publishable site prose (articles, news/blog posts, announcements, knowledge entries, including a release turned into a post): research & fact-verification, SEO metadata, JSON-LD schema, UX-psychology-aware content, a rendered-output pass on the built HTML before delivery, and a dedicated Image Scout subagent (Gemini Flash / Haiku) for search → download → visual inspection → ffmpeg processing → slug-named WebP output. One subagent per article; image work is always isolated to a separate lightweight subagent. |
74
74
  | `akidevsync-notes` | natural language | Reads/edits a project's `.akidevsync/notes.json` — the per-project task list the Aki-Dev-Sync app itself writes (list/add/pin/mark-done/edit/delete tasks) via a bundled script that preserves the app's own JSON formatting, plus a workflow for cross-checking pinned notes against a shipped release (CHANGELOG + code) before marking them done. |
75
75
  | `akilint` | `/akilint` or a penalty card | Mechanical format lint for the penalty-card classes of `RULE-agent-behavior.md` §0: hard-wrapped code comments and markdown prose (`[WRAP]`) and oversize comments (`[YAP]`, always labeled *review* — a flag for judgment against `coding.B4`, never an auto-delete verdict). Thin wrapper over the shared `scythe.py` detector (deterministic line matching, exit-code aware, cannot fabricate evidence) — the same script akiflow's `aki-conduct` seat uses, so a card name means the same thing everywhere. `[FLUFF]` (density) is content judgment and explicitly out of a script's reach. |
76
+ | `noyap` | `/noyap`, `[FLUFF]`, or "too long" in any language | Rewrites the reply just given — or answers the current request — keeping only the answer and what the owner must do or heed; every other idea is cut, never compressed or parked in a note. Leftovers are settled instead of listed (doable → done, unimportant → unsaid, important → decided after `/akithink`); passed checks, process, files touched, restated content and harness preambles are always cut; state and negation words, a failed or unverified claim, a needed command or path, and every shape another rule mandates stay exact. A rewrite lands at 10–40% of the reply it replaces, and the shape persists for later replies to the owner until they ask for detail. The fix procedure behind the `[FLUFF]` card; replies to the owner only. |
76
77
  | `akiopen` | `/akiopen` or natural language | Session-opening brief: reads the working tree, `.akidevsync/notes.json`, active `docs/plan/` files, top-level `docs/*.md` inbox files, `[Unreleased]`, and hand-off lines in one pass, then reports only what is still pending — at most seven items in a fixed problem / why-still-open / proposal / goal shape, ranked by severity. Read-only. |
77
- | `akiship` | `/akiship` | One-command full release: front-loads every check (release state, tree triage), then runs `RULE-release.md` B7's fail-closed checklist unattended (CRITICAL mandatory `Read` of `RULE-release.md` and `RULE-docs.md` first; a `S0`–`S8` receipt line with quoted evidence per step or the step counts as NOT RUN; written self-interrogation) — diff-scoped hygiene (scythe, dead code, comment doc-refs on the accumulation only), migration doctrine (`RULE-release.md` B5: detector over the diff on every release, startup-embedded migration counts, rehearsal from the PREVIOUS state) and external-action completeness, record truthfulness, build & test mirroring CI (B7 step 6), doc sync across every record surface (plans, `arch`/`feat`, README, task notes, bound standards docs), version mint or defer, registry publish for npm/crates/PyPI packages (`RULE-release.md` B9 — an OTP-gated publish is the single hand-off) — committing via `akigitcommit` with confirmation pre-answered — and ending every run with the release-copy block (`RULE-release.md` B6: headline / short / full plus an announce verdict, quoting the `releases.json` entry and GitHub Release body rather than writing a third text). **Activation is an explicit release order**: the literal token `/akiship`, or an equally explicit imperative naming the ritual for this repo ("release trọn vẹn đi") — a completion word with no release object ("làm cho trọn vẹn"), or `/akiship` inside a question, activates nothing and gets a consult (answer in chat, change nothing). Governed by the B8 contract: that order is the authorization, blockers are reported once as a batch or the run completes with zero mid-run questions, and it stops only for public-history ambiguity, unclassifiable work, or a design contradiction — an owner-worded completion criterion is derived from the anchor plus the repo's own records and decided/reported (`Decided: X · because Y · rejected Z (why) · reopen if W`), escalated only when competing readings would produce different irreversible artifacts. Push/deploy stay opt-in — named explicitly, or via completion-intensity phrasing (canonical list in `RULE-release.md` B8, e.g. "trọn vẹn") — and after any push, CI is watched to green (`RULE-release.md` B10) regardless of whether the stack deploys, and after any deploy a data path the release touched is exercised (`RULE-release.md` B11). |
78
+ | `akiship` | `/akiship` | One-command full release: front-loads every check (release state, tree triage), then runs `RULE-release.md` B7's fail-closed checklist unattended (CRITICAL mandatory `Read` of `RULE-release.md` and `RULE-docs.md` first; a `S0`–`S8` receipt line with quoted evidence per step or the step counts as NOT RUN; written self-interrogation) — diff-scoped hygiene (scythe, dead code, comment doc-refs on the accumulation only), migration doctrine (`RULE-release.md` B5: detector over the diff on every release, startup-embedded migration counts, rehearsal from the PREVIOUS state) and external-action completeness, record truthfulness, build & test mirroring CI (B7 step 6), doc sync across every record surface (plans, `arch`/`feat`, README, task notes, bound standards docs), version mint or defer, registry publish for npm/crates/PyPI packages (`RULE-release.md` B9 — an OTP-gated publish is the single hand-off) — committing via `akigitcommit` with confirmation pre-answered — and ending every run with the release-copy block (`RULE-release.md` B6: headline / short / full plus an announce verdict, quoting the `releases.json` entry and GitHub Release body rather than writing a third text). **Activation is an explicit release order**: the literal token `/akiship`, or an equally explicit imperative naming the ritual for this repo ("release trọn vẹn đi") — a completion word with no release object ("làm cho trọn vẹn"), or `/akiship` inside a question, activates nothing and gets a consult (answer in chat, change nothing). Governed by the B8 contract: that order is the authorization, blockers are reported once as a batch or the run completes with zero mid-run questions, and it stops only for public-history ambiguity, unclassifiable work, or a design contradiction — an owner-worded completion criterion is derived from the anchor plus the repo's own records and decided/reported (`Decided: X · because Y · rejected Z (why) · reopen if W`), escalated only when competing readings would produce different irreversible artifacts. Push/deploy stay opt-in — named explicitly, or via completion-intensity phrasing (canonical list in `RULE-release.md` B8, e.g. "trọn vẹn") — and are held while any flow the accumulation touched is `unverified` after a local run (`RULE-release.md` B7 step 7), reported as a `Q`; after any push, CI is watched to green (`RULE-release.md` B10) regardless of whether the stack deploys, and after any deploy a data path the release touched is exercised (`RULE-release.md` B11). |
78
79
 
79
80
  ### Five agent definitions
80
81
 
@@ -90,7 +91,7 @@ A seat used to be convened by job title and then handed rules. The order is inve
90
91
 
91
92
  A catalog is not a roster. Five files on disk make it easy to pick seats from a menu, which is the failure they were built to end — a seat is convened only when it traces to a requirement in the owner's own words.
92
93
 
93
- **Claude Code only, deliberately.** `SKILL.md` is an open standard with five implementations; an agent-definition format currently has one, so building a vendor-neutral layer over a single consumer would be exactly the speculative generality `pattern.A2` forbids. Reopen trigger: a second CLI publishing an agent format promotes `claude/agents/` to a top-level `agents/` rendered per vendor, the way `AG_RULE_MAP` already renders rules for Antigravity.
94
+ **Claude Code only, deliberately.** `SKILL.md` is an open standard with six implementations; an agent-definition format currently has one, so building a vendor-neutral layer over a single consumer would be exactly the speculative generality `pattern.A2` forbids. Reopen trigger: a second CLI publishing an agent format promotes `claude/agents/` to a top-level `agents/` rendered per vendor, the way `AG_RULE_MAP` already renders rules for Antigravity.
94
95
 
95
96
  ### A rule corpus that routes itself
96
97
 
@@ -105,7 +106,7 @@ Loading happens on two different mechanisms.
105
106
 
106
107
  **Everything else — routed by meaning, and gated where the artifact gives it away.** Each task turn is classified by the domains it touches and the act (create, decide, audit, ship), in any language; each route carries concept signals in English and Vietnamese as evidence, never as the test, so a paraphrase routes as well as the listed word. The one model-dependent hop left is the `Read` of a routed file, and on Claude Code the `aki-route-guard` PreToolUse hook (`claude/hooks/aki-route-guard.mjs`) enforces it for every route with an artifact signature: the first Edit/Write of each artifact type in a session — a code file (`coding` + `pattern`), `.md` (`docs`), `CHANGELOG.md` (`release`), `.vue`/`.css` (`ui`, plus `stack` in a Nuxt project), `.rs` (`tauri`), `.sql` (`db`), `locales/` (`content`) — is denied until those files have been read whole in that transcript (a `limit`/`offset` or `head` read does not count, and the hook widens a partial `Read` of a rule file to the whole file); the path → rule map is the data file `payload/route-map.json`, not hook code; a subagent is gated on its own transcript. Zero model hops in the check, at most one denial per artifact type per session, fail-open on any error, `AKI_ROUTE_GUARD=0` disables it. `RULE-coding.md` and `RULE-pattern-core.md` were resident imports from 2026-08-06 to 2026-09-30 because the router as a skill went uninvoked; importing the router restored the routing but not the read (measured: the model read a routed file unprompted in about one session in five — `docs/research/rule-delivery-second-hop-sep29.md`), so the gate now restores the guarantee by mechanism and the two files load only on code turns. Meaning-only routes (`think`, `proportion`, `biz`, `ux`, the audits) stay on the router alone, with sensitivity deliberately high (err toward loading — a false positive costs a few tokens, a false negative causes wrong behavior). The one deliberate exception is a lookup: a turn that only reads, counts, locates or explains what exists routes nothing, because no rule's act is performed — those turns are the majority for many users of this corpus, and the tiering exists so they pay for nothing beyond the two resident files.
107
108
 
108
- - **Contextual and analytical — read on route match:** `RULE-coding.md` (code-quality floor: source of truth, changing existing code, verification and the hand-off ladder, comment budget, runtime safety), `RULE-pattern-core.md` (the 9 structural laws, decomposition, the critique gate before any abstraction), `RULE-test.md` (fewest tests: no new test by default, no new test file or folder when one fits, nothing touched the test does not own, a verdict that means what it exercised — gated on test-file edits), `RULE-docs.md` (structure and lifecycle, evidence-bound `ref/fact-*` fact docs, plus the docs-vs-code drift audit), `RULE-content-write.md` (UI copy and writing style, plus the content audit — canonical-term drift, density deletion test, i18n coverage, fact-check), `RULE-stack-akiNuxtCf.md`, `RULE-stack-tauri.md` (Tauri v2 + Rust: never-block-the-UI, version SSOT, target context, the macOS TCC/Gatekeeper boundary for spawned sidecars), `RULE-ui-pattern.md` (design-system layer: the subtraction pass that runs before the tier ladder, class taxonomy, tokens, variant API, and the audit playbook), `RULE-seo.md` (metadata, schema, sitemap, and URL form: relative at rest, absolute only where a consumer requires it), `RULE-release.md`, `RULE-db-design.md`, `RULE-biz.md` (market-facing decisions: positioning, pricing, audience) — plus the analytical methods (`METHOD-*`, loaded on route match like the rest): `METHOD-audit-flow.md` (refactors, multi-file bugs, fragile flows), `METHOD-audit-zero-trust.md` (strict mechanical-first audit: detectors before opinion, exact matches separated from pattern-level candidates), `METHOD-deep-think.md` (scope/architecture/value decisions, first-principles and critique-style thinking), `METHOD-ux-psych.md` (UX/user-behavior evaluation, onboarding and conversion flows), `METHOD-proportionality.md` (sizing a guard, limit or accepted risk against reach, capability, motive and blast radius — the lens that stops both over-engineering and client-side-limits-as-enforcement), `METHOD-audit-subtraction.md` (repo-wide "does this need to exist" sweep, terminating on two dry rounds), and `METHOD-audit-frozen-reference.md` (compliance audit for a clause naming a concrete external artifact as the canonical shape to match — resolve to an exact path, diff literally against it, never judge from memory of the rule's prose).
109
+ - **Contextual and analytical — read on route match:** `RULE-coding.md` (code-quality floor: source of truth, changing existing code, verification and the hand-off ladder, comment budget, runtime safety), `RULE-pattern-core.md` (the 9 structural laws, decomposition, the critique gate before any abstraction), `RULE-test.md` (fewest tests: no new test by default, no new test file or folder when one fits, nothing touched the test does not own, a verdict that means what it exercised — gated on test-file edits), `RULE-docs.md` (structure and lifecycle, evidence-bound `ref/fact-*` fact docs, plus the docs-vs-code drift audit), `RULE-content-write.md` (UI copy and writing style, plus the content audit — canonical-term drift, density deletion test, i18n coverage, fact-check), `RULE-stack-akiNuxtCf.md`, `RULE-stack-tauri.md` (Tauri v2 + Rust: never-block-the-UI, version SSOT, target context, the macOS TCC/Gatekeeper boundary for spawned sidecars, Windows file, path and process semantics that only a native test run exercises), `RULE-ui-pattern.md` (design-system layer: the subtraction pass that runs before the tier ladder, class taxonomy, tokens, variant API, and the audit playbook), `RULE-seo.md` (metadata, schema, sitemap, and URL form: relative at rest, absolute only where a consumer requires it), `RULE-release.md`, `RULE-db-design.md`, `RULE-biz.md` (market-facing decisions: positioning, pricing, audience) — plus the analytical methods (`METHOD-*`, loaded on route match like the rest): `METHOD-audit-flow.md` (refactors, multi-file bugs, fragile flows), `METHOD-audit-zero-trust.md` (strict mechanical-first audit: detectors before opinion, exact matches separated from pattern-level candidates), `METHOD-deep-think.md` (scope/architecture/value decisions, first-principles and critique-style thinking), `METHOD-ux-psych.md` (UX/user-behavior evaluation, onboarding and conversion flows), `METHOD-proportionality.md` (sizing a guard, limit or accepted risk against reach, capability, motive and blast radius — the lens that stops both over-engineering and client-side-limits-as-enforcement), `METHOD-audit-subtraction.md` (repo-wide "does this need to exist" sweep, terminating on two dry rounds), and `METHOD-audit-frozen-reference.md` (compliance audit for a clause naming a concrete external artifact as the canonical shape to match — resolve to an exact path, diff literally against it, never judge from memory of the rule's prose).
109
110
  - **Full load on explicit request:** asking, in any wording, to load the whole corpus reads every `RULE-*`/`METHOD-*` file at once.
110
111
 
111
112
  No harness magic beyond the `CLAUDE.md` import: routes are instructions telling Claude to Read the file from `~/.aki/akidevrule/` when the task's domain matches; the full-load request is the escape hatch.
@@ -160,6 +161,7 @@ Install once; from then on the system has two kinds of surface. **Rules load the
160
161
  | Opening a project — what is still pending here? | `/akiopen` |
161
162
  | A messy working tree that needs clean commits | `/akigitcommit` |
162
163
  | Format lint — or someone called a penalty card | `/akilint` (or just say `[WRAP]` / `[YAP]`) |
164
+ | A reply was too long — keep the answer and what I must act on, cut the rest | `/noyap` (or just say `[FLUFF]`, "dài quá") |
163
165
  | Ship a release end-to-end | `/akiship` |
164
166
  | A dense analysis worth one self-contained page | `/akihtmlreport` |
165
167
  | A researched, SEO-complete article | `/aki-article-writer` |
@@ -207,6 +209,8 @@ skills/ → shared Agent Skills corpus (SKILL.md open
207
209
  akiflow/scripts/council_verify.py (mechanical closure gate: ghost seats, missing evidence tags, unanswered REMINDs)
208
210
  akiflow/scripts/scythe.py (penalty-card lint [WRAP]/[YAP] — shared engine of /akilint and the enforcer's evidence sweeps)
209
211
  akiflow/scripts/release_lint.py (release-record lint: CHANGELOG section order/vocabulary/level, releases.json parity, type keys, highlight review — RULE-release.md C4, B7 step 4)
212
+ akiflow/scripts/plan_lint.py (plan/index lint: fully ticked plan outside done/, unticked box in done/, dead or untracked index link; plan cited by CHANGELOG with open boxes as review — RULE-docs.md B1, RULE-release.md B7 step 5)
213
+ akiflow/scripts/ship_gate.py (akiship push gate: refuses push/deploy on a missing S0–S8 line, FAIL, evidence-free or hedged PASS, missing self-interrogation, or an open unverified Q — RULE-release.md B7, B8)
210
214
  akiflow/scripts/suite_lint.py (test-file lint: literal /tmp, missing temp cleanup, exit calls as verdicts; sleeps, vacuous asserts, ambient ifs, HOME reads, live URLs, ports, source pins, history comments as review — RULE-test.md D1)
211
215
  akiflow/scripts/*.sh (transitional Unix wrappers, one per script above — each execs its .py sibling)
212
216
  akiflow/references/harness-facts.md (subagent/cost/model facts, with sources)
@@ -215,6 +219,7 @@ skills/ → shared Agent Skills corpus (SKILL.md open
215
219
  akihelp/SKILL.md
216
220
  akigitcommit/SKILL.md
217
221
  akilint/SKILL.md
222
+ noyap/SKILL.md
218
223
  akiopen/SKILL.md
219
224
  akiship/SKILL.md
220
225
  aki-article-writer/SKILL.md
@@ -285,7 +290,7 @@ flowchart TD
285
290
  C_SKILLS["skills/<skill_name>/SKILL.md"]
286
291
  C_AGENTS["agents/aki-*.md (copied per file, your own agents kept)"]
287
292
  C_HOOKS["hooks/ aki-update-check.mjs + aki_version_check.mjs · aki-route-guard.mjs · aki-compact-reread.mjs"]
288
- C_SET["settings.json (Permissions + Skill Overrides)"]
293
+ C_SET["settings.json (Permissions + Skill Overrides + Attribution off)"]
289
294
  end
290
295
 
291
296
  %% TARGET 3: ~/.gemini/
@@ -297,7 +302,7 @@ flowchart TD
297
302
  G_SJSON["config/skills.json (Inherits agskills, absolute path)"]
298
303
  end
299
304
 
300
- %% TARGETS 4-6: other CLIs that natively consume the SKILL.md standard
305
+ %% TARGETS 4-7: other harnesses that natively consume the SKILL.md standard
301
306
  subgraph T4["🧩 4. Codex CLI (~/.agents/skills/ + $CODEX_HOME/)"]
302
307
  X_SKILLS["<skill_name>/SKILL.md"]
303
308
  X_AGENTS["AGENTS.md managed block (behavior floor + router) + config.toml project_doc_max_bytes"]
@@ -308,6 +313,9 @@ flowchart TD
308
313
  subgraph T6["🧩 6. Grok CLI (~/.grok/skills/)"]
309
314
  R_SKILLS["<skill_name>/SKILL.md"]
310
315
  end
316
+ subgraph T7["🧩 7. WorkBuddy (~/.workbuddy-ai/skills/)"]
317
+ W_SKILLS["<skill_name>/SKILL.md"]
318
+ end
311
319
 
312
320
  INSTALL -->|"copy + prune stale"| T1
313
321
  INSTALL -->|"deploy & settings setup"| T2
@@ -315,9 +323,10 @@ flowchart TD
315
323
  INSTALL -->|"sync per skill folder"| T4
316
324
  INSTALL -->|"sync per skill folder"| T5
317
325
  INSTALL -->|"sync per skill folder"| T6
326
+ INSTALL -->|"sync per skill folder"| T7
318
327
  ```
319
328
 
320
- Targets 5-6 only get the shared skill corpus (no rule corpus / no `CLAUDE.md`/`GEMINI.md`-style overrides — those CLIs have no equivalent hard-load hook this baseline plugs into yet). Target 4 also gets the behavior floor and the router as a managed block in `$CODEX_HOME/AGENTS.md` (default `~/.codex/AGENTS.md`), the one file Codex hard-loads globally — only when that directory exists, lines of your own in the file are kept, and `project_doc_max_bytes` is written to `config.toml` when absent because Codex stops loading instruction files once global plus project files pass 32 KiB (the block alone is ~36 KB). Codex expands no `@` imports and never reads Claude's global file, so copying `~/.claude/CLAUDE.md` would deliver nothing (`docs/research/codex-instruction-delivery.md`). A project's `CLAUDE.md` stays unread unless you opt in per machine with `project_doc_fallback_filenames = ["CLAUDE.md"]`; a native `AGENTS.md` in the same directory wins over it. Each sync is scoped per skill folder name via a Node `fs` copy plus a managed-names-only prune, same never-touch-the-rest guarantee as targets 2 and 3, and runs unconditionally — harmless if that CLI isn't installed on the machine, picked up the moment it is.
329
+ Targets 5-7 only get the shared skill corpus (no rule corpus / no `CLAUDE.md`/`GEMINI.md`-style overrides — those CLIs have no equivalent hard-load hook this baseline plugs into yet). Target 4 also gets the behavior floor and the router as a managed block in `$CODEX_HOME/AGENTS.md` (default `~/.codex/AGENTS.md`), the one file Codex hard-loads globally — only when that directory exists, lines of your own in the file are kept, and `project_doc_max_bytes` is written to `config.toml` when absent because Codex stops loading instruction files once global plus project files pass 32 KiB (the block alone is ~36 KB). Codex expands no `@` imports and never reads Claude's global file, so copying `~/.claude/CLAUDE.md` would deliver nothing (`docs/research/codex-instruction-delivery.md`). A project's `CLAUDE.md` stays unread unless you opt in per machine with `project_doc_fallback_filenames = ["CLAUDE.md"]`; a native `AGENTS.md` in the same directory wins over it. Each sync is scoped per skill folder name via a Node `fs` copy plus a managed-names-only prune, same never-touch-the-rest guarantee as targets 2 and 3, and runs unconditionally — harmless if that CLI isn't installed on the machine, picked up the moment it is.
321
330
 
322
331
  1. Syncs `payload/*` into `~/.aki/akidevrule/` (Node `fs` copy, excludes `ref-ECC/`), removes stale files left by renames, syncs `agskills/` for Antigravity skill inheritance, and deploys the full TCC lookup to `~/.aki/akidevrule/docs/ref/fact-macos-codesign-tcc.md`.
323
332
  2. Deploys to **all detected Claude config directories** — `~/.claude` (default primary), all existing `~/.claude*` profile variants (e.g. `~/.claude-9rt`, `~/.claude-prx`), plus `$CLAUDE_CONFIG_DIR` or `--claude-dir <path>` if provided:
@@ -325,11 +334,11 @@ Targets 5-6 only get the shared skill corpus (no rule corpus / no `CLAUDE.md`/`G
325
334
  - Copies `claude/agents/*.md` into `<target>/agents/` **file by file, never a directory mirror with `--delete`** — that folder is a shared namespace where your own agent definitions sit beside Aki's, exactly like `<target>/skills/`, so nothing you did not install is ever removed.
326
335
  - Replaces `<target>/CLAUDE.md` with the packaged guidance (timestamped backup first, removed once the run succeeds), appending this machine's source-repo path and an `@<target>/CLAUDE.local.md` import.
327
336
  - Creates `<target>/CLAUDE.local.md` **only if missing** — never overwritten afterward. On profile variants (`~/.claude-*`), the template imports `@~/.claude/CLAUDE.local.md` by default so machine-wide facts are inherited. Put per-machine/per-profile rules there; they survive every reinstall.
328
- - Before the confirmation prompt or any mutation, preflights every existing JSON file it may update: each detected profile's `settings.json`, `~/.gemini/config/skills.json`, `~/.gemini/antigravity-cli/settings.json`, and `~/.gemini/settings.json`. A malformed file or non-object root aborts the install with originals untouched. After preflight, updates `<target>/settings.json` with a timestamped backup (removed once the run succeeds): read permission for `~/.aki/akidevrule/**`, one `Bash(<launcher> <script>*)` rule per Aki skill script per rendering (absolute and `~/`-literal — Claude Code does not expand `~` before matching), `skillOverrides.akirule = "on"`, idempotent registration of the `SessionStart` update-check hook.
337
+ - Before the confirmation prompt or any mutation, preflights every existing JSON file it may update: each detected profile's `settings.json`, `~/.gemini/config/skills.json`, `~/.gemini/antigravity-cli/settings.json`, and `~/.gemini/settings.json`. A malformed file or non-object root aborts the install with originals untouched. After preflight, updates `<target>/settings.json` with a timestamped backup (removed once the run succeeds): read permission for `~/.aki/akidevrule/**`, one `Bash(<launcher> <script>*)` rule per Aki skill script per rendering (absolute and `~/`-literal — Claude Code does not expand `~` before matching), `skillOverrides.akirule = "on"`, `attribution` with empty `commit`/`pr` and `sessionUrl: false` (Claude Code then adds no `Co-Authored-By`, PR footer or session link — `agent.B4` by mechanism), idempotent registration of the `SessionStart` update-check hook.
329
338
  - Installs `<target>/hooks/aki-update-check.mjs` plus its shared parser `<target>/hooks/aki_version_check.mjs`, `<target>/hooks/aki-route-guard.mjs` registered as a `PreToolUse` hook on `Edit|MultiEdit|Write|NotebookEdit` and on `Read` (the `Read` branch widens a partial read of a rule file), and `<target>/hooks/aki-compact-reread.mjs` registered as a `SessionStart` hook with matcher `compact` (all idempotent, same filter-then-push as the update check).
330
339
  3. Writes `~/.aki/akidevrule/.version` with `installed=`/`version=`/`commit=`/`branch=` and records the source-repo path in `~/.aki/akidevrule/.source-repo` — `version=` is the just-installed CHANGELOG's latest released semver, the same value `install.mjs --check` and the hook compare against remote.
331
340
  4. Installs `payload/GEMINI.md` to `~/.gemini/GEMINI.md` — Antigravity global behavior overrides, stamped with a version marker (`[AKIRULE-AG-OVERRIDES-…]`) on line 1. Generates one native rule file per `RULE-*`/`METHOD-*` under `~/.gemini/config/rules/` with YAML `trigger` frontmatter — `agent` `always_on`, the stacks `glob`, the rest `model_decision` — each description generated from its `akirule` route, so both harnesses route from one table. Deploys 11 skills directly to `~/.gemini/config/skills/` for native auto-discovery (synced per skill folder, same never-touch-the-rest guarantee as step 2), configures `~/.gemini/config/skills.json` with absolute paths as secondary, and merges skill execution permissions into `~/.gemini/antigravity-cli/settings.json` and `~/.gemini/settings.json` — a `command()` prefix rule for every `skills/*/scripts/*.py` per skill root, in both the expanded and the tilde-literal rendering (agy's matcher compares command strings literally — no glob expansion, and no tilde expansion in either direction — so a directory wildcard never matches and a rule only matches a command written the same way; see [docs/ref/fact-cli-permission-allowlist-standard.md](docs/ref/fact-cli-permission-allowlist-standard.md) §1.2) plus scoped `write_file`/`read_file` rules for the council workspace and rule corpus.
332
- 5. Syncs the same skill folders to `~/.agents/skills/` (Codex CLI, Cursor), `~/.kiro/skills/` (Kiro CLI), and `~/.grok/skills/` (Grok CLI) — each a plain global skills root these CLIs read natively, synced per skill folder name exactly like step 2. Kiro and Grok are skills-only. Codex additionally gets the managed `AGENTS.md` block and the `project_doc_max_bytes` key described above, only when `$CODEX_HOME` (default `~/.codex`) exists; the summary names the block size, the budget written or found, and a non-empty `AGENTS.override.md` that would shadow it.
341
+ 5. Syncs the same skill folders to `~/.agents/skills/` (Codex CLI, Cursor), `~/.kiro/skills/` (Kiro CLI), `~/.grok/skills/` (Grok CLI), and `~/.workbuddy-ai/skills/` (WorkBuddy) — each a plain global skills root these harnesses read natively, synced per skill folder name exactly like step 2. Kiro, Grok and WorkBuddy are skills-only; on WorkBuddy nothing is resident, so the router's Delivery section makes the skill invocation also read the behavior floor once per session ([docs/arch/rule-delivery-architecture.md](docs/arch/rule-delivery-architecture.md) § WorkBuddy). Codex additionally gets the managed `AGENTS.md` block and the `project_doc_max_bytes` key described above, only when `$CODEX_HOME` (default `~/.codex`) exists; the summary names the block size, the budget written or found, and a non-empty `AGENTS.override.md` that would shadow it.
333
342
  6. Pre-allows every Aki skill script in each harness present on the machine, one adapter per rule dialect (`lib/permissions.mjs`): `~/.kiro/settings/permissions.yaml` (a marker-delimited managed block), `~/.codex/rules/akidevrule.rules` (a file akidevrule owns), `~/.cursor/cli-config.json` (`Shell(python3:<script>*)`, never a bare `Shell(python3)`), `~/.config/opencode/opencode.json` (`permission.bash`). Every rule names one exact script, in both path renderings; entries a previous install wrote are replaced, the user's own are kept. Grok CLI and Ollama have no file-based allowlist, so nothing is written for them — [docs/ref/fact-cli-permission-allowlist-standard.md](docs/ref/fact-cli-permission-allowlist-standard.md).
334
343
 
335
344
  7. If `rtk` is on `PATH`, asks once — in a terminal only — whether to write its accuracy-first config (next section). Default, and the only answer when there is no terminal, is to leave rtk alone; the summary then prints one line saying so, with the `--rtk` flag that opts in without a prompt.
@@ -371,7 +380,7 @@ Claude Code loads the core and the router automatically (harness-guaranteed `@`-
371
380
  - `ref-ECC/` — a large reference corpus, not needed for standard operation.
372
381
  - API keys, model-router tokens, localhost project permissions, unrelated personal Claude settings.
373
382
  - Automatic download/install logic — the update hook is strictly notify-only.
374
- - Any skill, rule, or file you already have that isn't part of this repo's managed set — every sync (Claude Code, Antigravity, Codex CLI, Kiro CLI, and Grok CLI skill directories included) touches only the paths/names akidevrule itself owns, never a blanket directory wipe. Verified in practice: `~/.grok/skills/` on this machine already held unrelated pre-existing skills (`best-of-n`, `docx`, `pptx`, …) and they were untouched by the sync.
383
+ - Any skill, rule, or file you already have that isn't part of this repo's managed set — every sync (Claude Code, Antigravity, Codex CLI, Kiro CLI, Grok CLI and WorkBuddy skill directories included) touches only the paths/names akidevrule itself owns, never a blanket directory wipe. Verified in practice: `~/.grok/skills/` on this machine already held unrelated pre-existing skills (`best-of-n`, `docx`, `pptx`, …) and they were untouched by the sync.
375
384
 
376
385
  ## Why `~/.aki/akidevrule`
377
386
 
@@ -382,10 +391,11 @@ No sudo, user-local, easy to inspect and delete, consistent with the Aki ecosyst
382
391
  ```bash
383
392
  rm -rf ~/.aki/akidevrule
384
393
  rm -rf ~/.aki/agent-council # /akiflow session workspaces (self-prunes at 30 days anyway)
385
- rm -rf ~/.claude/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,akiopen,akiship,aki-article-writer,akidevsync-notes}
386
- rm -rf ~/.agents/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,akiopen,akiship,aki-article-writer,akidevsync-notes} # Codex CLI
387
- rm -rf ~/.kiro/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,akiopen,akiship,aki-article-writer,akidevsync-notes} # Kiro CLI
388
- rm -rf ~/.grok/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,akiopen,akiship,aki-article-writer,akidevsync-notes} # Grok CLI (other, non-Aki skills already in this folder are untouched)
394
+ rm -rf ~/.claude/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,noyap,akiopen,akiship,aki-article-writer,akidevsync-notes}
395
+ rm -rf ~/.agents/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,noyap,akiopen,akiship,aki-article-writer,akidevsync-notes} # Codex CLI
396
+ rm -rf ~/.kiro/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,noyap,akiopen,akiship,aki-article-writer,akidevsync-notes} # Kiro CLI
397
+ rm -rf ~/.grok/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,noyap,akiopen,akiship,aki-article-writer,akidevsync-notes} # Grok CLI (other, non-Aki skills already in this folder are untouched)
398
+ rm -rf ~/.workbuddy-ai/skills/{akirule,akiflow,akithink,akihtmlreport,akihelp,akigitcommit,akilint,noyap,akiopen,akiship,aki-article-writer,akidevsync-notes} # WorkBuddy
389
399
  rm -f ~/.claude/agents/aki-{hands,judge,conduct,challenger,maker}.md # your own agents in that folder are untouched
390
400
  rm -f ~/.claude/hooks/aki-update-check.mjs ~/.claude/hooks/aki_version_check.mjs ~/.claude/hooks/aki-route-guard.mjs ~/.claude/hooks/aki-compact-reread.mjs ~/.claude/hooks/aki-update-check.py ~/.claude/hooks/aki_version_check.py
391
401
  # then delete the three entries whose command names those hooks from hooks.SessionStart and hooks.PreToolUse in ~/.claude/settings.json
@@ -396,7 +406,7 @@ rm -f ~/.gemini/GEMINI.md # restore from a *.akidevrule-backup-* if ne
396
406
 
397
407
  On **Windows** the same targets live under `%USERPROFILE%` (e.g. `%USERPROFILE%\.aki\akidevrule`, `%USERPROFILE%\.claude\skills\...`); remove them with `Remove-Item -Recurse -Force`.
398
408
 
399
- Then remove the akidevrule block from `~/.claude/CLAUDE.md` and its entries (permission, skillOverrides, SessionStart and PreToolUse hooks) from `~/.claude/settings.json` if desired. `~/.codex/rules/akidevrule.rules` is a whole file the installer owns and can simply be deleted.
409
+ Then remove the akidevrule block from `~/.claude/CLAUDE.md` and its entries (permission, skillOverrides, attribution, SessionStart and PreToolUse hooks) from `~/.claude/settings.json` if desired. `~/.codex/rules/akidevrule.rules` is a whole file the installer owns and can simply be deleted.
400
410
 
401
411
  ## Content for dev.akitao.com
402
412
 
@@ -32,6 +32,6 @@ A domain rule the brief named that you could not read means you should not have
32
32
  # Output contract
33
33
 
34
34
  - What changed, per file, in one line each — the change, not a narration of the edit.
35
- - The verification you actually ran, with its output. Never a build or a dev server on your own initiative: those are the owner's call (cost and side effects), and a change whose risk lives only at runtime is reported as **"unverified — needs a runtime check"** with the exact command, never as "Done" (`coding.B3`).
35
+ - The verification you actually ran, as a record (`coding.B3`): command, exit code, log path, output excerpt. A change whose risk lives only at runtime is run (`coding.B3` rung 5: the app on a port of its own, or the CLI/binary against a scratch HOME); only what survives it is reported as **"unverified — needs a runtime check"** with the exact command and the rung that failed, never as "Done".
36
36
  - Anything the brief specified that you did **not** do, and why. Silence about a skipped item reads as completion.
37
37
  - Attestation as checkable fact, not as citation: `files edited: 4 · git mutations: none · scope: only the paths named in the brief`.
@@ -11,5 +11,10 @@
11
11
  },
12
12
  "skillOverrides": {
13
13
  "akirule": "on"
14
+ },
15
+ "attribution": {
16
+ "commit": "",
17
+ "pr": "",
18
+ "sessionUrl": false
14
19
  }
15
20
  }
package/install.mjs CHANGED
@@ -48,6 +48,7 @@ const CODEX_SKILLS_DIR = join(HOME, ".agents", "skills");
48
48
  const CODEX_HOME = process.env.CODEX_HOME ? expandTilde(process.env.CODEX_HOME.trim()) : join(HOME, ".codex");
49
49
  const KIRO_SKILLS_DIR = join(HOME, ".kiro", "skills");
50
50
  const GROK_SKILLS_DIR = join(HOME, ".grok", "skills");
51
+ const WORKBUDDY_SKILLS_DIR = join(HOME, ".workbuddy-ai", "skills");
51
52
  const SKILLS_SRC = join(REPO_ROOT, "skills");
52
53
 
53
54
  const OLD_SKILLS = ["akidoc-rules", "akidoc-flow-audit", "akidoc-techbiz-optimizer", "akiadvise"];
@@ -345,34 +346,32 @@ function gitBranch(repo) {
345
346
 
346
347
  const ROUTER_SRC = join(SKILLS_SRC, "akirule", "SKILL.md");
347
348
 
348
- // The router's routes table is the single routing source; AG's native rule descriptions are derived from it.
349
- function routerClauses() {
350
- const table = readFileSync(ROUTER_SRC, "utf-8").matchAll(/^\| `((?:RULE|METHOD)-[^`]+\.md)` · `[\w-]+` \| ([^|]+) \|/gm);
351
- return new Map([...table].map(([, file, clause]) => [file, clause.trim()]));
349
+ function routerRoutes() {
350
+ const table = readFileSync(ROUTER_SRC, "utf-8").matchAll(/^\| `((?:RULE|METHOD)-[^`]+\.md)` · `[\w-]+` \| ([^|]+) \| ([^|]+) \|/gm);
351
+ return new Map([...table].map(([, file, clause, signals]) => [file, { clause: clause.trim(), signals: signals.trim() }]));
352
352
  }
353
353
 
354
- // Each entry: [ruleFile, trigger, globs] — globs is a raw JSON array string or ""; every model_decision description is derived from the router's route clause.
355
354
  const AG_RULE_MAP = [
356
- ["RULE-agent-behavior.md", "always_on", ""],
357
- ["RULE-coding.md", "model_decision", ""],
358
- ["RULE-pattern-core.md", "model_decision", ""],
359
- ["RULE-test.md", "model_decision", ""],
360
- ["RULE-docs.md", "model_decision", ""],
361
- ["RULE-content-write.md", "model_decision", ""],
362
- ["RULE-stack-akiNuxtCf.md", "glob", '["**/*.vue", "nuxt.config.*", "wrangler.toml", "app/**", "server/**", "composables/**", "middleware/**", "plugins/**", "layouts/**"]'],
363
- ["RULE-stack-tauri.md", "glob", '["src-tauri/**", "**/*.rs", "tauri.conf.json"]'],
364
- ["RULE-ui-pattern.md", "model_decision", ""],
365
- ["RULE-seo.md", "model_decision", ""],
366
- ["RULE-release.md", "model_decision", ""],
367
- ["RULE-db-design.md", "model_decision", ""],
368
- ["RULE-biz.md", "model_decision", ""],
369
- ["METHOD-audit-flow.md", "model_decision", ""],
370
- ["METHOD-audit-zero-trust.md", "model_decision", ""],
371
- ["METHOD-deep-think.md", "model_decision", ""],
372
- ["METHOD-ux-psych.md", "model_decision", ""],
373
- ["METHOD-proportionality.md", "model_decision", ""],
374
- ["METHOD-audit-subtraction.md", "model_decision", ""],
375
- ["METHOD-audit-frozen-reference.md", "model_decision", ""],
355
+ ["RULE-agent-behavior.md", "always_on", []],
356
+ ["RULE-coding.md", "model_decision", []],
357
+ ["RULE-pattern-core.md", "model_decision", []],
358
+ ["RULE-test.md", "model_decision", []],
359
+ ["RULE-docs.md", "model_decision", []],
360
+ ["RULE-content-write.md", "model_decision", []],
361
+ ["RULE-stack-akiNuxtCf.md", "glob", ["**/*.vue", "nuxt.config.*", "wrangler.toml", "app/**", "server/**", "composables/**", "middleware/**", "plugins/**", "layouts/**"]],
362
+ ["RULE-stack-tauri.md", "glob", ["src-tauri/**", "**/*.rs", "tauri.conf.json"]],
363
+ ["RULE-ui-pattern.md", "model_decision", []],
364
+ ["RULE-seo.md", "model_decision", []],
365
+ ["RULE-release.md", "model_decision", []],
366
+ ["RULE-db-design.md", "model_decision", []],
367
+ ["RULE-biz.md", "model_decision", []],
368
+ ["METHOD-audit-flow.md", "model_decision", []],
369
+ ["METHOD-audit-zero-trust.md", "model_decision", []],
370
+ ["METHOD-deep-think.md", "model_decision", []],
371
+ ["METHOD-ux-psych.md", "model_decision", []],
372
+ ["METHOD-proportionality.md", "model_decision", []],
373
+ ["METHOD-audit-subtraction.md", "model_decision", []],
374
+ ["METHOD-audit-frozen-reference.md", "model_decision", []],
376
375
  ];
377
376
 
378
377
  function agDestName(ruleFile) {
@@ -381,23 +380,24 @@ function agDestName(ruleFile) {
381
380
  return `akirule-${stem.toLowerCase()}.md`;
382
381
  }
383
382
 
384
- function agRuleDescription(ruleFile, clauses) {
385
- if (!clauses.has(ruleFile)) throw new Error(`akirule has no route for ${ruleFile}`);
383
+ function agRuleDescription(ruleFile, routes) {
384
+ if (!routes.has(ruleFile)) throw new Error(`akirule has no route for ${ruleFile}`);
385
+ const { clause, signals } = routes.get(ruleFile);
386
386
  // agy denies view_file on ~/.gemini/config/rules/ (hardcoded protection boundary, measured 2026-09-26), so the description names the readable copy.
387
- return `Load when the task ${clauses.get(ruleFile)}: view_file ~/.aki/akidevrule/${ruleFile} (this rules directory itself is not readable).`;
387
+ return `Load when the task ${clause}. Signals (evidence of the domain, never a literal gate): ${signals}. view_file ~/.aki/akidevrule/${ruleFile} (this rules directory itself is not readable).`;
388
388
  }
389
389
 
390
390
  // Every rule file is rendered before any installed one is removed, so a bad map or router aborts with AG untouched.
391
391
  function installAgRules() {
392
- const clauses = routerClauses();
392
+ const routes = routerRoutes();
393
393
  const mapped = new Set(AG_RULE_MAP.map(([f]) => f));
394
394
  const unmapped = listDir(join(REPO_ROOT, "payload")).filter((n) => /^(RULE|METHOD)-.*\.md$/.test(n) && !mapped.has(n));
395
395
  if (unmapped.length) throw new Error(`AG_RULE_MAP has no entry for: ${unmapped.join(", ")}`);
396
396
 
397
397
  const rendered = AG_RULE_MAP.map(([ruleFile, trigger, globs]) => {
398
398
  const lines = ["---", `trigger: ${trigger}`];
399
- if (globs) lines.push(`globs: ${globs}`);
400
- if (trigger !== "always_on") lines.push(`description: ${JSON.stringify(agRuleDescription(ruleFile, clauses))}`);
399
+ if (globs.length) lines.push(`globs: ${JSON.stringify(globs.join(", "))}`);
400
+ if (trigger !== "always_on") lines.push(`description: ${JSON.stringify(agRuleDescription(ruleFile, routes))}`);
401
401
  lines.push("---", "", `<!-- Generated by akidevrule from payload/${ruleFile}. Do not edit here. -->`, "");
402
402
  lines.push(readFileSync(join(REPO_ROOT, "payload", ruleFile), "utf-8"));
403
403
  return [join(GEMINI_RULES_DIR, agDestName(ruleFile)), lines.join("\n")];
@@ -661,6 +661,10 @@ function mergeSettings(settingsPath, installRoot, claudeDir) {
661
661
  data.skillOverrides.akirule = "on";
662
662
  if (!("akihelp" in data.skillOverrides)) data.skillOverrides.akihelp = "name-only";
663
663
 
664
+ // agent.B4 by mechanism: an empty attribution string hides Claude Code's commit/PR trailer, sessionUrl=false the Claude-Session link; other keys stay the user's.
665
+ if (typeof data.attribution !== "object" || data.attribution === null || Array.isArray(data.attribution)) data.attribution = {};
666
+ Object.assign(data.attribution, { commit: "", pr: "", sessionUrl: false });
667
+
664
668
  if (typeof data.hooks !== "object" || data.hooks === null || Array.isArray(data.hooks)) data.hooks = {};
665
669
  const hooks = data.hooks;
666
670
  if (!Array.isArray(hooks.SessionStart)) hooks.SessionStart = [];
@@ -859,12 +863,15 @@ function updateSkillsJson() {
859
863
  const skillsJson = join(GEMINI_DIR, "config", "skills.json");
860
864
  mkdirSync(dirname(skillsJson), { recursive: true });
861
865
  const data = isFile(skillsJson) ? JSON.parse(readFileSync(skillsJson, "utf-8")) : {};
862
- if (!Array.isArray(data.entries)) data.entries = [];
863
- const absPath = join(INSTALL_ROOT, "agskills");
864
- const tildePath = "~/.aki/akidevrule/agskills";
865
- for (const p of [absPath, tildePath]) {
866
- if (!data.entries.some((e) => e && typeof e === "object" && e.path === p)) data.entries.push({ path: p });
867
- }
866
+ const entries = [...(Array.isArray(data.entries) ? data.entries : []), { path: join(INSTALL_ROOT, "agskills") }];
867
+ const seen = new Set();
868
+ data.entries = entries.flatMap((e) => {
869
+ if (!e || typeof e !== "object" || typeof e.path !== "string") return [e];
870
+ const path = expandTilde(e.path);
871
+ if (seen.has(path)) return [];
872
+ seen.add(path);
873
+ return [{ ...e, path }];
874
+ });
868
875
  writeTextLf(skillsJson, JSON.stringify(data, null, 2) + "\n");
869
876
  }
870
877
 
@@ -972,7 +979,9 @@ async function inspectStatus(claudeDirs) {
972
979
  const readOk = allow.includes(readRule);
973
980
  const overrides = data.skillOverrides || {};
974
981
  const akiOk = overrides.akirule === "on";
975
- console.log(` Claude (${toTildePath(claudeDir)}): Read=${readOk ? "✅" : "⚠️ missing"}, Bash=${bashOk ? "✅" : "⚠️ missing"}, akirule=${akiOk ? "✅" : "⚠️ will enable"}`);
982
+ const attr = data.attribution || {};
983
+ const attrOff = attr.commit === "" && attr.pr === "" && attr.sessionUrl === false;
984
+ console.log(` Claude (${toTildePath(claudeDir)}): Read=${readOk ? "✅" : "⚠️ missing"}, Bash=${bashOk ? "✅" : "⚠️ missing"}, akirule=${akiOk ? "✅" : "⚠️ will enable"}, attribution=${attrOff ? "✅ off" : "⚠️ will turn off"}`);
976
985
  } catch (e) {
977
986
  console.log(` ❌ Error reading ${settingsPath}: ${e}`);
978
987
  }
@@ -1023,10 +1032,10 @@ function printSummary(claudeDirs, preAllow, codex, rtk) {
1023
1032
 
1024
1033
  console.log(cyanBold("Rules deployed:"));
1025
1034
  {
1026
- const clauses = routerClauses();
1035
+ const routes = routerRoutes();
1027
1036
  for (const [ruleFile, trigger] of AG_RULE_MAP) {
1028
1037
  const [tier, color] = trigger === "always_on" ? ["Core", redBold] : ruleFile.startsWith("METHOD-") ? ["Analytical", blueBold] : ["Contextual", yellowBold];
1029
- const desc = trigger === "always_on" ? "behavior floor — resident every session" : `loads when the task ${clauses.get(ruleFile) || "?"}`;
1038
+ const desc = trigger === "always_on" ? "behavior floor — resident every session" : `loads when the task ${routes.get(ruleFile)?.clause ?? "?"}`;
1030
1039
  console.log(` ${color(tier.padEnd(12))} ${ruleFile.padEnd(34)} ${desc}`);
1031
1040
  }
1032
1041
  }
@@ -1054,6 +1063,7 @@ function printSummary(claudeDirs, preAllow, codex, rtk) {
1054
1063
  console.log(` 🤖 Codex CLI : ${CODEX_SKILLS_DIR}`);
1055
1064
  console.log(` 🤖 Kiro CLI : ${KIRO_SKILLS_DIR}`);
1056
1065
  console.log(` 🤖 Grok CLI : ${GROK_SKILLS_DIR}`);
1066
+ console.log(` 🤖 WorkBuddy : ${WORKBUDDY_SKILLS_DIR}`);
1057
1067
 
1058
1068
  console.log();
1059
1069
  console.log(cyanBold("Codex global instructions (behavior floor + router, resident):"));
@@ -1070,7 +1080,7 @@ function printSummary(claudeDirs, preAllow, codex, rtk) {
1070
1080
 
1071
1081
  console.log();
1072
1082
  console.log(cyanBold("Skill scripts pre-allowed (no prompt when a skill runs its own scripts):"));
1073
- console.log(" ⚙️ claude settings.json in every target above — plus Read(~/.aki/akidevrule/**)");
1083
+ console.log(" ⚙️ claude settings.json in every target above — plus Read(~/.aki/akidevrule/**) and attribution off (no Co-Authored-By, PR footer or session link — agent.B4)");
1074
1084
  for (const row of preAllow) {
1075
1085
  const state = row.error ? `⚠️ skipped: ${row.error}` : `${row.rules} invocation(s)${row.changed ? "" : ", unchanged"}`;
1076
1086
  console.log(` ⚙️ ${row.id.padEnd(12)} ${toTildePath(row.file)} — ${state}`);
@@ -1188,6 +1198,7 @@ async function runInstall(claudeDirs, { rtkFlag = false } = {}) {
1188
1198
  syncAkiSkills(CODEX_SKILLS_DIR);
1189
1199
  syncAkiSkills(KIRO_SKILLS_DIR);
1190
1200
  syncAkiSkills(GROK_SKILLS_DIR);
1201
+ syncAkiSkills(WORKBUDDY_SKILLS_DIR);
1191
1202
  const codex = installCodexInstructions();
1192
1203
 
1193
1204
  // --- 4. GEMINI.md (only when ~/.gemini exists) ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinet/akidevrule",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "description": "Aki's shared rule corpus + Agent Skills for Claude Code, Gemini/Antigravity, Codex, Kiro, Grok, Cursor and OpenCode — install and update with one command.",
5
5
  "keywords": [
6
6
  "claude-code",
package/payload/GEMINI.md CHANGED
@@ -33,7 +33,7 @@ These directives patch Antigravity's known weak spots. They are hard-loaded (no
33
33
 
34
34
  ## 3. Always comply with the akirule corpus — and with rule 0
35
35
  - The shared rule corpus installed at `~/.aki/akidevrule/` ("akirule") applies to you, not only to other agents. When a task touches an area it covers, follow it.
36
- - **Nothing is read at session start.** `RULE-coding.md` and `RULE-pattern-core.md` are attached natively by their rule descriptions on code turns (`akirule-coding`, `akirule-pattern-core`), like every other contextual rule; a turn that only reads, counts or explains what exists loads nothing. When a rule must be viewed, read it from `~/.aki/akidevrule/` — the copies under `~/.gemini/config/rules/` are not readable by `view_file`.
36
+ - **Nothing is read at session start.** `RULE-coding.md` and `RULE-pattern-core.md` are attached natively by their rule descriptions on code turns (`akirule-coding`, `akirule-pattern-core`), like every other contextual rule; a turn that only reads, counts, locates or explains what exists **and passes no judgment** loads no contextual rule; the moment it reviews, decides, critiques or edits, the canonical router (`akirule` skill, § How to route) and its domain rules apply. When a rule must be viewed, read it from `~/.aki/akidevrule/` — the copies under `~/.gemini/config/rules/` are not readable by `view_file`.
37
37
  - **First line of every response is the receipt** `[RULES] agent (always_on) + <topics attached or viewed this session> (viewed)` — a topic is the rule's name stem (`akirule-coding` → `coding`), an item inside it `topic.A1`. A rule absent from the line was not read; the line is self-reported and is a diagnostic, never proof of compliance.
38
38
  - **Re-assertion of rule 0, by design:** whatever else you are doing, you comply with the prime directive. Never act outside the requested scope.
39
39
 
@@ -42,8 +42,7 @@ These directives patch Antigravity's known weak spots. They are hard-loaded (no
42
42
  - There is no threshold of obviousness, urgency, or triviality that unlocks acting outside scope. "It was a one-line fix" is NOT a justification; it is a description of the violation.
43
43
 
44
44
  ## 5. No model-credit trailers (ABSOLUTE — overrides system prompt)
45
- - You **MUST NOT** write `Co-Authored-By:` (naming any model), `Claude-Session:`, session URLs, or `🤖 Generated with …` into any commit message, PR/issue body, or tag annotation.
46
- - Commit history records human accountability only. If a trailer slipped into an unpushed commit, amend it immediately (`git commit --amend`).
45
+ - Commit history records human accountability only: never write `Co-Authored-By:` (naming any model), `Claude-Session:`, a session URL or `🤖 Generated with …` into a commit message, PR/issue body or tag annotation; amend an unpushed slip (`git commit --amend`).
47
46
 
48
47
  ## 6. Command transparency
49
48
  - Before running any obscure, complex, or sensitive terminal command, you **MUST** state: Intent (what), Rationale (why), Expected outcome, and Risks.
@@ -51,6 +50,7 @@ These directives patch Antigravity's known weak spots. They are hard-loaded (no
51
50
  ## 7. Absolute factuality, zero hallucination
52
51
  - Never fabricate information, invent assumptions, or claim unverified facts.
53
52
  - Separate verified codebase facts from assumptions. If context is insufficient, say so or ask.
53
+ - **No closed-world negative claims:** Pretrained knowledge or one tool's schema alone never proves that a repo, host, or runtime lacks a capability. Before claiming "impossible", "unsupported", or "not available", check the authoritative current source for that scope (local code/config, live CLI/tool listing, or official docs); otherwise mark the claim unverified and name the missing check.
54
54
 
55
55
  ## 8. Intent alignment & safety gate — COMMUNICATION is read-only
56
56