@akinet/akidevrule 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/README.md +21 -20
  3. package/claude/CLAUDE.md +5 -6
  4. package/claude/agents/aki-challenger.md +1 -1
  5. package/claude/agents/aki-conduct.md +2 -2
  6. package/claude/agents/aki-hands.md +4 -4
  7. package/claude/agents/aki-judge.md +2 -2
  8. package/claude/agents/aki-maker.md +2 -2
  9. package/install.mjs +115 -292
  10. package/lib/permissions.mjs +244 -0
  11. package/package.json +5 -2
  12. package/payload/GEMINI.md +2 -0
  13. package/payload/METHOD-audit-frozen-reference.md +33 -0
  14. package/payload/METHOD-audit-zero-trust.md +1 -1
  15. package/payload/METHOD-deep-think.md +1 -1
  16. package/payload/RULE-agent-behavior.md +4 -3
  17. package/payload/RULE-coding.md +2 -1
  18. package/payload/RULE-docs.md +14 -3
  19. package/payload/RULE-pattern-core.md +1 -1
  20. package/payload/RULE-release.md +2 -2
  21. package/payload/RULE-ui-pattern.md +1 -1
  22. package/payload/index.md +11 -7
  23. package/skills/aki-article-writer/SKILL.md +1 -1
  24. package/skills/akidevsync-notes/SKILL.md +1 -1
  25. package/skills/akiflow/references/harness-facts.md +8 -6
  26. package/skills/akihelp/SKILL.md +7 -7
  27. package/skills/akihtmlreport/SKILL.md +1 -1
  28. package/skills/akilint/SKILL.md +1 -1
  29. package/skills/akirule/SKILL.md +45 -131
  30. package/skills/akiship/SKILL.md +3 -3
  31. package/skills/akithink/SKILL.md +8 -7
  32. package/skills/akiflow/scripts/council-cost.sh +0 -4
  33. package/skills/akiflow/scripts/council-open.sh +0 -4
  34. package/skills/akiflow/scripts/council-read.sh +0 -4
  35. package/skills/akiflow/scripts/council-verify.sh +0 -4
  36. package/skills/akiflow/scripts/scythe.sh +0 -4
@@ -0,0 +1,244 @@
1
+ // Script pre-allow for every agent harness akidevrule deploys skills to.
2
+ // Matcher facts per harness: docs/ref/cli-permission-allowlist-standard.md.
3
+ import { existsSync, readdirSync, readFileSync, mkdirSync } from "node:fs";
4
+ import { join, dirname, relative, isAbsolute, sep } from "node:path";
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Inventory — the scripts and the command lines that invoke them
8
+ // ---------------------------------------------------------------------------
9
+
10
+ export function listSkillScripts(skillsSrc) {
11
+ const scripts = [];
12
+ for (const skill of readdirSync(skillsSrc).sort()) {
13
+ const dir = join(skillsSrc, skill, "scripts");
14
+ if (!existsSync(dir)) continue;
15
+ for (const name of readdirSync(dir).sort()) {
16
+ if (name.endsWith(".py")) scripts.push([skill, "scripts", name]);
17
+ }
18
+ }
19
+ return scripts;
20
+ }
21
+
22
+ function launchers(isWin) {
23
+ return isWin ? ["py -3", "python", "python3"] : ["python3"];
24
+ }
25
+
26
+ // Every rendering a model may type: absolute and `~/`-literal, since no surveyed matcher expands `~` on both sides.
27
+ export function scriptInvocations({ roots, scripts, home, isWin }) {
28
+ const out = new Set();
29
+ for (const root of new Set(roots)) {
30
+ for (const parts of scripts) {
31
+ const abs = join(root, ...parts);
32
+ const renderings = [abs];
33
+ const rel = relative(home, abs);
34
+ if (rel && !rel.startsWith("..") && !isAbsolute(rel)) renderings.push("~/" + rel.split(sep).join("/"));
35
+ for (const launcher of launchers(isWin)) {
36
+ for (const path of renderings) out.add(`${launcher} ${path}`);
37
+ }
38
+ }
39
+ }
40
+ return [...out];
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Ownership — which existing entries this installer wrote and may replace
45
+ // ---------------------------------------------------------------------------
46
+
47
+ const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
48
+
49
+ // Owned = any Python launcher pointing into `<akiSkill>/scripts/`, plus the directory-glob rules of earlier releases.
50
+ export function ownershipTest(skillNames) {
51
+ const names = skillNames.map(escapeRe).join("|");
52
+ const current = new RegExp(`(?:py -3|python3?)[\\s:]+\\S*[\\\\/](?:${names})[\\\\/]scripts[\\\\/]`);
53
+ const legacy = /^(?:(?:Bash|command)\()?python3 \S*(?:skills|agskills)[\\/]\*{1,2}\)?$/;
54
+ return (entry) => typeof entry === "string" && (current.test(entry) || legacy.test(entry));
55
+ }
56
+
57
+ export function replaceOwned(list, isOwned, desired) {
58
+ return [...list.filter((e) => !isOwned(e)), ...desired];
59
+ }
60
+
61
+ // Recovers a --claude-dir root already recorded in a shared target's allowlist, so a run that omits the flag does not prune it as stale.
62
+ export function recoverSkillRoots(allow, isOwned, home) {
63
+ const roots = new Set();
64
+ for (const entry of allow) {
65
+ if (!isOwned(entry)) continue;
66
+ const m = /^command\((?:py -3|python3?)[ :]+(.+)\)$/.exec(entry);
67
+ if (!m) continue;
68
+ let p = m[1];
69
+ if (p.startsWith("~/")) p = join(home, ...p.slice(2).split("/"));
70
+ if (!isAbsolute(p)) continue;
71
+ const root = dirname(dirname(dirname(p)));
72
+ if (isAbsolute(root)) roots.add(root);
73
+ }
74
+ return [...roots];
75
+ }
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // File writers
79
+ // ---------------------------------------------------------------------------
80
+
81
+ const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
82
+
83
+ function writeIfChanged(path, before, after, io) {
84
+ if (before === after) return false;
85
+ mkdirSync(dirname(path), { recursive: true });
86
+ if (existsSync(path)) io.backup(path);
87
+ io.writeText(path, after);
88
+ return true;
89
+ }
90
+
91
+ function updateJson(path, mutate, io) {
92
+ const before = existsSync(path) ? readFileSync(path, "utf-8") : null;
93
+ const data = before === null ? {} : JSON.parse(before);
94
+ if (!isObject(data)) throw new Error(`must be a JSON object: ${path}`);
95
+ mutate(data);
96
+ return writeIfChanged(path, before, JSON.stringify(data, null, 2) + "\n", io);
97
+ }
98
+
99
+ function allowList(data, key = "allow") {
100
+ if (!isObject(data.permissions)) data.permissions = {};
101
+ if (!Array.isArray(data.permissions[key])) data.permissions[key] = [];
102
+ return data.permissions;
103
+ }
104
+
105
+ const BLOCK_START = "# >>> akidevrule managed — regenerated on every install";
106
+ const BLOCK_END = "# <<< akidevrule managed";
107
+
108
+ // Kiro 3.x: one `rules:` list per file; the managed items live between two marker comments at its end.
109
+ function writeKiroYaml(path, matches, isOwned, io) {
110
+ const before = existsSync(path) ? readFileSync(path, "utf-8") : null;
111
+ let body = (before ?? "").replace(new RegExp(`\\n?${escapeRe(BLOCK_START)}[\\s\\S]*?${escapeRe(BLOCK_END)}\\n?`), "\n");
112
+ // Pre-marker releases appended bare allow items; drop those whose every match line is owned.
113
+ body = body.replace(/\n - capability: shell\n match:\n((?: - ".*"\n)+) effect: allow\n?/g, (item, lines) =>
114
+ lines.trimEnd().split("\n").every((l) => isOwned(JSON.parse(l.trim().slice(2)))) ? "\n" : item
115
+ );
116
+ body = body.replace(/\s+$/, "");
117
+ if (!/^rules:/m.test(body)) body = (body ? body + "\n" : "") + "rules:";
118
+ const block = [BLOCK_START, " - capability: shell", " match:", ...matches.map((m) => ` - ${JSON.stringify(m)}`), " effect: allow", BLOCK_END];
119
+ return writeIfChanged(path, before, body + "\n" + block.join("\n") + "\n", io);
120
+ }
121
+
122
+ function splitLauncher(invocation) {
123
+ const i = invocation.startsWith("py -3 ") ? 5 : invocation.indexOf(" ");
124
+ return [invocation.slice(0, i), invocation.slice(i + 1)];
125
+ }
126
+
127
+ // ---------------------------------------------------------------------------
128
+ // Harness adapters — one per rule dialect
129
+ // ---------------------------------------------------------------------------
130
+
131
+ // Claude Code: `*` spans `/` and spaces; used inside the settings.json merge the installer already owns.
132
+ export function claudeAllowRules(invocations) {
133
+ return invocations.map((inv) => `Bash(${inv}*)`);
134
+ }
135
+
136
+ // Each adapter: which config it owns, which skill roots its sessions see, and how to write the rules.
137
+ export function harnessAdapters(ctx) {
138
+ const { home, claudeSkillRoots, dirs } = ctx;
139
+ const primaryClaude = claudeSkillRoots[0];
140
+ return [
141
+ {
142
+ id: "antigravity",
143
+ present: existsSync(dirs.gemini),
144
+ roots: [dirs.geminiSkills, ...claudeSkillRoots],
145
+ files: [join(dirs.gemini, "antigravity-cli", "settings.json"), join(dirs.gemini, "settings.json")],
146
+ // Literal string-prefix matcher, no glob: one rule per exact invocation.
147
+ write(path, invs, isOwned, io) {
148
+ return updateJson(path, (data) => {
149
+ const perms = allowList(data);
150
+ const lanes = [
151
+ `write_file(${join(home, ".aki", "agent-council")}/)`,
152
+ `read_file(${join(home, ".aki", "akidevrule")}/)`,
153
+ "write_file(~/.aki/agent-council/)",
154
+ "read_file(~/.aki/akidevrule/)",
155
+ ];
156
+ perms.allow = replaceOwned(perms.allow.filter((e) => !lanes.includes(e)), isOwned, [
157
+ ...invs.map((inv) => `command(${inv})`),
158
+ ...lanes,
159
+ ]);
160
+ perms.allowNonWorkspaceAccess = true;
161
+ perms.agentMode = true;
162
+ if (!Array.isArray(perms.trustedWorkspaces)) perms.trustedWorkspaces = [];
163
+ if (!perms.trustedWorkspaces.includes(home)) perms.trustedWorkspaces.push(home);
164
+ }, io);
165
+ },
166
+ },
167
+ {
168
+ id: "kiro",
169
+ present: existsSync(dirs.kiro),
170
+ roots: [dirs.kiroSkills, primaryClaude],
171
+ files: [join(dirs.kiro, "settings", "permissions.yaml")],
172
+ write: (path, invs, isOwned, io) => writeKiroYaml(path, invs.map((inv) => `${inv}*`), isOwned, io),
173
+ },
174
+ {
175
+ id: "codex",
176
+ present: existsSync(dirs.codex),
177
+ roots: [dirs.agentsSkills, primaryClaude],
178
+ // A whole file akidevrule owns — regenerated, never merged.
179
+ files: [join(dirs.codex, "rules", "akidevrule.rules")],
180
+ write(path, invs, _isOwned, io) {
181
+ const before = existsSync(path) ? readFileSync(path, "utf-8") : null;
182
+ const rules = invs.map((inv) => {
183
+ const [launcher, script] = splitLauncher(inv);
184
+ const pattern = [...launcher.split(" "), script].map((t) => JSON.stringify(t)).join(", ");
185
+ return `prefix_rule(pattern = [${pattern}], decision = "allow")`;
186
+ });
187
+ return writeIfChanged(path, before, ["# Generated by akidevrule installer — do not edit.", ...rules, ""].join("\n"), io);
188
+ },
189
+ },
190
+ {
191
+ id: "cursor",
192
+ present: existsSync(dirs.cursor),
193
+ roots: [dirs.agentsSkills, primaryClaude],
194
+ files: [join(dirs.cursor, "cli-config.json")],
195
+ // `Shell(<first token>:<args glob>)`; a bare `Shell(python3)` would allow every Python command.
196
+ write(path, invs, isOwned, io) {
197
+ return updateJson(path, (data) => {
198
+ const perms = allowList(data);
199
+ perms.allow = replaceOwned(perms.allow, isOwned, invs.map((inv) => {
200
+ const [launcher, args] = splitLauncher(inv);
201
+ const [base, ...flags] = launcher.split(" ");
202
+ return `Shell(${base}:${[...flags, args].join(" ")}*)`;
203
+ }));
204
+ }, io);
205
+ },
206
+ },
207
+ {
208
+ id: "opencode",
209
+ present: existsSync(dirs.opencode),
210
+ roots: [primaryClaude, dirs.agentsSkills],
211
+ files: [join(dirs.opencode, "opencode.json")],
212
+ // `permission.bash` maps glob → action, last match wins, so owned keys go last.
213
+ write(path, invs, isOwned, io) {
214
+ return updateJson(path, (data) => {
215
+ if (!isObject(data.permission)) data.permission = {};
216
+ const bash = data.permission.bash;
217
+ const kept = isObject(bash) ? bash : typeof bash === "string" ? { "*": bash } : {};
218
+ const next = Object.fromEntries(Object.entries(kept).filter(([k]) => !isOwned(k)));
219
+ for (const inv of invs) next[`${inv}*`] = "allow";
220
+ data.permission.bash = next;
221
+ }, io);
222
+ },
223
+ },
224
+ ];
225
+ }
226
+
227
+ // Returns one report row per file touched or skipped, for the install summary.
228
+ export function applyHarnessPreAllow(ctx, io) {
229
+ const isOwned = ownershipTest(ctx.akiSkillNames);
230
+ const report = [];
231
+ for (const adapter of harnessAdapters(ctx)) {
232
+ if (!adapter.present) continue;
233
+ const invs = scriptInvocations({ roots: adapter.roots, scripts: ctx.scripts, home: ctx.home, isWin: ctx.isWin });
234
+ for (const file of adapter.files) {
235
+ try {
236
+ const changed = adapter.write(file, invs, isOwned, io);
237
+ report.push({ id: adapter.id, file, rules: invs.length, changed });
238
+ } catch (err) {
239
+ report.push({ id: adapter.id, file, error: err.message });
240
+ }
241
+ }
242
+ }
243
+ return report;
244
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@akinet/akidevrule",
3
- "version": "3.3.0",
4
- "description": "Aki's shared rule corpus + Agent Skills for Claude Code, Gemini/Antigravity, Codex, Kiro and Grok — install and update with one command.",
3
+ "version": "3.4.0",
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",
7
7
  "agent-skills",
@@ -10,6 +10,8 @@
10
10
  "codex",
11
11
  "kiro",
12
12
  "grok",
13
+ "cursor",
14
+ "opencode",
13
15
  "ai-rules",
14
16
  "coding-standards",
15
17
  "installer",
@@ -40,6 +42,7 @@
40
42
  "install.mjs",
41
43
  "install.sh",
42
44
  "install.ps1",
45
+ "lib/",
43
46
  "payload/",
44
47
  "skills/",
45
48
  "claude/",
package/payload/GEMINI.md CHANGED
@@ -33,6 +33,8 @@ 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
+ - **Session start, before the first task action:** `view_file` `~/.aki/akidevrule/RULE-coding.md` and `~/.aki/akidevrule/RULE-pattern-core.md` in full. They are core rules; the rules budget cannot inline them, so this read is how they enter context. Read every `~/.aki/akidevrule/` file from that directory — the copies under `~/.gemini/config/rules/` are not readable by `view_file`.
37
+ - **First line of every response is the receipt** `[RULES] agent (always_on) + coding,pattern,<topics you viewed this session> (viewed)` — topic addresses from `~/.aki/akidevrule/index.md`. A rule absent from the line was not read; the line is self-reported and is a diagnostic, never proof of compliance.
36
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.
37
39
 
38
40
  ## 4. Rule 0 again — no unrequested action, at any cost
@@ -0,0 +1,33 @@
1
+ # Frozen-Reference Compliance Audit
2
+
3
+ <!-- Address map: frozen-ref.A1-3 · frozen-ref.B1-5 · frozen-ref.C1-5 -->
4
+
5
+ **Activation**: a rule or project doc names one or more concrete implementations as the canonical/frozen shape another project must match structurally (a pinned dependency version, a byte-identical component, a literal config key, a frozen page layout) — and the user asks whether the target actually conforms, at any strictness down to a single character.
6
+
7
+ ## Why this method exists
8
+
9
+ Ordinary rule-following audits judge against *principles* (DRY, SRP, naming) — a project can satisfy those by reading well. A frozen-reference clause instead claims literal parity with a specific artifact that exists somewhere else. Reading the rule's prose and judging "this looks compliant" against memory or impression is the single highest-frequency failure mode for this class of clause: the rule text describes the shape, but only the reference file *is* the shape. A rule audited this way will keep re-surfacing the same violations across sessions, because "looks compliant" is not falsifiable and each session re-derives its own impression instead of re-running the same diff.
10
+
11
+ This method forces the audit to be a diff against the actual reference bytes, never a recollection of them. It inherits `zero-trust`'s CERTAIN/SUGGESTED evidence split and read-only discipline (`agent.B5`) — this file adds what is specific to *comparing against a named external artifact* rather than auditing a codebase against itself.
12
+
13
+ ## A. Locate every reference before judging anything
14
+
15
+ 1. **Resolve the exact file(s)** the clause points to — not "the project that implements X" but the literal path(s):line(s). A frozen-reference clause with no resolvable path is not yet auditable; resolve it first or say plainly it cannot be resolved.
16
+ 2. **A single reference can itself have drifted from the written rule.** When more than one implementation of the standard exists, read at least two independently before ruling — where they disagree with each other, that is a defect in the *rule corpus*, not in the target project being audited. Report it as a **standard-vs-practice gap**, separate from target defects, and never charge it against the target.
17
+ 3. **Note what changed since the clause was written.** A frozen reference frozen a year ago against a codebase that has since evolved elsewhere is now two artifacts pulling apart; say so rather than silently picking a side.
18
+
19
+ ## B. Build the comparison mechanically, never from memory
20
+
21
+ 1. **One row per literal unit**, not per file: a specific exported function name, a specific class/prop, a specific config key, a specific sequence of steps in a flow. "The auth composable looks similar" is not a row; "`loginWithGoogle` returns `Result<T>`, the reference throws" is.
22
+ 2. **Verdict per row is one of exactly:** `MATCH` / `RENAMED` / `MISSING` / `EXTRA` / `STRUCTURAL-DIFF`. No row gets softened into "acceptable variance," "close enough," or "minor style difference" inside the audit — that judgment belongs to whoever reads the report, not to the auditor produced it. State the literal fact; let severity be decided downstream.
23
+ 3. **Distinguish clauses that explicitly allow local naming** (a rule that says "class names follow each project's own tokens") from clauses that claim structural/sequence/value identity. The former makes a naming difference not-a-violation by the rule's own text; the latter makes even a one-character difference a row. Cite which kind of clause governs each row — do not apply free-naming leniency to a clause that never granted it, and do not manufacture a violation out of a clause that did.
24
+ 4. **Every row carries `path:line` on both sides** — the target and whichever reference the row was checked against. A row without both sides is not yet evidence.
25
+ 5. **When the target diverges from the frozen shape, check whether a separate, higher-precedence rule justifies the divergence** (a project-level constraint that pre-dates and conflicts with the frozen clause). Report the conflict explicitly rather than either silently fixing it or silently ignoring it — that decision is the project owner's, not the auditor's.
26
+
27
+ ## C. Report
28
+
29
+ 1. **Verdict first**: does the target meet the standard, plainly stated, before any table.
30
+ 2. **Findings ranked by severity** (hard-rule / functional break → structural drift → cosmetic), each with the comparison row(s) that produced it.
31
+ 3. **A separate, clearly labeled section for standard-vs-practice gaps** (A2) — these are follow-ups for the rule corpus, not the audited project.
32
+ 4. **A coverage line**: which references were read, which clauses could not be resolved to a path, what was explicitly out of scope for this run.
33
+ 5. **Read-only** (`agent.B5`): this produces a report, never a fix. Fixing what the report finds is a separate, explicitly authorized run.
@@ -1,6 +1,6 @@
1
1
  # Zero-Trust Audit Method
2
2
 
3
- **Activation**: the user asks for a strict, uncompromising sweep ("audit khắt khe", "ép rule", "force audit", "quét tuyệt đối", "zero-trust audit", "rà soát toàn bộ").
3
+ **Activation**: the user asks for a strict, uncompromising sweep that must be proven by detectors rather than impression — of the whole project, or of a change plus everything that reads it.
4
4
 
5
5
  Zero trust means nothing counts as clean because it looks clean: a finding exists only when a mechanism produced it, and it weighs exactly what that mechanism weighs — an exact match is a verdict, a pattern match is a candidate. This is **read-only** like every audit (`agent.B5`): it reports, it does not fix, it never mutates git state. Fixing is a separate run, sized after the report is read.
6
6
 
@@ -22,7 +22,7 @@ Not every decision deserves the same depth. Before applying any module, size the
22
22
 
23
23
  This METHOD is consumed three ways:
24
24
 
25
- - **Passive (this file, via akirule):** akirule auto-loads it when a normal task hits a matching signal. Apply the lenses inline, briefly, inside the current answer. Ask at most ONE clarifying question. Never turn a routine task into an interrogation session.
25
+ - **Passive (this file, via akirule):** the router loads it whenever a task evaluates, decides or critiques rather than only executes. Apply the lenses inline, briefly, inside the current answer. Ask at most ONE clarifying question. Never turn a routine task into an interrogation session.
26
26
  - **Triggered self-run:** fired by `agent.A3`'s deep-think triggers, or by owner-authorized self-run (`skills/akithink/SKILL.md` § Self-run mode). Non-interactive — run Modules 1–3 and 5 (add 4 when there is business context), depth scaled to difficulty. Ends in decide-and-report or escalate per `agent.A3`'s outcomes, never in a question left hanging.
27
27
  - **Active (`/akithink` skill):** the user explicitly opens a full structured thinking session. That skill runs a 5-phase interactive protocol and uses this METHOD as its toolbox at maximum depth.
28
28
 
@@ -36,7 +36,7 @@ Classify every turn before acting: is it **communication** (a question, discussi
36
36
  - **Communication → answer, do not act.** Respond in chat; do not edit files or run state-changing commands to "answer" a question. "Can we X?" / "Should we X?" is a question, not permission to do X. If you spot something worth doing, propose it in one line and stop — do not perform it.
37
37
  - **Task → execute, do not stall.** Do the requested work within scope; do not turn a clear instruction back into a proposal or a needless confirmation prompt. Report when done, then stop.
38
38
  - **Calibrate autonomy by reversibility, not by asking-always.** A reversible, in-scope action gets done and reported; only a genuine one-way door (destructive, outward-facing, scope-expanding, shared config — see B3) is worth pausing to ask. Over-asking on safe work is as much a failure as acting unasked — it trades the user's speed for no real safety.
39
- - **Three kill-tests before any question reaches the user — failing one means answer it yourself and record the answer.** Reversibility (above) is the fourth. **Impact:** if the user answers against your default, does any artifact change? "The conclusion holds either way" is a default to write down, never a question to ask. **Already authorized:** the request may have settled it — asking the user to re-confirm a course they just ordered charges them twice for one decision. **Silence is not contradiction:** a doc that does not mention X does not conflict with X; that is a one-line gap to close, i.e. a work item, not a question. A question dressed as a "decision with a recommendation" still costs a read and an answer — the shape does not exempt it from these tests.
39
+ - **Four kill-tests before any question reaches the user — failing one means answer it yourself and record the answer.** Reversibility (above) is the fifth. **Impact:** if the user answers against your default, does any artifact change? "The conclusion holds either way" is a default to write down, never a question to ask. **Already authorized:** the request may have settled it — asking the user to re-confirm a course they just ordered charges them twice for one decision. **Silence is not contradiction:** a doc that does not mention X does not conflict with X; that is a one-line gap to close, i.e. a work item, not a question. **Self-sufficiency:** before the question leaves, confirm the answer is not already sitting in the three sources you are expected to have exhausted — the rule corpus (`akirule` routes it; the core files are already in context), the deep-think budget (`METHOD-deep-think.md`, run to convergence, not one shallow pass), and the owner's original request read verbatim plus the conversation history. A question those three already answer is amnesia, not a genuine unknown; re-reading them is cheaper than an interrupt and is not optional. This test only redirects a question you could answer yourself — it never overrides the escalation floor below: a real one-way door with outward effect is still asked, no matter how self-sufficient the reasoning feels. A question dressed as a "decision with a recommendation" still costs a read and an answer — the shape does not exempt it from these tests.
40
40
  - **Deep-think trigger (mandatory, self-driven, non-interactive).** When any holds, Read `METHOD-deep-think.md` and run it before acting or asking: (a) about to ask or escalate to the owner; (b) about to take a one-way-door action; (c) the same fix failed a second time, or a third patch lands on one transition (`pattern.B2`); (d) two rules or instructions conflict; (e) the owner's wording admits readings that produce different artifacts; (f) the change touches documented design or goals. Depth scales with difficulty — repeat goal chain → first principles → critique → pre-mortem until the answer converges, never a fixed round count. Trivial reversible work triggers nothing.
41
41
  - **Outcome — converged: act, report the decision.** Self-answer what the analysis settles and act; for important or hard calls report one block — `Decided: X · because Y · rejected Z (why) · reopen if W` — so the owner can overrule after the fact instead of being asked before.
42
42
  - **Outcome — escalate only when:** a one-way door with outward effect (publish, tag, destructive data change); contradiction with documented design (`B3`); the `coding.C4` security/money/auth floor; the owner's own wording is ambiguous AND the readings lead to different irreversible artifacts; or deep-think does not converge (name exactly where it is stuck). What survives is asked in a presentation the user can absorb at a glance: everyday wording, jargon glossed, each option carrying its concrete consequence, plus the analysis and one recommendation. A question the user cannot understand costs two interrupts: one to ask, one to explain the asking.
@@ -58,11 +58,11 @@ A worker is a subagent, or the same or another CLI called headlessly (`claude -p
58
58
 
59
59
  **Route by context need, not by the word “exploration.”** Conversation-dependent synthesis, ambiguous classification, and per-item judgment stay with the caller; delegate only the retrieval that feeds them. Prefer a fresh worker for a precise, context-free digest. Use a fork only when a bounded bulk task genuinely needs substantial accumulated context that would be expensive to restate. A worker never delegates again unless the caller explicitly grants a fan-out with bounded depth and width.
60
60
 
61
- **When delegation is warranted, use the current default wide-context tier available, one shot** — on Antigravity that is `agy --model gemini-3.7-flash-high --mode plan -p "<prompt>"` (prompt last; `-p` swallows the next token; owner-set default, 2026-08-15). It holds a very large context; its failure mode is skimming, so the counter is prompt precision rather than a bigger model: name the exact paths, the exact question, and the exact output shape, and leave it nothing to improvise. Keep it to a single call — multi-turn on that CLI degrades badly.
61
+ **When delegation is warranted, use the cheap wide-context tier the host resolves, one shot** — the literal command, model id and read-only mechanism per host live in one table (`skills/akiflow/references/harness-facts.md` § Model tiers › Host resolution), never in this rule. That tier holds a very large context; its failure mode is skimming, so the counter is prompt precision rather than a bigger model: name the exact paths, the exact question, and the exact output shape, and leave it nothing to improvise. Keep it to a single call — multi-turn on those CLIs degrades badly.
62
62
 
63
63
  **Know which kind of cheap you are buying.** A stateless cheap call is cheap *per call* and must re-receive its context every time. A persistent worker (`claude -p --session-id <uuid>`, later `--resume <uuid>`) is cheap *per turn after the first*, because its prefix is cached — roughly an eighth of the opening turn, then flat — and it keeps everything **it** was told, though nothing the caller knows. Use the first for one wide question, the second for a worker you will come back to. The session id is scoped to the directory it was created in.
64
64
  - **A worker inherits nothing** — not your context, not your rules, not your router. Name the exact rule files it must read and the exact paths or targets it must look at. "Follow the project rules" loads nothing and reads as compliance.
65
- - **Require the return leg — the worker reports what it actually received.** Naming the files is only half the loop: a brief that was ignored, a path that no longer resolves, and a rule read in full all produce output that looks the same. The worker's first line is a receipt — `[RULES] agent,coding (brief) | missing: none` — naming the topic address of every rule file it read and listing anything it was told to read and could not. A worker gets one round, so this is not conditional: with no receipt, a later violation cannot be traced to either the brief or the behavior, and those two have opposite fixes. Format and the session-side duty: `skills/akirule/SKILL.md` § Load confirmation.
65
+ - **Require the return leg — the worker reports what it actually received.** Naming the files is only half the loop: a brief that was ignored, a path that no longer resolves, and a rule read in full all produce output that looks the same. The worker's first line is a receipt — `[RULES] agent,coding (brief)` — naming the topic address of every rule file it read; a file the brief named that is absent from the line was not read. A worker gets one round, so this is not conditional: with no receipt, a later violation cannot be traced to either the brief or the behavior, and those two have opposite fixes. Format and the session-side duty: `skills/akirule/SKILL.md` § Load confirmation.
66
66
  - **Set both dials, every time: model tier and thinking effort.** An omitted parameter does not fall back to something cheap; it silently inherits the caller's own expensive settings. Silence is an expensive choice made by accident.
67
67
  - **Enforce read-only by mechanism, not by wording**, wherever "fixing while I'm here" would be unrecoverable — restrict the worker's tool set, or use the CLI's read-only/plan mode. A prompt-worded ban is one the model can talk itself out of.
68
68
  - **If a program will parse the output, use the structured-output flag** rather than asking for JSON in prose.
@@ -90,6 +90,7 @@ A worker is a subagent, or the same or another CLI called headlessly (`claude -p
90
90
  Ask before:
91
91
  - destructive or hard-to-reverse actions — hard-to-reverse means no backup/restore or fix-forward path exists; an action that has one (e.g. an additive migration with a backup, `stack.C8`) climbs `coding.B5`'s ladder instead of asking
92
92
  - changing deployment, infrastructure, auth, billing, or shared config assumptions
93
+ - any test, benchmark, or trial run that spends paid API credits or session quota
93
94
  - modifying shared rule files, templates, or project-wide conventions
94
95
  - large rewrites or broad renames
95
96
  - actions visible to other people or external services
@@ -49,7 +49,7 @@ A principle with the procedure that guarantees it — apply to any edit of code
49
49
  ### B4. Self-documenting code — comments are a last resort
50
50
  Domain application of the density root (`agent.A4` — every line must carry information the reader does not already have); the naming root is `pattern.A7`. Penalty card: `[YAP]` (`agent` §0).
51
51
  - Naming and shape come first: a comment that explains *what* a block does is a failed name or a failed extraction — fix the name/structure (`pattern.A7`, `pattern.A3`), then delete the comment. Clean flow plus role-named functions and variables need no narration.
52
- - A comment may state only what the code cannot say: a non-obvious constraint, an external contract, a genuine why. Never narrate the next line, restate the signature, or record change history.
52
+ - A comment may state only what the code cannot say: a non-obvious constraint, an external contract, a genuine why. Never narrate the next line, restate the signature, or record change history. What a pinned project doc already states, the code need not say either (`C1`).
53
53
  - Deletion test, per comment: if removing it loses nothing a reader needs beyond what the code already says, remove it. Default is silence — comment density is a smell, not a virtue.
54
54
  - Comments rot: no compiler checks a comment, so it drifts silently as the code under it changes, and a stale comment misleads worse than none — one more reason deletion is the default, and why a rationale that must stay current lives in a doc the code references ([[RULE-docs]] B3), never duplicated inline.
55
55
  - One line when a comment is genuinely needed; a rationale bigger than that lives in docs, with the comment holding only the reference (see [[RULE-docs]] B3).
@@ -79,6 +79,7 @@ None of this weakens `B3`'s honesty floor: what genuinely stays unverified is st
79
79
  ### C1. Error handling
80
80
  - Validate at system boundaries: user input, external APIs, filesystem, network, persistence
81
81
  - Do not add defensive guards for impossible internal states — and size the ones that do guard a reachable state against who can actually reach it (`METHOD-proportionality.md`), instead of adding protection by reflex
82
+ - **Impossible and obvious are judged against the project's pinned facts** — `CLAUDE.md`, `docs/biz`, `docs/feat|arch`, recorded research decisions — never against imagination: a state those documents rule out gets no guard, a dependency they declare present gets no fallback, a fact they state gets no comment (`B4`), and a path they define gets one natural flow, not a patch beside it (`pattern.A8`)
82
83
  - Fail loudly in development when it helps reveal broken assumptions
83
84
  - Keep production failures safe and user-appropriate
84
85
  - **Never fabricate mock/fixture data as a runtime fallback for a missing dependency** (DB, API, service binding). Throw/return a real error instead. If a local dev environment genuinely lacks that dependency, fix the environment itself (real local instance, proper binding/proxy) — don't paper over it with fake data. Verify the dependency is actually unavailable by reading how the runtime/framework wires it in dev before assuming a fallback is needed at all.
@@ -1,6 +1,6 @@
1
1
  # Core Docs Rules
2
2
 
3
- <!-- Address map: docs.A1-4 · docs.B1-3 · docs.C1-4 -->
3
+ <!-- Address map: docs.A1-5 · docs.B1-3 · docs.C1-4 -->
4
4
 
5
5
  ## Goals
6
6
  Docs should be readable for both humans and LLMs.
@@ -51,6 +51,17 @@ Filenames across all `docs/*` never lead with a date — the content-identifying
51
51
 
52
52
  The stamp is what makes drift mechanically visible: a `docs/arch/` file stamped three releases back is a drift-audit lead (C3) before anyone reads a line of it.
53
53
 
54
+ ### A5. The auto-loaded instruction file — `CLAUDE.md` / `AGENTS.md` / `GEMINI.md`
55
+
56
+ The harness prepends this file to every request, so every line in it is paid on every turn and read under every task, related or not. It is the most expensive doc in the project and carries the highest bar: `agent.A4`'s deletion test with a reach condition on top. A line stays only if it passes all five, and the whole file is re-run through them on every edit:
57
+ 1. **Harm** — absent from every request, name the concrete mistake the agent makes. No nameable mistake, no line.
58
+ 2. **Reach** — it governs the majority of requests in this project. A line that matters to one domain belongs in the doc that domain's route loads (`feat/`, `arch/`, `biz/`, a project rule file), not here.
59
+ 3. **Not derivable** — it cannot be read from the code, the manifest (`package.json`, `Cargo.toml`), or a doc the router already loads for that task.
60
+ 4. **Not a restatement** — a shared-corpus rule is pointed at by address (`coding.B3`), never copied; a copy drifts and doubles the cost.
61
+ 5. **Facts and limits, not behavior** — the file binds the project's facts (stack, reference implementation, test and compile command, ship platform, hard limits) and stricter constraints; behavior rules live in the corpus (`index.md` § Precedence). Those bindings are the router's standing signal for every task in the project.
62
+
63
+ One file is the source: a per-project `GEMINI.md` or `AGENTS.md` is a bootstrap that points at `CLAUDE.md`, never a second copy.
64
+
54
65
  ## B. Lifecycle & Sync
55
66
 
56
67
  ### B1. Plan lifecycle & Filename Rules
@@ -62,13 +73,13 @@ The stamp is what makes drift mechanically visible: a `docs/arch/` file stamped
62
73
 
63
74
  ### B2. Research doc structure (`docs/research/`)
64
75
 
65
- A research doc is an **event record** — the reasoning as it stood when written (the current-state vs. history split is defined in A2). Its body is frozen: never rewrite a claim, a number, or a verification status in place, because the record of what was believed is the doc's whole value. What may change after writing, by class:
76
+ A research doc is an **event record** — the reasoning as it stood when written (the current-state vs. history split is defined in A2). Frozen is the default, not a wall: most corrections land **in place** here, and the discriminator is one mechanical read of the **Decision** field — if applying the fix would change Decision, write a successor doc; if not, edit in place (amendment or cosmetic). Refusing to touch a research doc, or spawning a new doc for a fix the Decision survives, is the failure this rule exists to prevent — it inflates the tree and buries the correction. What is actually frozen is narrow: a **claim, number, or verification status that the Decision still rests on** — never rewrite that in place, because the record of what was believed is the doc's whole value; append an amendment instead. Correction classes:
66
77
  - **Cosmetic** (typo, broken link, a path after a rename) — edit in place, no marker.
67
78
  - **Erratum on a claim** — a fact turned out wrong, a number was re-measured, an unverified claim was later verified or contradicted, but the **Decision** field still stands: append a dated entry to a closing `## Amendments` section (`- 2026-08-02 · § R9: verified on kiro-cli 2.16.0; the row above was written unverified`), naming the section it corrects and stating only the corrected fact (no story of finding it — `agent.C2`), and add `Status: amended <date>` under the H1 so a reader is warned before reaching the stale claim. The original text stays.
68
79
  - **Decision changes** — applying the correction would alter the Decision field: create a **new** research doc and add `Status: superseded by <path>` at the top of the old one. Name the chain with a sequential numeric suffix, ADR-style: `db-engine-choice.md` → `db-engine-choice-2.md` → `db-engine-choice-3.md`, each `superseded by` pointing only at its immediate successor so the chain can be walked backward.
69
80
  - **Decision-field links and cross-references** — an Action link to where the result landed, a new cross-ref: edit in place; those fields describe where the event's consequences live, not the event.
70
81
 
71
- The discriminator is mechanical: read the Decision field; if the correction would change it, successor doc, otherwise amendment. Anything outside research that links to a chain (`arch/feat/biz`) points at the latest number and gets updated each time the chain grows — that edit is allowed because those docs hold current state, not history.
82
+ Anything outside research that links to a chain (`arch/feat/biz`) points at the latest number and gets updated each time the chain grows — that edit is allowed because those docs hold current state, not history.
72
83
 
73
84
  Required fields, in order:
74
85
  1. **Start time** — when the research began
@@ -37,7 +37,7 @@ These are constraints on **structure and reuse**, not style. Reach for this file
37
37
  **A7 — Name by role, never by concrete value.** Name things for what they *mean*, not what they *currently are*: `retryLimit` not `three`, `PrimaryAction` not `BlueButton`, `AuthBoundary` not `FirebaseWrapper`. Value-names rot the instant the value changes and force codebase-wide find-and-replace.
38
38
  - *Root rule for naming.* Every other naming item in this corpus (`agent.C1` file names, `ui.A` tokens, `stack.C1` component names, `release.A3` version/tag format, `content` semantic stability) is a **domain application** of A7, not a competing rule — do not restate A7 in them, and do not move them out of their domain. Address map: `index.md` § Cross-cutting lens.
39
39
 
40
- **A8 — One flow, made natural — not guarded.** When the same guard / check / fallback keeps reappearing around a path, the path's shape is wrong. Reshape the flow so the correct behavior is automatic; do not stack more enforcement on a weak path. Full method: `METHOD-audit-flow.md`.
40
+ **A8 — One flow, made natural — not guarded.** When the same guard / check / fallback keeps reappearing around a path, the path's shape is wrong. Reshape the flow so the correct behavior is automatic; do not stack more enforcement on a weak path. "Correct" is measured against the project's pinned facts (`coding.C1`), so a guard for a state those facts rule out is a patch, not a flow. Full method: `METHOD-audit-flow.md`.
41
41
 
42
42
  ---
43
43
 
@@ -169,9 +169,9 @@ The B7 gate plus its surrounding ritual (fix findings → sync docs → CHANGELO
169
169
  - **A valid `/akiship` invocation = standing authorization for every enumerated step.** Explicitly invoking the full run authorizes: fixing gate findings, CHANGELOG/`releases.json` edits, grouped commits (the akigitcommit confirm step is pre-answered — "commit luôn" semantics), the version mint per A4/A5, and tag/GitHub Release strictly per the repo's existing convention (A3, B4). Push and deploy are included only when the invocation names them **or carries a completion-intensity signal** (the same trigger set as the next bullet) — a plain `/akiship` with no intensity marker stays local-only; deploy still additionally requires the stack to auto-deploy on push (owned by the stack rule, not this contract).
170
170
  - **Front-load the asks.** Derive B1 state and run B7 step 0 first; every escalation found is reported once, as one batch, and the run stops there. A clean front check means the run completes with zero mid-run questions — an automation that stalls on a question halfway through has failed this rule.
171
171
  - **Escalation floor (canonical — `/akiship` references this list, never restates it, `pattern.A1`) — stop only for:** (1) public-history ambiguity — cannot determine whether a version actually shipped, or a `Mismatch`/`Drifted` state whose recovery would rewrite published versions (A5, B1); (2) work the tree cannot classify — mid-edit vs abandoned (B7 step 0); (3) contradiction with documented design, or scope beyond what the invocation named ([[RULE-agent-behavior]] B3).
172
- - **Completion-intensity phrasing collapses condition (2) and unlocks push/deploy/GitHub-Release, never conditions (1) or (3).** The canonical phrase list — every other file (the `/akiship` skill, `README.md`) points here (`pattern.A1`): "trọn vẹn", "hoàn thành"/"hoàn thiện", "làm/xong hết", "tất cả"/"toàn bộ", or equivalent sentiment insisting the run finish everything, end to end — read **only inside a valid invocation**, where it modifies a run already authorized to start and never creates that authorization, does two things: resolves B7 step 0's mid-edit-vs-abandoned ambiguity toward **mid-edit by default** (finish and integrate the leftover instead of stopping to ask), and satisfies the previous bullet's push/deploy naming requirement, so the run pushes commits and tags, creates the GitHub Release, and runs post-push CI watch (B10) and deploy verification (C5) without a separate mid-run confirmation. Conditions (1) and (3) gate on irreversibility (a published-version rewrite) and correctness (a documented-design contradiction), not on effort, so no phrasing intensity waives them — a "nghiêm trọng"/major-contradiction hit still stops the run.
172
+ - **Completion-intensity phrasing collapses condition (2) and unlocks push/deploy/GitHub-Release, never conditions (1) or (3).** The canonical definition — every other file (the `/akiship` skill, `README.md`) points here (`pattern.A1`): wording in any language that insists the run finish everything, end to end — read **only inside a valid invocation**, where it modifies a run already authorized to start and never creates that authorization, does two things: resolves B7 step 0's mid-edit-vs-abandoned ambiguity toward **mid-edit by default** (finish and integrate the leftover instead of stopping to ask), and satisfies the previous bullet's push/deploy naming requirement, so the run pushes commits and tags, creates the GitHub Release, and runs post-push CI watch (B10) and deploy verification (C5) without a separate mid-run confirmation. Conditions (1) and (3) gate on irreversibility (a published-version rewrite) and correctness (a documented-design contradiction), not on effort, so no phrasing intensity waives them — a "nghiêm trọng"/major-contradiction hit still stops the run.
173
173
  - **A question the repo already answers is a violation.** Anything determined by the repo, its docs, these rules, or the invocation itself — bump level (A4), tag or no tag (existing convention), changelog channel and tone (C1) — is self-answered, never asked — and every remaining candidate question runs through `agent.A3`'s kill-tests first. Over-asking inside an authorized run is the same failure as acting unasked (`agent.A3`, `think.B5`).
174
- - **A criterion stated in the owner's own words — what "trọn vẹn" must include, which leftovers count as debt versus future plan — is resolved, not escalated by default.** Derive the default from the anchor wording plus the repo's own records (plans, task notes, CHANGELOG), decide, and list each such call in the report's `agent.A3` decision block (`Decided: X · because Y · rejected Z (why) · reopen if W`) so the owner can overrule after the fact. Ask mid-run only when the competing readings would produce different irreversible artifacts (a published tag, a minted version, a registry publish) — `agent.A3`'s escalation, not a default reflex on ambiguous wording.
174
+ - **A criterion stated in the owner's own words — what "complete" must include, which leftovers count as debt versus future plan — is resolved, not escalated by default.** Derive the default from the anchor wording plus the repo's own records (plans, task notes, CHANGELOG), decide, and list each such call in the report's `agent.A3` decision block (`Decided: X · because Y · rejected Z (why) · reopen if W`) so the owner can overrule after the fact. Ask mid-run only when the competing readings would produce different irreversible artifacts (a published tag, a minted version, a registry publish) — `agent.A3`'s escalation, not a default reflex on ambiguous wording.
175
175
 
176
176
  ### B9. Registry-published package (npm, crates.io, PyPI, …) — the registry version is the release
177
177
 
@@ -106,7 +106,7 @@ Invariant: a `:hover`-shown popup/menu/tooltip stays open while the pointer trav
106
106
 
107
107
  ## C. Audit playbook — cleaning existing code
108
108
 
109
- **Triggers for this section:** `dọn dẹp`, `class trùng`, `duplicate class/CSS`, `trùng lặp`, `audit CSS`, `refactor CSS/UI`, `arbitrary value`, `quét class`. Pair with `METHOD-audit-flow.md` for the flow-level mindset; this section is the concrete UI grep layer. Run the steps in order — do not skip.
109
+ **Triggers for this section:** any request to clean up, deduplicate, audit or refactor classes, tokens or styles. Pair with `METHOD-audit-flow.md` for the flow-level mindset; this section is the concrete UI grep layer. Run the steps in order — do not skip.
110
110
 
111
111
  ### C1. Inventory by scan (quantify before refactoring by feel)
112
112
 
package/payload/index.md CHANGED
@@ -12,13 +12,13 @@ Provides reusable rules for agent behavior, coding, content, docs, and stack-spe
12
12
  | `RULE-agent-behavior.md` | `agent` | Core — `@` import in `~/.claude/CLAUDE.md` | public | Core: full text already in context every turn — read it directly, not this summary |
13
13
  | `RULE-coding.md` | `coding` | Core — `@` import in `~/.claude/CLAUDE.md` | public | Core: full text already in context every turn — read it directly, not this summary |
14
14
  | `RULE-pattern-core.md` | `pattern` | Core — `@` import in `~/.claude/CLAUDE.md` | public | Core: full text already in context every turn — read it directly, not this summary |
15
- | `RULE-docs.md` | `docs` | Contextual | public | Docs structure (incl. mandatory `docs/biz/` backbone), `updated <date> <version>` anchor stamp on every `arch|biz|feat` doc, plan lifecycle, research doc schema (event record: start time/purpose/strategy/checklist/result+verification/decision+cross-refs; frozen body, dated `## Amendments` for errata, successor doc only when the Decision changes), doc-sync behavior, drift audit (when it runs vs the two situations it does not, research+plan doc pair, comparison checklist, wrong/stale/incomplete/cosmetic severity) |
15
+ | `RULE-docs.md` | `docs` | Contextual | public | Docs structure (incl. mandatory `docs/biz/` backbone), `updated <date> <version>` anchor stamp on every `arch|biz|feat` doc, the auto-loaded instruction file's five-test admission bar (`A5`: nameable harm, majority-of-requests reach, not derivable, not a restatement, facts not behavior), plan lifecycle, research doc schema (event record: start time/purpose/strategy/checklist/result+verification/decision+cross-refs; frozen body, dated `## Amendments` for errata, successor doc only when the Decision changes), doc-sync behavior, drift audit (when it runs vs the two situations it does not, research+plan doc pair, comparison checklist, wrong/stale/incomplete/cosmetic severity) |
16
16
  | `RULE-content-write.md` | `content` | Contextual | public | UI copy, semantic stability, writing style (density enforced by deletion test), i18n, content audit (`content.C2` — canonical-term drift, density deletion test, i18n coverage, severity-classified per `docs.C4`) |
17
17
  | `RULE-stack-akiNuxtCf.md` | `stack` | Contextual | **mixed** — group C is ⟨Aki⟩ | Nuxt/Vue/Cloudflare Pages/Workers, Tailwind, i18n, canonical component names, state (useState-first), build & TypeScript, admin layout isolation, dev workflow scripts (killport/D1), layout chrome (breadcrumb/scroll-to-top), layout width (single source of truth in the layout, pages/apps never redeclare max-w), deploy verification after push |
18
18
  | `RULE-stack-tauri.md` | `tauri` | Contextual | public | Tauri v2 + Rust: absolute never-block-the-UI rule for any command running a subprocess/network call (`spawn_blocking`), titlebar boundary, version SSOT, IPC capability silent-fail, serde default for persisted JSON, cfg(target_os) scoping, subprocess PATH-resolution cold-start race, salient target context (ship platform) surfaced in the project CLAUDE.md, macOS TCC/Gatekeeper boundary for spawned sidecars (responsible-process attribution, FDA vs Files & Folders vs Developer Tools, sticky denials, ad-hoc signing losing grants on every rebuild, and the read-only scope limit of the whole chain) |
19
19
  | `RULE-ui-pattern.md` | `ui` | Contextual | public | Frontend enforcement of pattern-core: subtraction pass before any tier (delete/inherit/hoist — the ladder packages repetition, only this removes it), 4-tier class taxonomy with the second copy as the STOP (the ≥3 threshold is repo-wide and unobservable inside one file), inline `style=` as a runtime-only escape hatch, `<style>`-block budget measured in aggregate against the shared layer, design tokens in whichever mechanism the installed framework version uses with one theme source per project, arbitrary-value policy, atomic structure, variant API, two-way lookup-then-record pattern duty, UI audit/refactor playbook led by the inversion check |
20
20
  | `RULE-seo.md` | `seo` | Contextual | **mixed** — group C is ⟨Aki⟩ | Meta limits, schema.org matrix, robots, sitemap, OG, AI visibility, entity linking |
21
- | `RULE-release.md` | `release` | Contextual | **mixed** — group C is ⟨Aki⟩ | CHANGELOG.md mandatory in every project, release notes vs changelog split, GitHub Release compare-link footer, releases.json (web-only), release vs deploy boundary, cold-start version reconstruction, severity-driven bump, version minted only at the release event (`[Unreleased]` buffer, no local drift ahead of production), audit mode, pre-ship gate expanded into the full-release checklist (B7: leftover triage, diff-scoped hygiene, build & test mirroring CI as a mandatory step before verification honesty and the version decision), autonomous-run contract (B8: an explicit release order is the authorization — activation owned by akiship's own gate, this rule is never itself a trigger; asks front-loaded into one batch, three-case escalation floor and completion-intensity phrase list owned solely by B8, owner-worded criteria decided and reported rather than escalated by default; entry point `/akiship`), registry-published packages (B9: the registry version is the release, publish mechanism derived from existing convention and sibling packages, account/scope/2FA probed, OTP publish as the single hand-off, tarball verified before the irreversible publish), post-push CI watch (B10: a push or tag push is not Done until every triggered workflow is green, red fixed forward with a new commit never a history rewrite), migration doctrine (B5: detect by effect including startup-embedded code, separate artifact, expand → migrate → deploy → contract, rehearse from the PREVIOUS state never from empty, postconditions + named rollback), fail-closed gate contract (B7: a receipt line per step or the step was NOT RUN, self-interrogation reported, forbidden evidence words), post-deploy functional verification (B11: a version string proves code not function, a constant-`ok` health endpoint is a false instrument) |
21
+ | `RULE-release.md` | `release` | Contextual | **mixed** — group C is ⟨Aki⟩ | CHANGELOG.md mandatory in every project, release notes vs changelog split, GitHub Release compare-link footer, releases.json (web-only), release vs deploy boundary, cold-start version reconstruction, severity-driven bump, version minted only at the release event (`[Unreleased]` buffer, no local drift ahead of production), audit mode, pre-ship gate expanded into the full-release checklist (B7: leftover triage, diff-scoped hygiene, build & test mirroring CI as a mandatory step before verification honesty and the version decision), autonomous-run contract (B8: an explicit release order is the authorization — activation owned by akiship's own gate, this rule is never itself a trigger; asks front-loaded into one batch, three-case escalation floor and completion-intensity definition owned solely by B8, owner-worded criteria decided and reported rather than escalated by default; entry point `/akiship`), registry-published packages (B9: the registry version is the release, publish mechanism derived from existing convention and sibling packages, account/scope/2FA probed, OTP publish as the single hand-off, tarball verified before the irreversible publish), post-push CI watch (B10: a push or tag push is not Done until every triggered workflow is green, red fixed forward with a new commit never a history rewrite), migration doctrine (B5: detect by effect including startup-embedded code, separate artifact, expand → migrate → deploy → contract, rehearse from the PREVIOUS state never from empty, postconditions + named rollback), fail-closed gate contract (B7: a receipt line per step or the step was NOT RUN, self-interrogation reported, forbidden evidence words), post-deploy functional verification (B11: a version string proves code not function, a constant-`ok` health endpoint is a false instrument) |
22
22
  | `RULE-db-design.md` | `db` | Contextual | public | Immutability & Event Sourcing, 1NF, Bounded Context (DDD), flat-query discipline — load when designing schema/migration/DB refactor |
23
23
  | `RULE-biz.md` | `biz` | Contextual | public | Positioning & audience (one primary audience, falsifiable USP, `docs/biz/` as SSoT, niche-first), offer & pricing (value-based, few tiers, validate before building), messaging & customer psychology (benefit-first, anxiety at decision points, no dark patterns) — load on any market-facing decision |
24
24
  | `METHOD-audit-flow.md` | `flow` | Analytical | public | Flow integrity audit method |
@@ -27,14 +27,15 @@ Provides reusable rules for agent behavior, coding, content, docs, and stack-spe
27
27
  | `METHOD-audit-zero-trust.md` | `zero-trust` | Analytical | public | Strict mechanical-first audit: scope locked by command (project-wide or change-plus-callers), detectors run before any opinion, findings split into CERTAIN (exact machine match — a verdict) vs SUGGESTED (pattern/naming — a candidate judgment must settle), signature propagation across the locked scope, short findings-only report. Read-only like every audit |
28
28
  | `METHOD-proportionality.md` | `proportion` | Analytical | public | Sizing a defense against its real threat: four measures before any verdict (reach against the `docs/biz/` audience, capability ladder, motive, blast radius by recoverability), every number labeled measured or estimated; asymmetry law (irreversibility outranks frequency), the `coding.C4`/`biz.C3` floor that is never sizeable, the cheapest-sufficient-control ladder (impossible by shape → one trust boundary → detect → accept-and-record) with client-side limits classified as UX and never enforcement; verdict record carries a reopen trigger. Seated in akiflow as `risk-sizing` |
29
29
  | `METHOD-audit-subtraction.md` | `subtract` | Analytical | public | Repo-wide "does this need to exist" sweep: inherits zero-trust's scope-lock, detector-first order, CERTAIN/SUGGESTED classes and signature propagation, changes only the question. Loop-until-dry termination (two empty rounds) because no detector returns "minimal", nine domain passes each delegating detectors to the rule that owns them, subtraction severity classes including the mandatory *load-bearing but ugly* class, Chesterton's Fence as the brake before any CERTAIN removal. Read-only; bulk sweeps route to workers, judgment does not |
30
+ | `METHOD-audit-frozen-reference.md` | `frozen-ref` | Analytical | public | Compliance audit for a clause that names a concrete external artifact as the canonical shape to match (a pinned version, a byte-identical component, a frozen page layout) — never judged from memory of the rule's prose. Resolve the reference to an exact path before judging (§A); when more than one reference implementation exists, read at least two, since a single reference can itself have drifted from the written rule; a comparison table is built one literal unit per row (a function name, a config key, a flow step) with `path:line` on both sides and a verdict of MATCH/RENAMED/MISSING/EXTRA/STRUCTURAL-DIFF — never softened to "acceptable variance" inside the audit (§B); standard-vs-practice gaps (the rule and its own reference disagree) are reported separately from target defects (§C). Inherits zero-trust's evidence discipline and read-only floor |
30
31
 
31
- Four files load mechanically, not by routing: this `index.md`, `RULE-agent-behavior.md`, `RULE-coding.md` and `RULE-pattern-core.md` are `@`-imported by `~/.claude/CLAUDE.md`, which the harness reads at session start. Routing for every other file is defined in `~/.claude/skills/akirule/SKILL.md` and takes effect only when the model invokes that skill.
32
+ Five files load mechanically, not by routing: this `index.md`, `RULE-agent-behavior.md`, `RULE-coding.md`, `RULE-pattern-core.md` and the router `~/.claude/skills/akirule/SKILL.md` are `@`-imported by `~/.claude/CLAUDE.md`, which the harness reads at session start. Every other file is routed by meaning — the domain a task touches, with concept signals as evidence, never as the test — and enters context when the model `Read`s it on a route match.
32
33
 
33
- The two rule files were promoted out of Tier 1 because "default ON" was a description of intent, not a mechanism: a router that runs only when the model chooses to invoke it cannot guarantee anything, and the rules the owner had to re-state most often (`coding.B4` comment budget, `pattern.A2` Rule of Three, `pattern.A8` fix-at-the-root) turned out to be missing from the context rather than present and ignored. A rule that must hold unconditionally belongs in an `@` import; anything left to the router is best-effort by construction. The cost — both files in every session, including sessions that touch no code — is the price of that guarantee and was accepted knowingly.
34
+ The two rule files were promoted out of the router because "default ON" was a description of intent, not a mechanism: a router that runs only when the model chooses to invoke it cannot guarantee anything, and the rules the owner had to re-state most often (`coding.B4` comment budget, `pattern.A2` Rule of Three, `pattern.A8` fix-at-the-root) turned out to be missing from the context rather than present and ignored. A rule that must hold unconditionally belongs in an `@` import. The router followed for the same reason: as a skill it went uninvoked until the owner asked by name, so the routing itself is now imported and only the second hop — the `Read` of a routed file — stays model-dependent. The cost — both files in every session, including sessions that touch no code — is the price of that guarantee and was accepted knowingly.
34
35
 
35
36
  ## Addressing scheme — `topic.A1`
36
37
 
37
- Every file is internally organized into groups **A/B/C** (a topic's broad themes) and numbered items **1/2/3…** within each group — e.g. `coding.B2` (Changing existing code), `stack.C1` (Canonical component names). `topic` is the manifest's Topic column above — usually the filename with its `RULE-`/`METHOD-` prefix dropped; the audit methods keep their short topics (`flow`, `zero-trust`, `subtract`). This is purely a recall/reference convention — it does not change routing (still governed by `akirule/SKILL.md`) and does not rename any file.
38
+ Every file is internally organized into groups **A/B/C** (a topic's broad themes) and numbered items **1/2/3…** within each group — e.g. `coding.B2` (Changing existing code), `stack.C1` (Canonical component names). `topic` is the manifest's Topic column above — usually the filename with its `RULE-`/`METHOD-` prefix dropped; the audit methods keep their short topics (`flow`, `zero-trust`, `subtract`, `frozen-ref`). This is purely a recall/reference convention — it does not change routing (still governed by `akirule/SKILL.md`) and does not rename any file.
38
39
 
39
40
  **`⟨Aki⟩`** marks a group (always the last group in its file) that is specific to Aki's own AkiNuxtCf ecosystem rather than universal — currently `seo.C`, `release.C`, `stack.C`. These groups stay in this public repo (auto-load is more useful to Aki, the heaviest user, than a clean public/ private split), but are logically separable if a stripped public export is ever needed. Everything outside a `⟨Aki⟩` group is universal and applies to any project on the matching stack.
40
41
 
@@ -58,6 +59,7 @@ Every file is internally organized into groups **A/B/C** (a topic's broad themes
58
59
  | `zero-trust` | A Scope-lock · B Mechanical pass first · C Evidence classes · D Signature propagation · E Adversarial self-challenge · F Report |
59
60
  | `proportion` | A Dimensioning · B Verdict · C Output & reuse |
60
61
  | `subtract` | A Scope & terminating condition · B The passes · C Output · D Runner |
62
+ | `frozen-ref` | A Locate every reference · B Build the comparison mechanically · C Report |
61
63
 
62
64
  Full item-level breakdown: `docs/research/public-private-abc-restructure.md`.
63
65
 
@@ -71,11 +73,13 @@ Some subjects legitimately live in several files: one **root rule** stating the
71
73
  | **External-action completeness** ("done" needs the outside world to move, not just the file) | `coding.B3` — a change requiring a separate action against an external system isn't done when the file describing it is written | `release.B5` ⟨Aki⟩ CHANGELOG/release entry not truthful until a migration/infra step actually ran · `stack.C8` ⟨Aki⟩ D1 migration must run `--remote` and move to `scripts/done/`, a green build alone proves nothing about the database · `release.B10` a push or tag push is not Done until every triggered CI workflow is confirmed green · `release.B11` a deploy is not Done until a data path the release touched is exercised, not only the version |
72
74
  | **Audit reports, never fixes** (and the output depends on whether the baseline is stable) | `agent.B5` — an audit writes only its report; never mutates git state, never auto-classifies ambiguous work | `docs.C` docs-vs-reality, research+plan doc pair on a published baseline · `content.C2` canonical-term drift, density deletion test, i18n coverage sweeps · `release.B7` pre-ship pass/fail gate, no doc · `ui.C` class/token audit playbook · `flow` flow and state drift · `zero-trust` mechanical-first strict sweep, evidence weighted by the mechanism that produced it · `subtract` repo-wide does-this-need-to-exist sweep, terminating on two dry rounds |
73
75
  | **Sizing a control against its real threat** (severity is impact **and** who can actually reach it) | `proportion.A` — reach, capability, motive, blast radius, each labeled measured or estimated, before any guard is added, kept, or removed | `coding.C1` no defensive guards for impossible internal states · `coding.C4` the security floor this sizing never argues below · `pattern.A2` risk-weighted extraction at the 2nd occurrence for auth/money/permissions · `think.A1` one-way vs two-way door depth · `think.B5` when an edge-case is promoted above the MVP · `ux.C1` findings ranked by severity, never padded flat |
74
- | **Density — the deletion test** (a line exists only if deleting it loses information the reader needs) | `agent.A4` — report density: conclusion-first, no padding, no trimming of load-bearing detail | `coding.B4` code comments (naming first; comment only what code cannot say) · `docs.B3` doc prose · `content.B2` product copy · akiflow Step 4 output-hygiene floor (the enforcement tier for subagents, which inherit no router) · mechanical detection: `skills/akiflow/scripts/scythe.py` (`[WRAP]`/`[YAP]` only — `[FLUFF]` stays judgment, `agent` §0) |
76
+ | **Density — the deletion test** (a line exists only if deleting it loses information the reader needs) | `agent.A4` — report density: conclusion-first, no padding, no trimming of load-bearing detail | `coding.B4` code comments (naming first; comment only what code cannot say) · `docs.B3` doc prose · `docs.A5` the auto-loaded instruction file (deletion test plus a majority-of-requests reach bar, since every line is paid on every request) · `content.B2` product copy · akiflow Step 4 output-hygiene floor (the enforcement tier for subagents, which inherit no router) · mechanical detection: `skills/akiflow/scripts/scythe.py` (`[WRAP]`/`[YAP]` only — `[FLUFF]` stays judgment, `agent` §0) |
75
77
  | **Subtraction before abstraction** (packaging repetition is second-best; not needing it is first) | `think.B4` — what can be deleted, skipped, merged, delayed, or made manual | `pattern.B3` first bullet of the critique gate · `ui.A1` delete/inherit/hoist pass ahead of the tier ladder · `subtract` the repo-wide audit form of the same question, read-only and detector-driven · akiflow's `aki-challenger`, which closes every solution-shaped item on "what can be cut?" |
76
78
  | **Interrupting the owner** (a question must survive the kill-tests before it costs a read and an answer) | `agent.A3` — impact, already-authorized, silence≠contradiction, reversibility as the fourth, plus escalation outcomes and a `Decided: X · because Y · rejected Z (why) · reopen if W` decision block for what does get self-answered | `coding.B3` one human hand-off ledger per run, deduped by flow · `coding.B5` the six-rung ladder a check must fail before it may be handed to the owner at all, and the one-line reason each survivor carries · `release.B8` a question the repo already answers is a violation; owner-worded criteria decided and reported, escalated only when readings diverge on an irreversible artifact · akiflow Step 4 seat-raised `CONFLICT` filtered through the lead's kill-test pass |
77
79
 
78
- Add a lens row only when a subject has actually caused a miss — `pattern.A2` (Rule of Three) applies to this rule corpus too, and so did a real production incident where a migration script shipped in CHANGELOG but was never executed against remote D1 (2026-07-23).
80
+ | **Literal parity with a frozen external artifact** (a clause claiming byte/structural identity with a named reference is not satisfied by "looks compliant") | `frozen-ref.A` — resolve the reference to an exact path before judging; read ≥2 implementations when more than one exists, since one reference can itself have drifted | `stack.C1` ⟨Aki⟩ canonical component names — the naming half of this problem · `pattern.A7` root naming rule that frozen-reference structural clauses do not override · `zero-trust.C` evidence-class discipline this method inherits |
81
+
82
+ Add a lens row only when a subject has actually caused a miss — `pattern.A2` (Rule of Three) applies to this rule corpus too, and so did a real production incident where a migration script shipped in CHANGELOG but was never executed against remote D1 (2026-07-23). The `frozen-ref` row above was added after a private project spent over ten audit sessions re-discovering the same structural drift against its own frozen reference each time, because compliance was judged from the rule's prose instead of a literal diff against the reference file.
79
83
 
80
84
  ## Precedence
81
85
  When rules conflict, use this order:
@@ -11,7 +11,7 @@ description: >-
11
11
 
12
12
  # aki-article-writer
13
13
 
14
- Invoke with `/aki-article-writer` or by natural language: *"write an article about X"*, *"viết bài về X"*.
14
+ Invoke with `/aki-article-writer`, or whenever the user asks in any wording for an article to be written.
15
15
 
16
16
  This skill delegates one full article to a dedicated **Article Worker subagent**. The worker spawns a separate **Image Scout subagent** (lightweight model) for all image work, keeping both agents' contexts clean and independent.
17
17